@push.rocks/smartproxy 3.37.1 → 3.37.3

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.
@@ -10,6 +10,8 @@ export class SniHandler {
10
10
  static { this.TLS_SNI_EXTENSION_TYPE = 0x0000; }
11
11
  static { this.TLS_SESSION_TICKET_EXTENSION_TYPE = 0x0023; }
12
12
  static { this.TLS_SNI_HOST_NAME_TYPE = 0; }
13
+ static { this.TLS_PSK_EXTENSION_TYPE = 0x0029; } // Pre-Shared Key extension type for TLS 1.3
14
+ static { this.TLS_PSK_KE_MODES_EXTENSION_TYPE = 0x002D; } // PSK Key Exchange Modes
13
15
  /**
14
16
  * Checks if a buffer contains a TLS handshake message (record type 22)
15
17
  * @param buffer - The buffer to check
@@ -144,6 +146,7 @@ export class SniHandler {
144
146
  }
145
147
  // Track if we found session tickets (for improved resumption handling)
146
148
  let hasSessionTicket = false;
149
+ let hasPskExtension = false;
147
150
  // Iterate through extensions
148
151
  while (pos + 4 <= extensionsEnd) {
149
152
  // Parse extension type (2 bytes, big-endian)
@@ -225,14 +228,21 @@ export class SniHandler {
225
228
  hasSessionTicket = true;
226
229
  pos += extensionLength; // Skip this extension
227
230
  }
231
+ else if (extensionType === this.TLS_PSK_EXTENSION_TYPE) {
232
+ // TLS 1.3 PSK extension - mark for resumption support
233
+ log('Found PSK extension (TLS 1.3 resumption indicator)');
234
+ hasPskExtension = true;
235
+ // We'll skip the extension here and process it separately if needed
236
+ pos += extensionLength;
237
+ }
228
238
  else {
229
239
  // Skip this extension
230
240
  pos += extensionLength;
231
241
  }
232
242
  }
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');
243
+ // Log if we found session resumption indicators but no SNI
244
+ if (hasSessionTicket || hasPskExtension) {
245
+ log('Session resumption indicators present but no SNI found');
236
246
  }
237
247
  log('No SNI extension found in ClientHello');
238
248
  return undefined;
@@ -242,12 +252,157 @@ export class SniHandler {
242
252
  return undefined;
243
253
  }
244
254
  }
255
+ /**
256
+ * Attempts to extract SNI from the PSK extension in a TLS 1.3 ClientHello.
257
+ *
258
+ * In TLS 1.3, when a client attempts to resume a session, it may include
259
+ * the server name in the PSK identity hint rather than in the SNI extension.
260
+ *
261
+ * @param buffer - The buffer containing the TLS ClientHello message
262
+ * @param enableLogging - Whether to enable detailed debug logging
263
+ * @returns The extracted server name or undefined if not found
264
+ */
265
+ static extractSNIFromPSKExtension(buffer, enableLogging = false) {
266
+ const log = (message) => {
267
+ if (enableLogging) {
268
+ console.log(`[PSK-SNI Extraction] ${message}`);
269
+ }
270
+ };
271
+ try {
272
+ // Ensure this is a ClientHello
273
+ if (!this.isClientHello(buffer)) {
274
+ log('Not a ClientHello message');
275
+ return undefined;
276
+ }
277
+ // Find the start position of extensions
278
+ let pos = 5; // Start after record header
279
+ // Skip handshake type (1 byte)
280
+ pos += 1;
281
+ // Skip handshake length (3 bytes)
282
+ pos += 3;
283
+ // Skip client version (2 bytes)
284
+ pos += 2;
285
+ // Skip client random (32 bytes)
286
+ pos += 32;
287
+ // Skip session ID
288
+ if (pos + 1 > buffer.length)
289
+ return undefined;
290
+ const sessionIdLength = buffer[pos];
291
+ pos += 1 + sessionIdLength;
292
+ // Skip cipher suites
293
+ if (pos + 2 > buffer.length)
294
+ return undefined;
295
+ const cipherSuitesLength = (buffer[pos] << 8) + buffer[pos + 1];
296
+ pos += 2 + cipherSuitesLength;
297
+ // Skip compression methods
298
+ if (pos + 1 > buffer.length)
299
+ return undefined;
300
+ const compressionMethodsLength = buffer[pos];
301
+ pos += 1 + compressionMethodsLength;
302
+ // Check if we have extensions
303
+ if (pos + 2 > buffer.length) {
304
+ log('No extensions present');
305
+ return undefined;
306
+ }
307
+ // Get extensions length
308
+ const extensionsLength = (buffer[pos] << 8) + buffer[pos + 1];
309
+ pos += 2;
310
+ // Extensions end position
311
+ const extensionsEnd = pos + extensionsLength;
312
+ if (extensionsEnd > buffer.length)
313
+ return undefined;
314
+ // Look for PSK extension
315
+ while (pos + 4 <= extensionsEnd) {
316
+ const extensionType = (buffer[pos] << 8) + buffer[pos + 1];
317
+ pos += 2;
318
+ const extensionLength = (buffer[pos] << 8) + buffer[pos + 1];
319
+ pos += 2;
320
+ if (extensionType === this.TLS_PSK_EXTENSION_TYPE) {
321
+ log('Found PSK extension');
322
+ // PSK extension structure:
323
+ // 2 bytes: identities list length
324
+ if (pos + 2 > extensionsEnd)
325
+ break;
326
+ const identitiesLength = (buffer[pos] << 8) + buffer[pos + 1];
327
+ pos += 2;
328
+ // End of identities list
329
+ const identitiesEnd = pos + identitiesLength;
330
+ if (identitiesEnd > extensionsEnd)
331
+ break;
332
+ // Process each PSK identity
333
+ while (pos + 2 <= identitiesEnd) {
334
+ // Identity length (2 bytes)
335
+ if (pos + 2 > identitiesEnd)
336
+ break;
337
+ const identityLength = (buffer[pos] << 8) + buffer[pos + 1];
338
+ pos += 2;
339
+ if (pos + identityLength > identitiesEnd)
340
+ break;
341
+ // Try to extract hostname from identity
342
+ // Chrome often embeds the hostname in the PSK identity
343
+ // This is a heuristic as there's no standard format
344
+ if (identityLength > 0) {
345
+ const identity = buffer.slice(pos, pos + identityLength);
346
+ // Skip identity bytes
347
+ pos += identityLength;
348
+ // Skip obfuscated ticket age (4 bytes)
349
+ pos += 4;
350
+ // Try to parse the identity as UTF-8
351
+ try {
352
+ const identityStr = identity.toString('utf8');
353
+ log(`PSK identity: ${identityStr}`);
354
+ // Check if the identity contains hostname hints
355
+ // Chrome often embeds the hostname in a known format
356
+ // Try to extract using common patterns
357
+ // Pattern 1: Look for domain name pattern
358
+ const domainPattern = /([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?/i;
359
+ const domainMatch = identityStr.match(domainPattern);
360
+ if (domainMatch && domainMatch[0]) {
361
+ log(`Found domain in PSK identity: ${domainMatch[0]}`);
362
+ return domainMatch[0];
363
+ }
364
+ // Pattern 2: Chrome sometimes uses a specific format with delimiters
365
+ // This is a heuristic approach since the format isn't standardized
366
+ const parts = identityStr.split('|');
367
+ if (parts.length > 1) {
368
+ for (const part of parts) {
369
+ if (part.includes('.') && !part.includes('/')) {
370
+ const possibleDomain = part.trim();
371
+ if (/^[a-z0-9.-]+$/i.test(possibleDomain)) {
372
+ log(`Found possible domain in PSK delimiter format: ${possibleDomain}`);
373
+ return possibleDomain;
374
+ }
375
+ }
376
+ }
377
+ }
378
+ }
379
+ catch (e) {
380
+ log('Failed to parse PSK identity as UTF-8');
381
+ }
382
+ }
383
+ }
384
+ }
385
+ else {
386
+ // Skip this extension
387
+ pos += extensionLength;
388
+ }
389
+ }
390
+ log('No hostname found in PSK extension');
391
+ return undefined;
392
+ }
393
+ catch (error) {
394
+ log(`Error parsing PSK: ${error instanceof Error ? error.message : String(error)}`);
395
+ return undefined;
396
+ }
397
+ }
245
398
  /**
246
399
  * Attempts to extract SNI from an initial ClientHello packet and handles
247
400
  * session resumption edge cases more robustly than the standard extraction.
248
401
  *
249
- * This method is specifically designed for Chrome and other browsers that
250
- * may send different ClientHello formats during session resumption.
402
+ * This method handles:
403
+ * 1. Standard SNI extraction
404
+ * 2. TLS 1.3 PSK-based resumption (Chrome, Firefox, etc.)
405
+ * 3. Session ticket-based resumption
251
406
  *
252
407
  * @param buffer - The buffer containing the TLS ClientHello message
253
408
  * @param enableLogging - Whether to enable detailed debug logging
@@ -257,6 +412,9 @@ export class SniHandler {
257
412
  // First try the standard SNI extraction
258
413
  const standardSni = this.extractSNI(buffer, enableLogging);
259
414
  if (standardSni) {
415
+ if (enableLogging) {
416
+ console.log(`[SNI Extraction] Found standard SNI: ${standardSni}`);
417
+ }
260
418
  return standardSni;
261
419
  }
262
420
  // If standard extraction failed and we have a valid ClientHello,
@@ -265,10 +423,20 @@ export class SniHandler {
265
423
  if (enableLogging) {
266
424
  console.log('[SNI Extraction] Detected ClientHello without standard SNI, possible session resumption');
267
425
  }
268
- // Additional handling could be implemented here for specific browser behaviors
269
- // For now, this is a placeholder for future improvements
426
+ // Try to extract from PSK extension (TLS 1.3 resumption)
427
+ const pskSni = this.extractSNIFromPSKExtension(buffer, enableLogging);
428
+ if (pskSni) {
429
+ if (enableLogging) {
430
+ console.log(`[SNI Extraction] Extracted SNI from PSK extension: ${pskSni}`);
431
+ }
432
+ return pskSni;
433
+ }
434
+ // Could add more browser-specific heuristics here if needed
435
+ if (enableLogging) {
436
+ console.log('[SNI Extraction] Failed to extract SNI from resumption mechanisms');
437
+ }
270
438
  }
271
439
  return undefined;
272
440
  }
273
441
  }
274
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbmloYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5zbmloYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFaEM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFDckIsaUNBQWlDO2FBQ1QsOEJBQXlCLEdBQUcsRUFBRSxDQUFDO2FBQy9CLG9DQUErQixHQUFHLENBQUMsQ0FBQzthQUNwQywyQkFBc0IsR0FBRyxNQUFNLENBQUM7YUFDaEMsc0NBQWlDLEdBQUcsTUFBTSxDQUFDO2FBQzNDLDJCQUFzQixHQUFHLENBQUMsQ0FBQztJQUVuRDs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFjO1FBQ3pDLE9BQU8sTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyx5QkFBeUIsQ0FBQztJQUMzRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBYztRQUN4QyxrRUFBa0U7UUFDbEUsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3RCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELHdEQUF3RDtRQUN4RCxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztZQUNqRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCwrREFBK0Q7UUFDL0Qsd0RBQXdEO1FBQ3hELE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQywrQkFBK0IsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNJLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBYyxFQUFFLGdCQUF5QixLQUFLO1FBQ3JFLGlCQUFp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
442
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbmloYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5zbmloYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFaEM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFDckIsaUNBQWlDO2FBQ1QsOEJBQXlCLEdBQUcsRUFBRSxDQUFDO2FBQy9CLG9DQUErQixHQUFHLENBQUMsQ0FBQzthQUNwQywyQkFBc0IsR0FBRyxNQUFNLENBQUM7YUFDaEMsc0NBQWlDLEdBQUcsTUFBTSxDQUFDO2FBQzNDLDJCQUFzQixHQUFHLENBQUMsQ0FBQzthQUMzQiwyQkFBc0IsR0FBRyxNQUFNLENBQUMsR0FBQyw0Q0FBNEM7YUFDN0Usb0NBQStCLEdBQUcsTUFBTSxDQUFDLEdBQUMseUJBQXlCO0lBRTNGOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsY0FBYyxDQUFDLE1BQWM7UUFDekMsT0FBTyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLHlCQUF5QixDQUFDO0lBQzNFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLGFBQWEsQ0FBQyxNQUFjO1FBQ3hDLGtFQUFrRTtRQUNsRSxJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDdEIsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsd0RBQXdEO1FBQ3hELElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1lBQ2pELE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELCtEQUErRDtRQUMvRCx3REFBd0Q7UUFDeEQsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLCtCQUErQixDQUFDO0lBQzVE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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartproxy",
3
- "version": "3.37.1",
3
+ "version": "3.37.3",
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.1',
6
+ version: '3.37.3',
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
  }
@@ -566,44 +566,104 @@ export class PortProxy {
566
566
  connectionOptions.localAddress = record.remoteIP.replace('::ffff:', '');
567
567
  }
568
568
 
569
+ // Create a safe queue for incoming data using a Buffer array
570
+ // We'll use this to ensure we don't lose data during handler transitions
571
+ const dataQueue: Buffer[] = [];
572
+ let queueSize = 0;
573
+ let processingQueue = false;
574
+ let drainPending = false;
575
+
576
+ // Flag to track if we've switched to the final piping mechanism
577
+ // Once this is true, we no longer buffer data in dataQueue
578
+ let pipingEstablished = false;
579
+
569
580
  // Pause the incoming socket to prevent buffer overflows
581
+ // This ensures we control the flow of data until piping is set up
570
582
  socket.pause();
571
583
 
572
- // Temporary handler to collect data during connection setup
573
- const tempDataHandler = (chunk: Buffer) => {
574
- // Track bytes received
575
- record.bytesReceived += chunk.length;
584
+ // Function to safely process the data queue without losing events
585
+ const processDataQueue = () => {
586
+ if (processingQueue || dataQueue.length === 0 || pipingEstablished) return;
587
+
588
+ processingQueue = true;
589
+
590
+ try {
591
+ // Process all queued chunks with the current active handler
592
+ while (dataQueue.length > 0) {
593
+ const chunk = dataQueue.shift()!;
594
+ queueSize -= chunk.length;
595
+
596
+ // Once piping is established, we shouldn't get here,
597
+ // but just in case, pass to the outgoing socket directly
598
+ if (pipingEstablished && record.outgoing) {
599
+ record.outgoing.write(chunk);
600
+ continue;
601
+ }
602
+
603
+ // Track bytes received
604
+ record.bytesReceived += chunk.length;
576
605
 
577
- // Check for TLS handshake
578
- if (!record.isTLS && SniHandler.isTlsHandshake(chunk)) {
579
- record.isTLS = true;
606
+ // Check for TLS handshake
607
+ if (!record.isTLS && SniHandler.isTlsHandshake(chunk)) {
608
+ record.isTLS = true;
580
609
 
581
- if (this.settings.enableTlsDebugLogging) {
582
- console.log(
583
- `[${connectionId}] TLS handshake detected in tempDataHandler, ${chunk.length} bytes`
584
- );
585
- }
586
- }
610
+ if (this.settings.enableTlsDebugLogging) {
611
+ console.log(
612
+ `[${connectionId}] TLS handshake detected in tempDataHandler, ${chunk.length} bytes`
613
+ );
614
+ }
615
+ }
587
616
 
588
- // Check if adding this chunk would exceed the buffer limit
589
- const newSize = record.pendingDataSize + chunk.length;
617
+ // Check if adding this chunk would exceed the buffer limit
618
+ const newSize = record.pendingDataSize + chunk.length;
590
619
 
591
- if (this.settings.maxPendingDataSize && newSize > this.settings.maxPendingDataSize) {
592
- console.log(
593
- `[${connectionId}] Buffer limit exceeded for connection from ${record.remoteIP}: ${newSize} bytes > ${this.settings.maxPendingDataSize} bytes`
594
- );
595
- socket.end(); // Gracefully close the socket
596
- return this.initiateCleanupOnce(record, 'buffer_limit_exceeded');
620
+ if (this.settings.maxPendingDataSize && newSize > this.settings.maxPendingDataSize) {
621
+ console.log(
622
+ `[${connectionId}] Buffer limit exceeded for connection from ${record.remoteIP}: ${newSize} bytes > ${this.settings.maxPendingDataSize} bytes`
623
+ );
624
+ socket.end(); // Gracefully close the socket
625
+ this.initiateCleanupOnce(record, 'buffer_limit_exceeded');
626
+ return;
627
+ }
628
+
629
+ // Buffer the chunk and update the size counter
630
+ record.pendingData.push(Buffer.from(chunk));
631
+ record.pendingDataSize = newSize;
632
+ this.updateActivity(record);
633
+ }
634
+ } finally {
635
+ processingQueue = false;
636
+
637
+ // If there's a pending drain and we've processed everything,
638
+ // signal we're ready for more data if we haven't established piping yet
639
+ if (drainPending && dataQueue.length === 0 && !pipingEstablished) {
640
+ drainPending = false;
641
+ socket.resume();
642
+ }
597
643
  }
644
+ };
598
645
 
599
- // Buffer the chunk and update the size counter
600
- record.pendingData.push(Buffer.from(chunk));
601
- record.pendingDataSize = newSize;
602
- this.updateActivity(record);
646
+ // Unified data handler that safely queues incoming data
647
+ const safeDataHandler = (chunk: Buffer) => {
648
+ // If piping is already established, just let the pipe handle it
649
+ if (pipingEstablished) return;
650
+
651
+ // Add to our queue for orderly processing
652
+ dataQueue.push(Buffer.from(chunk)); // Make a copy to be safe
653
+ queueSize += chunk.length;
654
+
655
+ // If queue is getting large, pause socket until we catch up
656
+ if (this.settings.maxPendingDataSize && queueSize > this.settings.maxPendingDataSize * 0.8) {
657
+ socket.pause();
658
+ drainPending = true;
659
+ }
660
+
661
+ // Process the queue
662
+ processDataQueue();
603
663
  };
604
664
 
605
- // Add the temp handler to capture all incoming data during connection setup
606
- socket.on('data', tempDataHandler);
665
+ // Add our safe data handler
666
+ socket.on('data', safeDataHandler);
607
667
 
608
668
  // Add initial chunk to pending data if present
609
669
  if (initialChunk) {
@@ -776,56 +836,32 @@ export class PortProxy {
776
836
  // Add the normal error handler for established connections
777
837
  targetSocket.on('error', this.handleError('outgoing', record));
778
838
 
779
- // Remove temporary data handler
780
- socket.removeListener('data', tempDataHandler);
781
-
782
- // Flush all pending data to target
783
- if (record.pendingData.length > 0) {
784
- const combinedData = Buffer.concat(record.pendingData);
785
- targetSocket.write(combinedData, (err) => {
786
- if (err) {
787
- console.log(`[${connectionId}] Error writing pending data to target: ${err.message}`);
788
- return this.initiateCleanupOnce(record, 'write_error');
789
- }
790
-
791
- // Now set up piping for future data and resume the socket
792
- socket.pipe(targetSocket);
793
- targetSocket.pipe(socket);
794
- socket.resume(); // Resume the socket after piping is established
795
-
796
- if (this.settings.enableDetailedLogging) {
797
- console.log(
798
- `[${connectionId}] Connection established: ${record.remoteIP} -> ${targetHost}:${connectionOptions.port}` +
799
- `${
800
- serverName
801
- ? ` (SNI: ${serverName})`
802
- : domainConfig
803
- ? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
804
- : ''
805
- }` +
806
- ` TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${
807
- record.hasKeepAlive ? 'Yes' : 'No'
808
- }`
809
- );
810
- } else {
811
- console.log(
812
- `Connection established: ${record.remoteIP} -> ${targetHost}:${connectionOptions.port}` +
813
- `${
814
- serverName
815
- ? ` (SNI: ${serverName})`
816
- : domainConfig
817
- ? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
818
- : ''
819
- }`
820
- );
821
- }
822
- });
823
- } else {
824
- // No pending data, so just set up piping
839
+ // Process any remaining data in the queue before switching to piping
840
+ processDataQueue();
841
+
842
+ // Setup function to establish piping - we'll use this after flushing data
843
+ const setupPiping = () => {
844
+ // Mark that we're switching to piping mode
845
+ pipingEstablished = true;
846
+
847
+ // Setup piping in both directions
825
848
  socket.pipe(targetSocket);
826
849
  targetSocket.pipe(socket);
827
- socket.resume(); // Resume the socket after piping is established
828
-
850
+
851
+ // Resume the socket to ensure data flows
852
+ socket.resume();
853
+
854
+ // Process any data that might be queued in the interim
855
+ if (dataQueue.length > 0) {
856
+ // Write any remaining queued data directly to the target socket
857
+ for (const chunk of dataQueue) {
858
+ targetSocket.write(chunk);
859
+ }
860
+ // Clear the queue
861
+ dataQueue.length = 0;
862
+ queueSize = 0;
863
+ }
864
+
829
865
  if (this.settings.enableDetailedLogging) {
830
866
  console.log(
831
867
  `[${connectionId}] Connection established: ${record.remoteIP} -> ${targetHost}:${connectionOptions.port}` +
@@ -852,6 +888,23 @@ export class PortProxy {
852
888
  }`
853
889
  );
854
890
  }
891
+ };
892
+
893
+ // Flush all pending data to target
894
+ if (record.pendingData.length > 0) {
895
+ const combinedData = Buffer.concat(record.pendingData);
896
+ targetSocket.write(combinedData, (err) => {
897
+ if (err) {
898
+ console.log(`[${connectionId}] Error writing pending data to target: ${err.message}`);
899
+ return this.initiateCleanupOnce(record, 'write_error');
900
+ }
901
+
902
+ // Establish piping now that we've flushed the buffered data
903
+ setupPiping();
904
+ });
905
+ } else {
906
+ // No pending data, just establish piping immediately
907
+ setupPiping();
855
908
  }
856
909
 
857
910
  // Clear the buffer now that we've processed it
@@ -859,6 +912,7 @@ export class PortProxy {
859
912
  record.pendingDataSize = 0;
860
913
 
861
914
  // Add the renegotiation handler for SNI validation with strict domain enforcement
915
+ // This will be called after we've established piping
862
916
  if (serverName) {
863
917
  // Define a handler for checking renegotiation with improved detection
864
918
  const renegotiationHandler = (renegChunk: Buffer) => {
@@ -895,8 +949,13 @@ export class PortProxy {
895
949
  // Store the handler in the connection record so we can remove it during cleanup
896
950
  record.renegotiationHandler = renegotiationHandler;
897
951
 
898
- // Add the listener
952
+ // The renegotiation handler is added when piping is established
953
+ // Making it part of setupPiping ensures proper sequencing of event handlers
899
954
  socket.on('data', renegotiationHandler);
955
+
956
+ if (this.settings.enableDetailedLogging) {
957
+ console.log(`[${connectionId}] TLS renegotiation handler installed for SNI domain: ${serverName}`);
958
+ }
900
959
  }
901
960
 
902
961
  // Set connection timeout with simpler logic
@@ -1056,13 +1115,16 @@ export class PortProxy {
1056
1115
  const bytesReceived = record.bytesReceived;
1057
1116
  const bytesSent = record.bytesSent;
1058
1117
 
1059
- // Remove the renegotiation handler if present
1060
- if (record.renegotiationHandler && record.incoming) {
1118
+ // Remove all data handlers (both standard and renegotiation) to make sure we clean up properly
1119
+ if (record.incoming) {
1061
1120
  try {
1062
- record.incoming.removeListener('data', record.renegotiationHandler);
1121
+ // Remove our safe data handler
1122
+ record.incoming.removeAllListeners('data');
1123
+
1124
+ // Reset the handler references
1063
1125
  record.renegotiationHandler = undefined;
1064
1126
  } catch (err) {
1065
- console.log(`[${record.id}] Error removing renegotiation handler: ${err}`);
1127
+ console.log(`[${record.id}] Error removing data handlers: ${err}`);
1066
1128
  }
1067
1129
  }
1068
1130