tunnelfetch 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +617 -0
  3. package/README.zh-CN.md +470 -0
  4. package/package.json +74 -0
  5. package/src/client/cookies.js +429 -0
  6. package/src/client/decode.js +346 -0
  7. package/src/client/redirect.js +249 -0
  8. package/src/client.js +704 -0
  9. package/src/errors.js +181 -0
  10. package/src/http1/chunked.js +289 -0
  11. package/src/http1/index.js +10 -0
  12. package/src/http1/request.js +143 -0
  13. package/src/http1/response.js +493 -0
  14. package/src/http2/connection.js +1170 -0
  15. package/src/http2/constants.js +129 -0
  16. package/src/http2/frames.js +291 -0
  17. package/src/http2/hpack.js +420 -0
  18. package/src/http2/huffman.js +203 -0
  19. package/src/http2/index.js +21 -0
  20. package/src/index.js +46 -0
  21. package/src/pool.js +256 -0
  22. package/src/proxy/direct.js +62 -0
  23. package/src/proxy/http-connect.js +206 -0
  24. package/src/proxy/index.js +197 -0
  25. package/src/proxy/socks5.js +344 -0
  26. package/src/tls/aead.js +263 -0
  27. package/src/tls/connect.js +407 -0
  28. package/src/tls/constants.js +334 -0
  29. package/src/tls/extensions.js +376 -0
  30. package/src/tls/handshake-messages.js +901 -0
  31. package/src/tls/handshake.js +568 -0
  32. package/src/tls/handshake12.js +507 -0
  33. package/src/tls/index.js +44 -0
  34. package/src/tls/keyschedule.js +473 -0
  35. package/src/tls/record.js +872 -0
  36. package/src/tls/tickets.js +145 -0
  37. package/src/tls/transcript.js +101 -0
  38. package/src/tls/wire.js +224 -0
  39. package/src/transport.js +296 -0
  40. package/src/trust/der.js +551 -0
  41. package/src/trust/index.js +375 -0
  42. package/src/trust/name.js +235 -0
  43. package/src/trust/ocsp.js +759 -0
  44. package/src/trust/path.js +595 -0
  45. package/src/trust/roots.js +454 -0
  46. package/src/trust/x509.js +902 -0
  47. package/src/util/bytes.js +470 -0
  48. package/src/util/deadline.js +266 -0
  49. package/src/warmup-fixture.js +85 -0
  50. package/src/warmup.js +243 -0
  51. package/types/client/cookies.d.ts +159 -0
  52. package/types/client/decode.d.ts +54 -0
  53. package/types/client/redirect.d.ts +96 -0
  54. package/types/client.d.ts +323 -0
  55. package/types/errors.d.ts +141 -0
  56. package/types/http1/chunked.d.ts +48 -0
  57. package/types/http1/index.d.ts +3 -0
  58. package/types/http1/request.d.ts +44 -0
  59. package/types/http1/response.d.ts +183 -0
  60. package/types/http2/connection.d.ts +282 -0
  61. package/types/http2/constants.d.ts +95 -0
  62. package/types/http2/frames.d.ts +116 -0
  63. package/types/http2/hpack.d.ts +99 -0
  64. package/types/http2/huffman.d.ts +21 -0
  65. package/types/http2/index.d.ts +5 -0
  66. package/types/index.d.ts +17 -0
  67. package/types/pool.d.ts +135 -0
  68. package/types/proxy/direct.d.ts +26 -0
  69. package/types/proxy/http-connect.d.ts +37 -0
  70. package/types/proxy/index.d.ts +62 -0
  71. package/types/proxy/socks5.d.ts +47 -0
  72. package/types/tls/aead.d.ts +67 -0
  73. package/types/tls/connect.d.ts +280 -0
  74. package/types/tls/constants.d.ts +275 -0
  75. package/types/tls/extensions.d.ts +195 -0
  76. package/types/tls/handshake-messages.d.ts +430 -0
  77. package/types/tls/handshake.d.ts +90 -0
  78. package/types/tls/handshake12.d.ts +35 -0
  79. package/types/tls/index.d.ts +9 -0
  80. package/types/tls/keyschedule.d.ts +272 -0
  81. package/types/tls/record.d.ts +361 -0
  82. package/types/tls/tickets.d.ts +66 -0
  83. package/types/tls/transcript.d.ts +52 -0
  84. package/types/tls/wire.d.ts +106 -0
  85. package/types/transport.d.ts +222 -0
  86. package/types/trust/der.d.ts +239 -0
  87. package/types/trust/index.d.ts +194 -0
  88. package/types/trust/name.d.ts +33 -0
  89. package/types/trust/ocsp.d.ts +138 -0
  90. package/types/trust/path.d.ts +139 -0
  91. package/types/trust/roots.d.ts +36 -0
  92. package/types/trust/x509.d.ts +401 -0
  93. package/types/util/bytes.d.ts +183 -0
  94. package/types/util/deadline.d.ts +133 -0
  95. package/types/warmup-fixture.d.ts +11 -0
  96. package/types/warmup.d.ts +45 -0
@@ -0,0 +1,334 @@
1
+ // TLS wire constants, and the deliberate boundaries of what this package will negotiate.
2
+ //
3
+ // The selection below is not "what we got around to implementing" — it is a security position.
4
+ // Everything here is AEAD. There is no CBC, no RC4, no RSA key transport, and no TLS below 1.2:
5
+ //
6
+ // * MAC-then-encrypt (every CBC suite, and all of TLS 1.0/1.1) needs constant-time padding
7
+ // validation to resist Lucky13. JavaScript cannot promise constant time — JIT tiering and GC
8
+ // see to that — so shipping CBC would mean shipping a padding oracle in the name of
9
+ // compatibility. That argument does not weaken at TLS 1.2; RFC 7366 encrypt-then-MAC is too
10
+ // rarely deployed to rely on.
11
+ // * RSA key transport has no forward secrecy.
12
+ // * ChaCha20-Poly1305 is absent from WebCrypto in this runtime, and buys nothing: a server can
13
+ // only select a suite we offered, TLS 1.3 mandates AES-128-GCM (RFC 8446 s9.1), and AES-GCM is
14
+ // universal in TLS 1.2 deployments.
15
+ //
16
+ // A server that cannot meet these terms gets a typed error naming the exact value it chose, not a
17
+ // downgrade.
18
+
19
+ export const RECORD_TYPE = {
20
+ change_cipher_spec: 20,
21
+ alert: 21,
22
+ handshake: 22,
23
+ application_data: 23,
24
+ };
25
+
26
+ export const HANDSHAKE_TYPE = {
27
+ client_hello: 1,
28
+ server_hello: 2,
29
+ new_session_ticket: 4,
30
+ end_of_early_data: 5,
31
+ encrypted_extensions: 8,
32
+ certificate: 11,
33
+ server_key_exchange: 12,
34
+ certificate_request: 13,
35
+ server_hello_done: 14,
36
+ certificate_verify: 15,
37
+ client_key_exchange: 16,
38
+ finished: 20,
39
+ certificate_status: 22,
40
+ key_update: 24,
41
+ message_hash: 254,
42
+ };
43
+
44
+ /** Legacy record-layer version. Always 0x0303 on the wire after ClientHello (RFC 8446 s5.1). */
45
+ export const LEGACY_VERSION = 0x0303;
46
+ export const TLS12 = 0x0303;
47
+ export const TLS13 = 0x0304;
48
+
49
+ export const VERSION_NAME = {
50
+ 0x0300: 'SSL 3.0',
51
+ 0x0301: 'TLS 1.0',
52
+ 0x0302: 'TLS 1.1',
53
+ 0x0303: 'TLS 1.2',
54
+ 0x0304: 'TLS 1.3',
55
+ };
56
+
57
+ export const EXTENSION = {
58
+ server_name: 0,
59
+ status_request: 5,
60
+ supported_groups: 10,
61
+ ec_point_formats: 11,
62
+ signature_algorithms: 13,
63
+ alpn: 16,
64
+ signed_certificate_timestamp: 18,
65
+ extended_master_secret: 23,
66
+ session_ticket: 35,
67
+ pre_shared_key: 41,
68
+ early_data: 42,
69
+ supported_versions: 43,
70
+ cookie: 44,
71
+ psk_key_exchange_modes: 45,
72
+ certificate_authorities: 47,
73
+ signature_algorithms_cert: 50,
74
+ key_share: 51,
75
+ renegotiation_info: 0xff01,
76
+ };
77
+
78
+ // -------------------------------------------------------------------- cipher suites
79
+
80
+ export const CIPHER = {
81
+ // TLS 1.3
82
+ TLS_AES_128_GCM_SHA256: 0x1301,
83
+ TLS_AES_256_GCM_SHA384: 0x1302,
84
+ TLS_CHACHA20_POLY1305_SHA256: 0x1303, // named for diagnostics only; never offered
85
+ // TLS 1.2, ECDHE + AEAD only
86
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: 0xc02b,
87
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: 0xc02f,
88
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: 0xc02c,
89
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: 0xc030,
90
+ };
91
+
92
+ /** Reverse map for error messages. A server that picks something unlisted still gets a hex code. */
93
+ export const CIPHER_NAME = Object.fromEntries(Object.entries(CIPHER).map(([k, v]) => [v, k]));
94
+
95
+ /** Offered in ClientHello, in preference order. */
96
+ export const TLS13_CIPHERS = [CIPHER.TLS_AES_128_GCM_SHA256, CIPHER.TLS_AES_256_GCM_SHA384];
97
+
98
+ export const TLS12_CIPHERS = [
99
+ CIPHER.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
100
+ CIPHER.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
101
+ CIPHER.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
102
+ CIPHER.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
103
+ ];
104
+
105
+ /**
106
+ * Per-suite parameters. `hash` drives the whole key schedule; `keyLen` the AEAD key size.
107
+ * @typedef {object} CipherParams
108
+ * @property {'SHA-256' | 'SHA-384'} hash the only hashes any negotiable suite selects
109
+ * @property {number} hashLen
110
+ * @property {number} keyLen
111
+ * @property {number} ivLen
112
+ * @property {number} tagLen
113
+ * @property {number} [fixedIvLen] TLS 1.2 only: the 4-byte implicit GCM salt of RFC 5288
114
+ * @property {'ecdsa' | 'rsa'} [sig] TLS 1.2 only: the authentication family the suite names
115
+ */
116
+
117
+ /** @type {{ [suite: number]: CipherParams }} */
118
+ export const CIPHER_PARAMS = {
119
+ [CIPHER.TLS_AES_128_GCM_SHA256]: { hash: 'SHA-256', hashLen: 32, keyLen: 16, ivLen: 12, tagLen: 16 },
120
+ [CIPHER.TLS_AES_256_GCM_SHA384]: { hash: 'SHA-384', hashLen: 48, keyLen: 32, ivLen: 12, tagLen: 16 },
121
+ [CIPHER.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256]: {
122
+ hash: 'SHA-256', hashLen: 32, keyLen: 16, ivLen: 12, tagLen: 16, fixedIvLen: 4, sig: 'ecdsa',
123
+ },
124
+ [CIPHER.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]: {
125
+ hash: 'SHA-256', hashLen: 32, keyLen: 16, ivLen: 12, tagLen: 16, fixedIvLen: 4, sig: 'rsa',
126
+ },
127
+ [CIPHER.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384]: {
128
+ hash: 'SHA-384', hashLen: 48, keyLen: 32, ivLen: 12, tagLen: 16, fixedIvLen: 4, sig: 'ecdsa',
129
+ },
130
+ [CIPHER.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]: {
131
+ hash: 'SHA-384', hashLen: 48, keyLen: 32, ivLen: 12, tagLen: 16, fixedIvLen: 4, sig: 'rsa',
132
+ },
133
+ };
134
+
135
+ // -------------------------------------------------------------------- groups
136
+
137
+ export const GROUP = {
138
+ secp256r1: 0x0017,
139
+ secp384r1: 0x0018,
140
+ secp521r1: 0x0019,
141
+ x25519: 0x001d,
142
+ x448: 0x001e,
143
+ ffdhe2048: 0x0100,
144
+ };
145
+
146
+ export const GROUP_NAME = Object.fromEntries(Object.entries(GROUP).map(([k, v]) => [v, k]));
147
+
148
+ /**
149
+ * Offered in preference order. X25519 first because it is the modern default and the runtime's
150
+ * WebCrypto has it; secp256r1 second because RFC 8446 s9.1 makes it mandatory to implement, so
151
+ * offering both means no compliant server can fail to find a match.
152
+ */
153
+ export const SUPPORTED_GROUPS = [GROUP.x25519, GROUP.secp256r1, GROUP.secp384r1, GROUP.secp521r1];
154
+
155
+ /**
156
+ * WebCrypto parameters per group, discriminated on `kind` because X25519 sizes its shared
157
+ * secret in bytes while ECDH sizes it in bits.
158
+ * @typedef {{ kind: 'x25519', algorithm: { name: string }, publicLen: number, secretLen: number }
159
+ * | { kind: 'ec', algorithm: { name: string, namedCurve: string }, publicLen: number,
160
+ * secretBits: number }} GroupParams
161
+ */
162
+
163
+ /**
164
+ * WebCrypto parameters per group. x448 and the finite-field groups are absent by design.
165
+ * @type {{ [group: number]: GroupParams }}
166
+ */
167
+ export const GROUP_PARAMS = {
168
+ [GROUP.x25519]: { kind: 'x25519', algorithm: { name: 'X25519' }, publicLen: 32, secretLen: 32 },
169
+ [GROUP.secp256r1]: {
170
+ kind: 'ec', algorithm: { name: 'ECDH', namedCurve: 'P-256' }, publicLen: 65, secretBits: 256,
171
+ },
172
+ [GROUP.secp384r1]: {
173
+ kind: 'ec', algorithm: { name: 'ECDH', namedCurve: 'P-384' }, publicLen: 97, secretBits: 384,
174
+ },
175
+ [GROUP.secp521r1]: {
176
+ kind: 'ec', algorithm: { name: 'ECDH', namedCurve: 'P-521' }, publicLen: 133, secretBits: 528,
177
+ },
178
+ };
179
+
180
+ // -------------------------------------------------------------------- signature schemes
181
+
182
+ export const SIG_SCHEME = {
183
+ rsa_pkcs1_sha256: 0x0401,
184
+ rsa_pkcs1_sha384: 0x0501,
185
+ rsa_pkcs1_sha512: 0x0601,
186
+ ecdsa_secp256r1_sha256: 0x0403,
187
+ ecdsa_secp384r1_sha384: 0x0503,
188
+ ecdsa_secp521r1_sha512: 0x0603,
189
+ rsa_pss_rsae_sha256: 0x0804,
190
+ rsa_pss_rsae_sha384: 0x0805,
191
+ rsa_pss_rsae_sha512: 0x0806,
192
+ ed25519: 0x0807,
193
+ ed448: 0x0808,
194
+ rsa_pss_pss_sha256: 0x0809,
195
+ rsa_pss_pss_sha384: 0x080a,
196
+ rsa_pss_pss_sha512: 0x080b,
197
+ rsa_pkcs1_sha1: 0x0201,
198
+ ecdsa_sha1: 0x0203,
199
+ };
200
+
201
+ export const SIG_SCHEME_NAME = Object.fromEntries(
202
+ Object.entries(SIG_SCHEME).map(([k, v]) => [v, k]),
203
+ );
204
+
205
+ /**
206
+ * Offered in signature_algorithms. SHA-1 schemes are deliberately absent: they are forbidden in
207
+ * TLS 1.3 handshake signatures and are not worth accepting in 1.2 either.
208
+ */
209
+ export const SUPPORTED_SIG_SCHEMES = [
210
+ SIG_SCHEME.ecdsa_secp256r1_sha256,
211
+ SIG_SCHEME.ecdsa_secp384r1_sha384,
212
+ SIG_SCHEME.ecdsa_secp521r1_sha512,
213
+ SIG_SCHEME.rsa_pss_rsae_sha256,
214
+ SIG_SCHEME.rsa_pss_rsae_sha384,
215
+ SIG_SCHEME.rsa_pss_rsae_sha512,
216
+ SIG_SCHEME.ed25519,
217
+ SIG_SCHEME.rsa_pkcs1_sha256,
218
+ SIG_SCHEME.rsa_pkcs1_sha384,
219
+ SIG_SCHEME.rsa_pkcs1_sha512,
220
+ ];
221
+
222
+ /**
223
+ * How to verify one signature scheme with WebCrypto. `format: 'ecdsa-der'` marks the schemes
224
+ * whose wire signatures need the DER-to-P1363 conversion before subtle.verify will take them.
225
+ * @typedef {object} SigSchemeParams
226
+ * @property {{ name: string, namedCurve?: string, hash?: string }} import importKey algorithm
227
+ * @property {{ name: string, hash?: string, saltLength?: number }} verify verify() algorithm
228
+ * @property {'ecdsa-der'} [format]
229
+ * @property {number} [curveOrderLen] byte width of the curve order, ECDSA only
230
+ */
231
+
232
+ /**
233
+ * How to verify each scheme with WebCrypto. Absent entries are rejected with a named error.
234
+ * @type {{ [scheme: number]: SigSchemeParams }}
235
+ */
236
+ export const SIG_SCHEME_PARAMS = {
237
+ [SIG_SCHEME.ecdsa_secp256r1_sha256]: {
238
+ import: { name: 'ECDSA', namedCurve: 'P-256' }, verify: { name: 'ECDSA', hash: 'SHA-256' },
239
+ format: 'ecdsa-der', curveOrderLen: 32,
240
+ },
241
+ [SIG_SCHEME.ecdsa_secp384r1_sha384]: {
242
+ import: { name: 'ECDSA', namedCurve: 'P-384' }, verify: { name: 'ECDSA', hash: 'SHA-384' },
243
+ format: 'ecdsa-der', curveOrderLen: 48,
244
+ },
245
+ [SIG_SCHEME.ecdsa_secp521r1_sha512]: {
246
+ import: { name: 'ECDSA', namedCurve: 'P-521' }, verify: { name: 'ECDSA', hash: 'SHA-512' },
247
+ format: 'ecdsa-der', curveOrderLen: 66,
248
+ },
249
+ [SIG_SCHEME.rsa_pss_rsae_sha256]: {
250
+ import: { name: 'RSA-PSS', hash: 'SHA-256' }, verify: { name: 'RSA-PSS', saltLength: 32 },
251
+ },
252
+ [SIG_SCHEME.rsa_pss_rsae_sha384]: {
253
+ import: { name: 'RSA-PSS', hash: 'SHA-384' }, verify: { name: 'RSA-PSS', saltLength: 48 },
254
+ },
255
+ [SIG_SCHEME.rsa_pss_rsae_sha512]: {
256
+ import: { name: 'RSA-PSS', hash: 'SHA-512' }, verify: { name: 'RSA-PSS', saltLength: 64 },
257
+ },
258
+ [SIG_SCHEME.rsa_pss_pss_sha256]: {
259
+ import: { name: 'RSA-PSS', hash: 'SHA-256' }, verify: { name: 'RSA-PSS', saltLength: 32 },
260
+ },
261
+ [SIG_SCHEME.rsa_pss_pss_sha384]: {
262
+ import: { name: 'RSA-PSS', hash: 'SHA-384' }, verify: { name: 'RSA-PSS', saltLength: 48 },
263
+ },
264
+ [SIG_SCHEME.rsa_pss_pss_sha512]: {
265
+ import: { name: 'RSA-PSS', hash: 'SHA-512' }, verify: { name: 'RSA-PSS', saltLength: 64 },
266
+ },
267
+ [SIG_SCHEME.rsa_pkcs1_sha256]: {
268
+ import: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, verify: { name: 'RSASSA-PKCS1-v1_5' },
269
+ },
270
+ [SIG_SCHEME.rsa_pkcs1_sha384]: {
271
+ import: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-384' }, verify: { name: 'RSASSA-PKCS1-v1_5' },
272
+ },
273
+ [SIG_SCHEME.rsa_pkcs1_sha512]: {
274
+ import: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-512' }, verify: { name: 'RSASSA-PKCS1-v1_5' },
275
+ },
276
+ [SIG_SCHEME.ed25519]: { import: { name: 'Ed25519' }, verify: { name: 'Ed25519' } },
277
+ };
278
+
279
+ // -------------------------------------------------------------------- alerts
280
+
281
+ export const ALERT_LEVEL = { warning: 1, fatal: 2 };
282
+
283
+ export const ALERT_DESC = {
284
+ 0: 'close_notify',
285
+ 10: 'unexpected_message',
286
+ 20: 'bad_record_mac',
287
+ 21: 'decryption_failed',
288
+ 22: 'record_overflow',
289
+ 40: 'handshake_failure',
290
+ 41: 'no_certificate',
291
+ 42: 'bad_certificate',
292
+ 43: 'unsupported_certificate',
293
+ 44: 'certificate_revoked',
294
+ 45: 'certificate_expired',
295
+ 46: 'certificate_unknown',
296
+ 47: 'illegal_parameter',
297
+ 48: 'unknown_ca',
298
+ 49: 'access_denied',
299
+ 50: 'decode_error',
300
+ 51: 'decrypt_error',
301
+ 70: 'protocol_version',
302
+ 71: 'insufficient_security',
303
+ 80: 'internal_error',
304
+ 86: 'inappropriate_fallback',
305
+ 90: 'user_canceled',
306
+ 109: 'missing_extension',
307
+ 110: 'unsupported_extension',
308
+ 112: 'unrecognized_name',
309
+ 113: 'bad_certificate_status_response',
310
+ 115: 'unknown_psk_identity',
311
+ 116: 'certificate_required',
312
+ 120: 'no_application_protocol',
313
+ };
314
+
315
+ /** RFC 8446 s5.1: plaintext fragments are at most 2^14 bytes; ciphertext adds at most 256. */
316
+ export const MAX_PLAINTEXT = 1 << 14;
317
+ export const MAX_CIPHERTEXT = (1 << 14) + 256;
318
+
319
+ /** The only protocol we will negotiate. Offering h2 we cannot speak would be a footgun. */
320
+ export const ALPN_HTTP11 = 'http/1.1';
321
+
322
+ /**
323
+ * RFC 8446 s4.1.3: a TLS 1.2 server that is really 1.3-aware signals a downgrade attempt by
324
+ * planting these in the last 8 bytes of ServerHello.random. A 1.3-capable client that lands on
325
+ * 1.2 must abort when it sees them.
326
+ */
327
+ export const DOWNGRADE_SENTINEL_12 = Uint8Array.from([0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01]);
328
+ export const DOWNGRADE_SENTINEL_11 = Uint8Array.from([0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x00]);
329
+
330
+ /** RFC 8446 s4.1.3: HelloRetryRequest is a ServerHello whose random is this fixed value. */
331
+ export const HELLO_RETRY_REQUEST_RANDOM = Uint8Array.from([
332
+ 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
333
+ 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c,
334
+ ]);