@push.rocks/smartproxy 3.37.0 → 3.37.2

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.
@@ -0,0 +1,45 @@
1
+ import { Buffer } from 'buffer';
2
+ /**
3
+ * SNI (Server Name Indication) handler for TLS connections.
4
+ * Provides robust extraction of SNI values from TLS ClientHello messages.
5
+ */
6
+ export declare class SniHandler {
7
+ private static readonly TLS_HANDSHAKE_RECORD_TYPE;
8
+ private static readonly TLS_CLIENT_HELLO_HANDSHAKE_TYPE;
9
+ private static readonly TLS_SNI_EXTENSION_TYPE;
10
+ private static readonly TLS_SESSION_TICKET_EXTENSION_TYPE;
11
+ private static readonly TLS_SNI_HOST_NAME_TYPE;
12
+ /**
13
+ * Checks if a buffer contains a TLS handshake message (record type 22)
14
+ * @param buffer - The buffer to check
15
+ * @returns true if the buffer starts with a TLS handshake record type
16
+ */
17
+ static isTlsHandshake(buffer: Buffer): boolean;
18
+ /**
19
+ * Checks if a buffer contains a TLS ClientHello message
20
+ * @param buffer - The buffer to check
21
+ * @returns true if the buffer appears to be a ClientHello message
22
+ */
23
+ static isClientHello(buffer: Buffer): boolean;
24
+ /**
25
+ * Extracts the SNI (Server Name Indication) from a TLS ClientHello message.
26
+ * Implements robust parsing with support for session resumption edge cases.
27
+ *
28
+ * @param buffer - The buffer containing the TLS ClientHello message
29
+ * @param enableLogging - Whether to enable detailed debug logging
30
+ * @returns The extracted server name or undefined if not found
31
+ */
32
+ static extractSNI(buffer: Buffer, enableLogging?: boolean): string | undefined;
33
+ /**
34
+ * Attempts to extract SNI from an initial ClientHello packet and handles
35
+ * session resumption edge cases more robustly than the standard extraction.
36
+ *
37
+ * This method is specifically designed for Chrome and other browsers that
38
+ * may send different ClientHello formats during session resumption.
39
+ *
40
+ * @param buffer - The buffer containing the TLS ClientHello message
41
+ * @param enableLogging - Whether to enable detailed debug logging
42
+ * @returns The extracted server name or undefined if not found
43
+ */
44
+ static extractSNIWithResumptionSupport(buffer: Buffer, enableLogging?: boolean): string | undefined;
45
+ }
@@ -0,0 +1,274 @@
1
+ import { Buffer } from 'buffer';
2
+ /**
3
+ * SNI (Server Name Indication) handler for TLS connections.
4
+ * Provides robust extraction of SNI values from TLS ClientHello messages.
5
+ */
6
+ export class SniHandler {
7
+ // TLS record types and constants
8
+ static { this.TLS_HANDSHAKE_RECORD_TYPE = 22; }
9
+ static { this.TLS_CLIENT_HELLO_HANDSHAKE_TYPE = 1; }
10
+ static { this.TLS_SNI_EXTENSION_TYPE = 0x0000; }
11
+ static { this.TLS_SESSION_TICKET_EXTENSION_TYPE = 0x0023; }
12
+ static { this.TLS_SNI_HOST_NAME_TYPE = 0; }
13
+ /**
14
+ * Checks if a buffer contains a TLS handshake message (record type 22)
15
+ * @param buffer - The buffer to check
16
+ * @returns true if the buffer starts with a TLS handshake record type
17
+ */
18
+ static isTlsHandshake(buffer) {
19
+ return buffer.length > 0 && buffer[0] === this.TLS_HANDSHAKE_RECORD_TYPE;
20
+ }
21
+ /**
22
+ * Checks if a buffer contains a TLS ClientHello message
23
+ * @param buffer - The buffer to check
24
+ * @returns true if the buffer appears to be a ClientHello message
25
+ */
26
+ static isClientHello(buffer) {
27
+ // Minimum ClientHello size (TLS record header + handshake header)
28
+ if (buffer.length < 9) {
29
+ return false;
30
+ }
31
+ // Check record type (must be TLS_HANDSHAKE_RECORD_TYPE)
32
+ if (buffer[0] !== this.TLS_HANDSHAKE_RECORD_TYPE) {
33
+ return false;
34
+ }
35
+ // Skip version and length in TLS record header (5 bytes total)
36
+ // Check handshake type at byte 5 (must be CLIENT_HELLO)
37
+ return buffer[5] === this.TLS_CLIENT_HELLO_HANDSHAKE_TYPE;
38
+ }
39
+ /**
40
+ * Extracts the SNI (Server Name Indication) from a TLS ClientHello message.
41
+ * Implements robust parsing with support for session resumption edge cases.
42
+ *
43
+ * @param buffer - The buffer containing the TLS ClientHello message
44
+ * @param enableLogging - Whether to enable detailed debug logging
45
+ * @returns The extracted server name or undefined if not found
46
+ */
47
+ static extractSNI(buffer, enableLogging = false) {
48
+ // Logging helper
49
+ const log = (message) => {
50
+ if (enableLogging) {
51
+ console.log(`[SNI Extraction] ${message}`);
52
+ }
53
+ };
54
+ try {
55
+ // Buffer must be at least 5 bytes (TLS record header)
56
+ if (buffer.length < 5) {
57
+ log('Buffer too small for TLS record header');
58
+ return undefined;
59
+ }
60
+ // Check record type (must be TLS_HANDSHAKE_RECORD_TYPE = 22)
61
+ if (buffer[0] !== this.TLS_HANDSHAKE_RECORD_TYPE) {
62
+ log(`Not a TLS handshake record: ${buffer[0]}`);
63
+ return undefined;
64
+ }
65
+ // Check TLS version
66
+ const majorVersion = buffer[1];
67
+ const minorVersion = buffer[2];
68
+ log(`TLS version: ${majorVersion}.${minorVersion}`);
69
+ // Parse record length (bytes 3-4, big-endian)
70
+ const recordLength = (buffer[3] << 8) + buffer[4];
71
+ log(`Record length: ${recordLength}`);
72
+ // Validate record length against buffer size
73
+ if (buffer.length < recordLength + 5) {
74
+ log('Buffer smaller than expected record length');
75
+ return undefined;
76
+ }
77
+ // Start of handshake message in the buffer
78
+ let pos = 5;
79
+ // Check handshake type (must be CLIENT_HELLO = 1)
80
+ if (buffer[pos] !== this.TLS_CLIENT_HELLO_HANDSHAKE_TYPE) {
81
+ log(`Not a ClientHello message: ${buffer[pos]}`);
82
+ return undefined;
83
+ }
84
+ // Skip handshake type (1 byte)
85
+ pos += 1;
86
+ // Parse handshake length (3 bytes, big-endian)
87
+ const handshakeLength = (buffer[pos] << 16) + (buffer[pos + 1] << 8) + buffer[pos + 2];
88
+ log(`Handshake length: ${handshakeLength}`);
89
+ // Skip handshake length (3 bytes)
90
+ pos += 3;
91
+ // Check client version (2 bytes)
92
+ const clientMajorVersion = buffer[pos];
93
+ const clientMinorVersion = buffer[pos + 1];
94
+ log(`Client version: ${clientMajorVersion}.${clientMinorVersion}`);
95
+ // Skip client version (2 bytes)
96
+ pos += 2;
97
+ // Skip client random (32 bytes)
98
+ pos += 32;
99
+ // Parse session ID
100
+ if (pos + 1 > buffer.length) {
101
+ log('Buffer too small for session ID length');
102
+ return undefined;
103
+ }
104
+ const sessionIdLength = buffer[pos];
105
+ log(`Session ID length: ${sessionIdLength}`);
106
+ // Skip session ID length (1 byte) and session ID
107
+ pos += 1 + sessionIdLength;
108
+ // Check if we have enough bytes left
109
+ if (pos + 2 > buffer.length) {
110
+ log('Buffer too small for cipher suites length');
111
+ return undefined;
112
+ }
113
+ // Parse cipher suites length (2 bytes, big-endian)
114
+ const cipherSuitesLength = (buffer[pos] << 8) + buffer[pos + 1];
115
+ log(`Cipher suites length: ${cipherSuitesLength}`);
116
+ // Skip cipher suites length (2 bytes) and cipher suites
117
+ pos += 2 + cipherSuitesLength;
118
+ // Check if we have enough bytes left
119
+ if (pos + 1 > buffer.length) {
120
+ log('Buffer too small for compression methods length');
121
+ return undefined;
122
+ }
123
+ // Parse compression methods length (1 byte)
124
+ const compressionMethodsLength = buffer[pos];
125
+ log(`Compression methods length: ${compressionMethodsLength}`);
126
+ // Skip compression methods length (1 byte) and compression methods
127
+ pos += 1 + compressionMethodsLength;
128
+ // Check if we have enough bytes for extensions length
129
+ if (pos + 2 > buffer.length) {
130
+ log('No extensions present or buffer too small');
131
+ return undefined;
132
+ }
133
+ // Parse extensions length (2 bytes, big-endian)
134
+ const extensionsLength = (buffer[pos] << 8) + buffer[pos + 1];
135
+ log(`Extensions length: ${extensionsLength}`);
136
+ // Skip extensions length (2 bytes)
137
+ pos += 2;
138
+ // Extensions end position
139
+ const extensionsEnd = pos + extensionsLength;
140
+ // Check if extensions length is valid
141
+ if (extensionsEnd > buffer.length) {
142
+ log('Extensions length exceeds buffer size');
143
+ return undefined;
144
+ }
145
+ // Track if we found session tickets (for improved resumption handling)
146
+ let hasSessionTicket = false;
147
+ // Iterate through extensions
148
+ while (pos + 4 <= extensionsEnd) {
149
+ // Parse extension type (2 bytes, big-endian)
150
+ const extensionType = (buffer[pos] << 8) + buffer[pos + 1];
151
+ log(`Extension type: 0x${extensionType.toString(16).padStart(4, '0')}`);
152
+ // Skip extension type (2 bytes)
153
+ pos += 2;
154
+ // Parse extension length (2 bytes, big-endian)
155
+ const extensionLength = (buffer[pos] << 8) + buffer[pos + 1];
156
+ log(`Extension length: ${extensionLength}`);
157
+ // Skip extension length (2 bytes)
158
+ pos += 2;
159
+ // Check if this is the SNI extension
160
+ if (extensionType === this.TLS_SNI_EXTENSION_TYPE) {
161
+ log('Found SNI extension');
162
+ // Ensure we have enough bytes for the server name list
163
+ if (pos + 2 > extensionsEnd) {
164
+ log('Extension too small for server name list length');
165
+ pos += extensionLength; // Skip this extension
166
+ continue;
167
+ }
168
+ // Parse server name list length (2 bytes, big-endian)
169
+ const serverNameListLength = (buffer[pos] << 8) + buffer[pos + 1];
170
+ log(`Server name list length: ${serverNameListLength}`);
171
+ // Skip server name list length (2 bytes)
172
+ pos += 2;
173
+ // Ensure server name list length is valid
174
+ if (pos + serverNameListLength > extensionsEnd) {
175
+ log('Server name list length exceeds extension size');
176
+ break; // Exit the loop, extension parsing is broken
177
+ }
178
+ // End position of server name list
179
+ const serverNameListEnd = pos + serverNameListLength;
180
+ // Iterate through server names
181
+ while (pos + 3 <= serverNameListEnd) {
182
+ // Check name type (must be HOST_NAME_TYPE = 0 for hostname)
183
+ const nameType = buffer[pos];
184
+ log(`Name type: ${nameType}`);
185
+ if (nameType !== this.TLS_SNI_HOST_NAME_TYPE) {
186
+ log(`Unsupported name type: ${nameType}`);
187
+ pos += 1; // Skip name type (1 byte)
188
+ // Skip name length (2 bytes) and name data
189
+ if (pos + 2 <= serverNameListEnd) {
190
+ const nameLength = (buffer[pos] << 8) + buffer[pos + 1];
191
+ pos += 2 + nameLength;
192
+ }
193
+ else {
194
+ log('Invalid server name entry');
195
+ break;
196
+ }
197
+ continue;
198
+ }
199
+ // Skip name type (1 byte)
200
+ pos += 1;
201
+ // Ensure we have enough bytes for name length
202
+ if (pos + 2 > serverNameListEnd) {
203
+ log('Server name entry too small for name length');
204
+ break;
205
+ }
206
+ // Parse name length (2 bytes, big-endian)
207
+ const nameLength = (buffer[pos] << 8) + buffer[pos + 1];
208
+ log(`Name length: ${nameLength}`);
209
+ // Skip name length (2 bytes)
210
+ pos += 2;
211
+ // Ensure we have enough bytes for the name
212
+ if (pos + nameLength > serverNameListEnd) {
213
+ log('Name length exceeds server name list size');
214
+ break;
215
+ }
216
+ // Extract server name (hostname)
217
+ const serverName = buffer.slice(pos, pos + nameLength).toString('utf8');
218
+ log(`Extracted server name: ${serverName}`);
219
+ return serverName;
220
+ }
221
+ }
222
+ else if (extensionType === this.TLS_SESSION_TICKET_EXTENSION_TYPE) {
223
+ // If we encounter a session ticket extension, mark it for later
224
+ log('Found session ticket extension');
225
+ hasSessionTicket = true;
226
+ pos += extensionLength; // Skip this extension
227
+ }
228
+ else {
229
+ // Skip this extension
230
+ pos += extensionLength;
231
+ }
232
+ }
233
+ // Log if we found a session ticket but no SNI
234
+ if (hasSessionTicket) {
235
+ log('Session ticket present but no SNI found - possible resumption scenario');
236
+ }
237
+ log('No SNI extension found in ClientHello');
238
+ return undefined;
239
+ }
240
+ catch (error) {
241
+ log(`Error parsing SNI: ${error instanceof Error ? error.message : String(error)}`);
242
+ return undefined;
243
+ }
244
+ }
245
+ /**
246
+ * Attempts to extract SNI from an initial ClientHello packet and handles
247
+ * session resumption edge cases more robustly than the standard extraction.
248
+ *
249
+ * This method is specifically designed for Chrome and other browsers that
250
+ * may send different ClientHello formats during session resumption.
251
+ *
252
+ * @param buffer - The buffer containing the TLS ClientHello message
253
+ * @param enableLogging - Whether to enable detailed debug logging
254
+ * @returns The extracted server name or undefined if not found
255
+ */
256
+ static extractSNIWithResumptionSupport(buffer, enableLogging = false) {
257
+ // First try the standard SNI extraction
258
+ const standardSni = this.extractSNI(buffer, enableLogging);
259
+ if (standardSni) {
260
+ return standardSni;
261
+ }
262
+ // If standard extraction failed and we have a valid ClientHello,
263
+ // this might be a session resumption with non-standard format
264
+ if (this.isClientHello(buffer)) {
265
+ if (enableLogging) {
266
+ console.log('[SNI Extraction] Detected ClientHello without standard SNI, possible session resumption');
267
+ }
268
+ // Additional handling could be implemented here for specific browser behaviors
269
+ // For now, this is a placeholder for future improvements
270
+ }
271
+ return undefined;
272
+ }
273
+ }
274
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbmloYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5zbmloYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFaEM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFDckIsaUNBQWlDO2FBQ1QsOEJBQXlCLEdBQUcsRUFBRSxDQUFDO2FBQy9CLG9DQUErQixHQUFHLENBQUMsQ0FBQzthQUNwQywyQkFBc0IsR0FBRyxNQUFNLENBQUM7YUFDaEMsc0NBQWlDLEdBQUcsTUFBTSxDQUFDO2FBQzNDLDJCQUFzQixHQUFHLENBQUMsQ0FBQztJQUVuRDs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFjO1FBQ3pDLE9BQU8sTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyx5QkFBeUIsQ0FBQztJQUMzRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBYztRQUN4QyxrRUFBa0U7UUFDbEUsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3RCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELHdEQUF3RDtRQUN4RCxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztZQUNqRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCwrREFBK0Q7UUFDL0Qsd0RBQXdEO1FBQ3hELE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQywrQkFBK0IsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNJLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBYyxFQUFFLGdCQUF5QixLQUFLO1FBQ3JFLGlCQUFp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
@@ -3,3 +3,4 @@ export * from './classes.networkproxy.js';
3
3
  export * from './classes.portproxy.js';
4
4
  export * from './classes.port80handler.js';
5
5
  export * from './classes.sslredirect.js';
6
+ export * from './classes.snihandler.js';
package/dist_ts/index.js CHANGED
@@ -3,4 +3,5 @@ export * from './classes.networkproxy.js';
3
3
  export * from './classes.portproxy.js';
4
4
  export * from './classes.port80handler.js';
5
5
  export * from './classes.sslredirect.js';
6
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsMEJBQTBCLENBQUMifQ==
6
+ export * from './classes.snihandler.js';
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyx5QkFBeUIsQ0FBQyJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartproxy",
3
- "version": "3.37.0",
3
+ "version": "3.37.2",
4
4
  "private": false,
5
5
  "description": "A powerful proxy package that effectively handles high traffic, with features such as SSL/TLS support, port proxying, WebSocket handling, dynamic routing with authentication options, and automatic ACME certificate management.",
6
6
  "main": "dist_ts/index.js",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '3.37.0',
6
+ version: '3.37.2',
7
7
  description: 'A powerful proxy package that effectively handles high traffic, with features such as SSL/TLS support, port proxying, WebSocket handling, dynamic routing with authentication options, and automatic ACME certificate management.'
8
8
  }