Skip to main content

wreq_util/emulate/profile/
okhttp.rs

1use super::*;
2
3const CURVES: &str = join!(":", "X25519", "P-256", "P-384");
4
5const SIGALGS_LIST: &str = join!(
6    ":",
7    "ecdsa_secp256r1_sha256",
8    "rsa_pss_rsae_sha256",
9    "rsa_pkcs1_sha256",
10    "ecdsa_secp384r1_sha384",
11    "rsa_pss_rsae_sha384",
12    "rsa_pkcs1_sha384",
13    "rsa_pss_rsae_sha512",
14    "rsa_pkcs1_sha512",
15    "rsa_pkcs1_sha1"
16);
17
18const CIPHER_LIST: &str = join!(
19    ":",
20    "TLS_AES_128_GCM_SHA256",
21    "TLS_AES_256_GCM_SHA384",
22    "TLS_CHACHA20_POLY1305_SHA256",
23    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
24    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
25    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
26    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
27    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
28    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
29    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
30    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
31    "TLS_RSA_WITH_AES_128_GCM_SHA256",
32    "TLS_RSA_WITH_AES_256_GCM_SHA384",
33    "TLS_RSA_WITH_AES_128_CBC_SHA",
34    "TLS_RSA_WITH_AES_256_CBC_SHA",
35    "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
36);
37
38#[derive(TypedBuilder)]
39struct OkHttpTlsConfig {
40    #[builder(default = CURVES)]
41    curves: &'static str,
42
43    #[builder(default = SIGALGS_LIST)]
44    sigalgs_list: &'static str,
45
46    cipher_list: &'static str,
47}
48
49impl From<OkHttpTlsConfig> for TlsOptions {
50    fn from(val: OkHttpTlsConfig) -> Self {
51        TlsOptions::builder()
52            .enable_ocsp_stapling(true)
53            .curves_list(val.curves)
54            .sigalgs_list(val.sigalgs_list)
55            .cipher_list(val.cipher_list)
56            .min_tls_version(TlsVersion::TLS_1_2)
57            .max_tls_version(TlsVersion::TLS_1_3)
58            .aes_hw_override(true)
59            .build()
60    }
61}
62
63macro_rules! mod_generator {
64    ($mod_name:ident, $cipher:expr, $ua:expr) => {
65        pub(crate) mod $mod_name {
66            use super::*;
67
68            pub fn emulation(emulation: Emulation) -> wreq::Emulation {
69                build_emulation(stringify!($mod_name), emulation, $cipher, $ua)
70            }
71        }
72    };
73}
74
75fn build_emulation(
76    group: &'static str,
77    emulation: Emulation,
78    cipher_list: &'static str,
79    user_agent: &'static str,
80) -> wreq::Emulation {
81    let tls_options = OkHttpTlsConfig::builder()
82        .cipher_list(cipher_list)
83        .build()
84        .into();
85
86    let http2_options = emulation.http2.then(|| {
87        let settings_order = SettingsOrder::builder()
88            .extend([
89                SettingId::HeaderTableSize,
90                SettingId::EnablePush,
91                SettingId::MaxConcurrentStreams,
92                SettingId::InitialWindowSize,
93                SettingId::MaxFrameSize,
94                SettingId::MaxHeaderListSize,
95                SettingId::EnableConnectProtocol,
96                SettingId::NoRfc7540Priorities,
97            ])
98            .build();
99
100        Http2Options::builder()
101            .initial_window_size(16777216)
102            .initial_connection_window_size(16777216)
103            .headers_pseudo_order(
104                PseudoOrder::builder()
105                    .extend([
106                        PseudoId::Method,
107                        PseudoId::Path,
108                        PseudoId::Authority,
109                        PseudoId::Scheme,
110                    ])
111                    .build(),
112            )
113            .settings_order(settings_order)
114            .build()
115    });
116
117    let headers = emulation.headers.then(|| {
118        let mut headers = HeaderMap::new();
119        headers.insert(ACCEPT, HeaderValue::from_static("*/*"));
120        headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.9"));
121        headers.insert(USER_AGENT, HeaderValue::from_static(user_agent));
122        #[cfg(feature = "emulation-compression")]
123        headers.insert(ACCEPT_ENCODING, HeaderValue::from_static("gzip"));
124        headers
125    });
126
127    build_standard_emulation(group, tls_options, http2_options, headers)
128}
129
130mod_generator!(
131    okhttp3_9,
132    join!(
133        ":",
134        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
135        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
136        "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
137        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
138        "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
139        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
140        "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
141        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
142        "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
143        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
144        "TLS_RSA_WITH_AES_128_GCM_SHA256",
145        "TLS_RSA_WITH_AES_256_GCM_SHA384",
146        "TLS_RSA_WITH_AES_128_CBC_SHA",
147        "TLS_RSA_WITH_AES_256_CBC_SHA",
148        "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
149    ),
150    "MaiMemo/4.4.50_639 okhttp/3.9 Android/5.0 Channel/WanDouJia Device/alps+M8+Emulator (armeabi-v7a) Screen/4.44 Resolution/480x800 DId/aa6cde19def3806806d5374c4e5fd617 RAM/0.94 ROM/4.91 Theme/Day"
151);
152
153mod_generator!(
154    okhttp3_11,
155    join!(
156        ":",
157        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
158        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
159        "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
160        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
161        "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
162        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
163        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
164        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
165        "TLS_RSA_WITH_AES_128_GCM_SHA256",
166        "TLS_RSA_WITH_AES_256_GCM_SHA384",
167        "TLS_RSA_WITH_AES_128_CBC_SHA",
168        "TLS_RSA_WITH_AES_256_CBC_SHA",
169        "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
170    ),
171    "NRC Audio/2.0.6 (nl.nrc.audio; build:36; Android 12; Sdk:31; Manufacturer:motorola; Model: moto g72) OkHttp/3.11.0"
172);
173
174mod_generator!(
175    okhttp3_13,
176    join!(
177        ":",
178        "TLS_AES_128_GCM_SHA256",
179        "TLS_AES_256_GCM_SHA384",
180        "TLS_CHACHA20_POLY1305_SHA256",
181        "TLS_AES_128_CCM_SHA256",
182        "TLS_AES_256_CCM_8_SHA256",
183        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
184        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
185        "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
186        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
187        "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
188        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
189        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
190        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
191        "TLS_RSA_WITH_AES_128_GCM_SHA256",
192        "TLS_RSA_WITH_AES_256_GCM_SHA384",
193        "TLS_RSA_WITH_AES_128_CBC_SHA",
194        "TLS_RSA_WITH_AES_256_CBC_SHA",
195        "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
196    ),
197    "GM-Android/6.112.2 (240590300; M:Google Pixel 7a; O:34; D:2b045e03986fa6dc) ObsoleteUrlFactory/1.0 OkHttp/3.13.0"
198);
199
200mod_generator!(
201    okhttp3_14,
202    CIPHER_LIST,
203    "DS podcast/2.0.1 (be.standaard.audio; build:9; Android 11; Sdk:30; Manufacturer:samsung; Model: SM-A405FN) OkHttp/3.14.0"
204);
205
206mod_generator!(
207    okhttp4_10,
208    CIPHER_LIST,
209    "GM-Android/6.112.2 (240590300; M:samsung SM-G781U1; O:33; D:edb34792871638d8) ObsoleteUrlFactory/1.0 OkHttp/4.10.0"
210);
211
212mod_generator!(
213    okhttp4_9,
214    join!(
215        ":",
216        "TLS_AES_128_GCM_SHA256",
217        "TLS_AES_256_GCM_SHA384",
218        "TLS_CHACHA20_POLY1305_SHA256",
219        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
220        "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
221        "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
222        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
223        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
224        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
225        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
226        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
227        "TLS_RSA_WITH_AES_128_GCM_SHA256",
228        "TLS_RSA_WITH_AES_256_GCM_SHA384",
229        "TLS_RSA_WITH_AES_128_CBC_SHA",
230        "TLS_RSA_WITH_AES_256_CBC_SHA"
231    ),
232    "GM-Android/6.111.1 (240460200; M:motorola moto g power (2021); O:30; D:76ba9f6628d198c8) ObsoleteUrlFactory/1.0 OkHttp/4.9"
233);
234
235mod_generator!(okhttp4_12, CIPHER_LIST, "okhttp/4.12.0");
236
237mod_generator!(
238    okhttp5,
239    CIPHER_LIST,
240    "NRC Audio/2.0.6 (nl.nrc.audio; build:36; Android 14; Sdk:34; Manufacturer:OnePlus; Model: CPH2609) OkHttp/5.0.0-alpha2"
241);