@push.rocks/smartproxy 19.3.6 → 19.3.9
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.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +16 -3
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +4 -0
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +120 -187
- package/dist_ts/proxies/smart-proxy/route-manager.js +13 -4
- package/package.json +1 -1
- package/readme.hints.md +42 -1
- package/readme.md +18 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/proxies/smart-proxy/http-proxy-bridge.ts +15 -2
- package/ts/proxies/smart-proxy/route-connection-handler.ts +173 -248
- package/ts/proxies/smart-proxy/route-manager.ts +12 -3
- package/readme.plan.md +0 -179
|
@@ -372,14 +372,14 @@ export class RouteConnectionHandler {
|
|
|
372
372
|
initialChunk?: Buffer
|
|
373
373
|
): void {
|
|
374
374
|
const connectionId = record.id;
|
|
375
|
-
const action = route.action;
|
|
375
|
+
const action = route.action as IRouteAction;
|
|
376
376
|
|
|
377
377
|
// Check if this route uses NFTables for forwarding
|
|
378
378
|
if (action.forwardingEngine === 'nftables') {
|
|
379
379
|
// NFTables handles packet forwarding at the kernel level
|
|
380
380
|
// The application should NOT interfere with these connections
|
|
381
381
|
|
|
382
|
-
//
|
|
382
|
+
// Log the connection for monitoring purposes
|
|
383
383
|
if (this.settings.enableDetailedLogging) {
|
|
384
384
|
console.log(
|
|
385
385
|
`[${record.id}] NFTables forwarding (kernel-level): ` +
|
|
@@ -407,9 +407,14 @@ export class RouteConnectionHandler {
|
|
|
407
407
|
);
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
|
-
|
|
411
|
-
// For NFTables routes,
|
|
412
|
-
//
|
|
410
|
+
|
|
411
|
+
// For NFTables routes, we should still track the connection but not interfere
|
|
412
|
+
// Mark the connection as using network proxy so it's cleaned up properly
|
|
413
|
+
record.usingNetworkProxy = true;
|
|
414
|
+
|
|
415
|
+
// We don't close the socket - just let it remain open
|
|
416
|
+
// The kernel-level NFTables rules will handle the actual forwarding
|
|
417
|
+
return;
|
|
413
418
|
}
|
|
414
419
|
|
|
415
420
|
// We should have a target configuration for forwarding
|
|
@@ -547,52 +552,74 @@ export class RouteConnectionHandler {
|
|
|
547
552
|
}
|
|
548
553
|
}
|
|
549
554
|
} else {
|
|
550
|
-
// No TLS settings -
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
555
|
+
// No TLS settings - check if this port should use HttpProxy
|
|
556
|
+
const isHttpProxyPort = this.settings.useHttpProxy?.includes(record.localPort);
|
|
557
|
+
|
|
558
|
+
if (isHttpProxyPort && this.httpProxyBridge.getHttpProxy()) {
|
|
559
|
+
// Forward non-TLS connections to HttpProxy if configured
|
|
560
|
+
if (this.settings.enableDetailedLogging) {
|
|
561
|
+
console.log(
|
|
562
|
+
`[${connectionId}] Using HttpProxy for non-TLS connection on port ${record.localPort}`
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
this.httpProxyBridge.forwardToHttpProxy(
|
|
567
|
+
connectionId,
|
|
568
|
+
socket,
|
|
569
|
+
record,
|
|
570
|
+
initialChunk,
|
|
571
|
+
this.settings.httpProxyPort || 8443,
|
|
572
|
+
(reason) => this.connectionManager.initiateCleanupOnce(record, reason)
|
|
554
573
|
);
|
|
555
|
-
|
|
574
|
+
return;
|
|
575
|
+
} else {
|
|
576
|
+
// Basic forwarding
|
|
577
|
+
if (this.settings.enableDetailedLogging) {
|
|
578
|
+
console.log(
|
|
579
|
+
`[${connectionId}] Using basic forwarding to ${action.target.host}:${action.target.port}`
|
|
580
|
+
);
|
|
581
|
+
}
|
|
556
582
|
|
|
557
|
-
|
|
558
|
-
|
|
583
|
+
// Get the appropriate host value
|
|
584
|
+
let targetHost: string;
|
|
585
|
+
|
|
586
|
+
if (typeof action.target.host === 'function') {
|
|
587
|
+
// For function-based host, use the same routeContext created earlier
|
|
588
|
+
const hostResult = action.target.host(routeContext);
|
|
589
|
+
targetHost = Array.isArray(hostResult)
|
|
590
|
+
? hostResult[Math.floor(Math.random() * hostResult.length)]
|
|
591
|
+
: hostResult;
|
|
592
|
+
} else {
|
|
593
|
+
// For static host value
|
|
594
|
+
targetHost = Array.isArray(action.target.host)
|
|
595
|
+
? action.target.host[Math.floor(Math.random() * action.target.host.length)]
|
|
596
|
+
: action.target.host;
|
|
597
|
+
}
|
|
559
598
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
? action.target.host[Math.floor(Math.random() * action.target.host.length)]
|
|
570
|
-
: action.target.host;
|
|
571
|
-
}
|
|
599
|
+
// Determine port - either function-based, static, or preserve incoming port
|
|
600
|
+
let targetPort: number;
|
|
601
|
+
if (typeof action.target.port === 'function') {
|
|
602
|
+
targetPort = action.target.port(routeContext);
|
|
603
|
+
} else if (action.target.port === 'preserve') {
|
|
604
|
+
targetPort = record.localPort;
|
|
605
|
+
} else {
|
|
606
|
+
targetPort = action.target.port;
|
|
607
|
+
}
|
|
572
608
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
targetPort = action.target.port(routeContext);
|
|
577
|
-
} else if (action.target.port === 'preserve') {
|
|
578
|
-
targetPort = record.localPort;
|
|
579
|
-
} else {
|
|
580
|
-
targetPort = action.target.port;
|
|
581
|
-
}
|
|
609
|
+
// Update the connection record and context with resolved values
|
|
610
|
+
record.targetHost = targetHost;
|
|
611
|
+
record.targetPort = targetPort;
|
|
582
612
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
targetHost,
|
|
594
|
-
targetPort
|
|
595
|
-
);
|
|
613
|
+
return this.setupDirectConnection(
|
|
614
|
+
socket,
|
|
615
|
+
record,
|
|
616
|
+
record.lockedDomain,
|
|
617
|
+
initialChunk,
|
|
618
|
+
undefined,
|
|
619
|
+
targetHost,
|
|
620
|
+
targetPort
|
|
621
|
+
);
|
|
622
|
+
}
|
|
596
623
|
}
|
|
597
624
|
}
|
|
598
625
|
|
|
@@ -657,6 +684,71 @@ export class RouteConnectionHandler {
|
|
|
657
684
|
}, record);
|
|
658
685
|
}
|
|
659
686
|
|
|
687
|
+
/**
|
|
688
|
+
* Setup improved error handling for the outgoing connection
|
|
689
|
+
*/
|
|
690
|
+
private setupOutgoingErrorHandler(
|
|
691
|
+
connectionId: string,
|
|
692
|
+
targetSocket: plugins.net.Socket,
|
|
693
|
+
record: IConnectionRecord,
|
|
694
|
+
socket: plugins.net.Socket,
|
|
695
|
+
finalTargetHost: string,
|
|
696
|
+
finalTargetPort: number
|
|
697
|
+
): void {
|
|
698
|
+
targetSocket.once('error', (err) => {
|
|
699
|
+
// This handler runs only once during the initial connection phase
|
|
700
|
+
const code = (err as any).code;
|
|
701
|
+
console.log(
|
|
702
|
+
`[${connectionId}] Connection setup error to ${finalTargetHost}:${finalTargetPort}: ${err.message} (${code})`
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
// Resume the incoming socket to prevent it from hanging
|
|
706
|
+
socket.resume();
|
|
707
|
+
|
|
708
|
+
// Log specific error types for easier debugging
|
|
709
|
+
if (code === 'ECONNREFUSED') {
|
|
710
|
+
console.log(
|
|
711
|
+
`[${connectionId}] Target ${finalTargetHost}:${finalTargetPort} refused connection. ` +
|
|
712
|
+
`Check if the target service is running and listening on that port.`
|
|
713
|
+
);
|
|
714
|
+
} else if (code === 'ETIMEDOUT') {
|
|
715
|
+
console.log(
|
|
716
|
+
`[${connectionId}] Connection to ${finalTargetHost}:${finalTargetPort} timed out. ` +
|
|
717
|
+
`Check network conditions, firewall rules, or if the target is too far away.`
|
|
718
|
+
);
|
|
719
|
+
} else if (code === 'ECONNRESET') {
|
|
720
|
+
console.log(
|
|
721
|
+
`[${connectionId}] Connection to ${finalTargetHost}:${finalTargetPort} was reset. ` +
|
|
722
|
+
`The target might have closed the connection abruptly.`
|
|
723
|
+
);
|
|
724
|
+
} else if (code === 'EHOSTUNREACH') {
|
|
725
|
+
console.log(
|
|
726
|
+
`[${connectionId}] Host ${finalTargetHost} is unreachable. ` +
|
|
727
|
+
`Check DNS settings, network routing, or firewall rules.`
|
|
728
|
+
);
|
|
729
|
+
} else if (code === 'ENOTFOUND') {
|
|
730
|
+
console.log(
|
|
731
|
+
`[${connectionId}] DNS lookup failed for ${finalTargetHost}. ` +
|
|
732
|
+
`Check your DNS settings or if the hostname is correct.`
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
// Clear any existing error handler after connection phase
|
|
737
|
+
targetSocket.removeAllListeners('error');
|
|
738
|
+
|
|
739
|
+
// Re-add the normal error handler for established connections
|
|
740
|
+
targetSocket.on('error', this.connectionManager.handleError('outgoing', record));
|
|
741
|
+
|
|
742
|
+
if (record.outgoingTerminationReason === null) {
|
|
743
|
+
record.outgoingTerminationReason = 'connection_failed';
|
|
744
|
+
this.connectionManager.incrementTerminationStat('outgoing', 'connection_failed');
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Clean up the connection
|
|
748
|
+
this.connectionManager.initiateCleanupOnce(record, `connection_failed_${code}`);
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
|
|
660
752
|
/**
|
|
661
753
|
* Sets up a direct connection to the target
|
|
662
754
|
*/
|
|
@@ -702,108 +794,14 @@ export class RouteConnectionHandler {
|
|
|
702
794
|
connectionOptions.localAddress = record.remoteIP.replace('::ffff:', '');
|
|
703
795
|
}
|
|
704
796
|
|
|
705
|
-
//
|
|
706
|
-
const dataQueue: Buffer[] = [];
|
|
707
|
-
let queueSize = 0;
|
|
708
|
-
let processingQueue = false;
|
|
709
|
-
let drainPending = false;
|
|
710
|
-
let pipingEstablished = false;
|
|
711
|
-
|
|
712
|
-
// Pause the incoming socket to prevent buffer overflows
|
|
713
|
-
socket.pause();
|
|
714
|
-
|
|
715
|
-
// Function to safely process the data queue without losing events
|
|
716
|
-
const processDataQueue = () => {
|
|
717
|
-
if (processingQueue || dataQueue.length === 0 || pipingEstablished) return;
|
|
718
|
-
|
|
719
|
-
processingQueue = true;
|
|
720
|
-
|
|
721
|
-
try {
|
|
722
|
-
// Process all queued chunks with the current active handler
|
|
723
|
-
while (dataQueue.length > 0) {
|
|
724
|
-
const chunk = dataQueue.shift()!;
|
|
725
|
-
queueSize -= chunk.length;
|
|
726
|
-
|
|
727
|
-
// Once piping is established, we shouldn't get here,
|
|
728
|
-
// but just in case, pass to the outgoing socket directly
|
|
729
|
-
if (pipingEstablished && record.outgoing) {
|
|
730
|
-
record.outgoing.write(chunk);
|
|
731
|
-
continue;
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
// Track bytes received
|
|
735
|
-
record.bytesReceived += chunk.length;
|
|
736
|
-
|
|
737
|
-
// Check for TLS handshake
|
|
738
|
-
if (!record.isTLS && this.tlsManager.isTlsHandshake(chunk)) {
|
|
739
|
-
record.isTLS = true;
|
|
740
|
-
|
|
741
|
-
if (this.settings.enableTlsDebugLogging) {
|
|
742
|
-
console.log(
|
|
743
|
-
`[${connectionId}] TLS handshake detected in tempDataHandler, ${chunk.length} bytes`
|
|
744
|
-
);
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
// Check if adding this chunk would exceed the buffer limit
|
|
749
|
-
const newSize = record.pendingDataSize + chunk.length;
|
|
750
|
-
|
|
751
|
-
if (this.settings.maxPendingDataSize && newSize > this.settings.maxPendingDataSize) {
|
|
752
|
-
console.log(
|
|
753
|
-
`[${connectionId}] Buffer limit exceeded for connection from ${record.remoteIP}: ${newSize} bytes > ${this.settings.maxPendingDataSize} bytes`
|
|
754
|
-
);
|
|
755
|
-
socket.end(); // Gracefully close the socket
|
|
756
|
-
this.connectionManager.initiateCleanupOnce(record, 'buffer_limit_exceeded');
|
|
757
|
-
return;
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
// Buffer the chunk and update the size counter
|
|
761
|
-
record.pendingData.push(Buffer.from(chunk));
|
|
762
|
-
record.pendingDataSize = newSize;
|
|
763
|
-
this.timeoutManager.updateActivity(record);
|
|
764
|
-
}
|
|
765
|
-
} finally {
|
|
766
|
-
processingQueue = false;
|
|
767
|
-
|
|
768
|
-
// If there's a pending drain and we've processed everything,
|
|
769
|
-
// signal we're ready for more data if we haven't established piping yet
|
|
770
|
-
if (drainPending && dataQueue.length === 0 && !pipingEstablished) {
|
|
771
|
-
drainPending = false;
|
|
772
|
-
socket.resume();
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
};
|
|
776
|
-
|
|
777
|
-
// Unified data handler that safely queues incoming data
|
|
778
|
-
const safeDataHandler = (chunk: Buffer) => {
|
|
779
|
-
// If piping is already established, just let the pipe handle it
|
|
780
|
-
if (pipingEstablished) return;
|
|
781
|
-
|
|
782
|
-
// Add to our queue for orderly processing
|
|
783
|
-
dataQueue.push(Buffer.from(chunk)); // Make a copy to be safe
|
|
784
|
-
queueSize += chunk.length;
|
|
785
|
-
|
|
786
|
-
// If queue is getting large, pause socket until we catch up
|
|
787
|
-
if (this.settings.maxPendingDataSize && queueSize > this.settings.maxPendingDataSize * 0.8) {
|
|
788
|
-
socket.pause();
|
|
789
|
-
drainPending = true;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
// Process the queue
|
|
793
|
-
processDataQueue();
|
|
794
|
-
};
|
|
795
|
-
|
|
796
|
-
// Add our safe data handler
|
|
797
|
-
socket.on('data', safeDataHandler);
|
|
798
|
-
|
|
799
|
-
// Add initial chunk to pending data if present
|
|
797
|
+
// Store initial data if provided
|
|
800
798
|
if (initialChunk) {
|
|
801
799
|
record.bytesReceived += initialChunk.length;
|
|
802
800
|
record.pendingData.push(Buffer.from(initialChunk));
|
|
803
801
|
record.pendingDataSize = initialChunk.length;
|
|
804
802
|
}
|
|
805
803
|
|
|
806
|
-
// Create the target socket
|
|
804
|
+
// Create the target socket
|
|
807
805
|
const targetSocket = plugins.net.connect(connectionOptions);
|
|
808
806
|
record.outgoing = targetSocket;
|
|
809
807
|
record.outgoingStartTime = Date.now();
|
|
@@ -811,7 +809,7 @@ export class RouteConnectionHandler {
|
|
|
811
809
|
// Apply socket optimizations
|
|
812
810
|
targetSocket.setNoDelay(this.settings.noDelay);
|
|
813
811
|
|
|
814
|
-
// Apply keep-alive settings
|
|
812
|
+
// Apply keep-alive settings if enabled
|
|
815
813
|
if (this.settings.keepAlive) {
|
|
816
814
|
targetSocket.setKeepAlive(true, this.settings.keepAliveInitialDelay);
|
|
817
815
|
|
|
@@ -835,53 +833,15 @@ export class RouteConnectionHandler {
|
|
|
835
833
|
}
|
|
836
834
|
}
|
|
837
835
|
|
|
838
|
-
// Setup
|
|
839
|
-
|
|
840
|
-
// This handler runs only once during the initial connection phase
|
|
841
|
-
const code = (err as any).code;
|
|
842
|
-
console.log(
|
|
843
|
-
`[${connectionId}] Connection setup error to ${finalTargetHost}:${connectionOptions.port}: ${err.message} (${code})`
|
|
844
|
-
);
|
|
845
|
-
|
|
846
|
-
// Resume the incoming socket to prevent it from hanging
|
|
847
|
-
socket.resume();
|
|
836
|
+
// Setup improved error handling for outgoing connection
|
|
837
|
+
this.setupOutgoingErrorHandler(connectionId, targetSocket, record, socket, finalTargetHost, finalTargetPort);
|
|
848
838
|
|
|
849
|
-
|
|
850
|
-
console.log(
|
|
851
|
-
`[${connectionId}] Target ${finalTargetHost}:${connectionOptions.port} refused connection`
|
|
852
|
-
);
|
|
853
|
-
} else if (code === 'ETIMEDOUT') {
|
|
854
|
-
console.log(
|
|
855
|
-
`[${connectionId}] Connection to ${finalTargetHost}:${connectionOptions.port} timed out`
|
|
856
|
-
);
|
|
857
|
-
} else if (code === 'ECONNRESET') {
|
|
858
|
-
console.log(
|
|
859
|
-
`[${connectionId}] Connection to ${finalTargetHost}:${connectionOptions.port} was reset`
|
|
860
|
-
);
|
|
861
|
-
} else if (code === 'EHOSTUNREACH') {
|
|
862
|
-
console.log(`[${connectionId}] Host ${finalTargetHost} is unreachable`);
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
// Clear any existing error handler after connection phase
|
|
866
|
-
targetSocket.removeAllListeners('error');
|
|
867
|
-
|
|
868
|
-
// Re-add the normal error handler for established connections
|
|
869
|
-
targetSocket.on('error', this.connectionManager.handleError('outgoing', record));
|
|
870
|
-
|
|
871
|
-
if (record.outgoingTerminationReason === null) {
|
|
872
|
-
record.outgoingTerminationReason = 'connection_failed';
|
|
873
|
-
this.connectionManager.incrementTerminationStat('outgoing', 'connection_failed');
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
// Route-based configuration doesn't use domain handlers
|
|
877
|
-
|
|
878
|
-
// Clean up the connection
|
|
879
|
-
this.connectionManager.initiateCleanupOnce(record, `connection_failed_${code}`);
|
|
880
|
-
});
|
|
881
|
-
|
|
882
|
-
// Setup close handler
|
|
839
|
+
// Setup close handlers
|
|
883
840
|
targetSocket.on('close', this.connectionManager.handleClose('outgoing', record));
|
|
884
841
|
socket.on('close', this.connectionManager.handleClose('incoming', record));
|
|
842
|
+
|
|
843
|
+
// Setup error handlers for incoming socket
|
|
844
|
+
socket.on('error', this.connectionManager.handleError('incoming', record));
|
|
885
845
|
|
|
886
846
|
// Handle timeouts with keep-alive awareness
|
|
887
847
|
socket.on('timeout', () => {
|
|
@@ -947,19 +907,19 @@ export class RouteConnectionHandler {
|
|
|
947
907
|
|
|
948
908
|
// Wait for the outgoing connection to be ready before setting up piping
|
|
949
909
|
targetSocket.once('connect', () => {
|
|
910
|
+
if (this.settings.enableDetailedLogging) {
|
|
911
|
+
console.log(
|
|
912
|
+
`[${connectionId}] Connection established to target: ${finalTargetHost}:${finalTargetPort}`
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
|
|
950
916
|
// Clear the initial connection error handler
|
|
951
917
|
targetSocket.removeAllListeners('error');
|
|
952
918
|
|
|
953
919
|
// Add the normal error handler for established connections
|
|
954
920
|
targetSocket.on('error', this.connectionManager.handleError('outgoing', record));
|
|
955
921
|
|
|
956
|
-
//
|
|
957
|
-
processDataQueue();
|
|
958
|
-
|
|
959
|
-
// Set up piping immediately
|
|
960
|
-
pipingEstablished = true;
|
|
961
|
-
|
|
962
|
-
// Flush all pending data to target
|
|
922
|
+
// Flush any pending data to target
|
|
963
923
|
if (record.pendingData.length > 0) {
|
|
964
924
|
const combinedData = Buffer.concat(record.pendingData);
|
|
965
925
|
|
|
@@ -982,52 +942,29 @@ export class RouteConnectionHandler {
|
|
|
982
942
|
record.pendingDataSize = 0;
|
|
983
943
|
}
|
|
984
944
|
|
|
985
|
-
//
|
|
945
|
+
// Immediately setup bidirectional piping - much simpler than manual data management
|
|
986
946
|
socket.pipe(targetSocket);
|
|
987
947
|
targetSocket.pipe(socket);
|
|
988
948
|
|
|
989
|
-
//
|
|
990
|
-
socket.
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
// Write any remaining queued data directly to the target socket
|
|
995
|
-
for (const chunk of dataQueue) {
|
|
996
|
-
targetSocket.write(chunk);
|
|
997
|
-
}
|
|
998
|
-
// Clear the queue
|
|
999
|
-
dataQueue.length = 0;
|
|
1000
|
-
queueSize = 0;
|
|
1001
|
-
}
|
|
949
|
+
// Track incoming data for bytes counting - do this after piping is set up
|
|
950
|
+
socket.on('data', (chunk: Buffer) => {
|
|
951
|
+
record.bytesReceived += chunk.length;
|
|
952
|
+
this.timeoutManager.updateActivity(record);
|
|
953
|
+
});
|
|
1002
954
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
record.hasKeepAlive ? 'Yes' : 'No'
|
|
1015
|
-
}`
|
|
1016
|
-
);
|
|
1017
|
-
} else {
|
|
1018
|
-
console.log(
|
|
1019
|
-
`Connection established: ${record.remoteIP} -> ${finalTargetHost}:${connectionOptions.port}` +
|
|
1020
|
-
`${
|
|
1021
|
-
serverName
|
|
1022
|
-
? ` (SNI: ${serverName})`
|
|
1023
|
-
: record.lockedDomain
|
|
1024
|
-
? ` (Domain: ${record.lockedDomain})`
|
|
1025
|
-
: ''
|
|
1026
|
-
}`
|
|
1027
|
-
);
|
|
1028
|
-
}
|
|
955
|
+
// Log successful connection
|
|
956
|
+
console.log(
|
|
957
|
+
`Connection established: ${record.remoteIP} -> ${finalTargetHost}:${finalTargetPort}` +
|
|
958
|
+
`${
|
|
959
|
+
serverName
|
|
960
|
+
? ` (SNI: ${serverName})`
|
|
961
|
+
: record.lockedDomain
|
|
962
|
+
? ` (Domain: ${record.lockedDomain})`
|
|
963
|
+
: ''
|
|
964
|
+
}`
|
|
965
|
+
);
|
|
1029
966
|
|
|
1030
|
-
// Add
|
|
967
|
+
// Add TLS renegotiation handler if needed
|
|
1031
968
|
if (serverName) {
|
|
1032
969
|
// Create connection info object for the existing connection
|
|
1033
970
|
const connInfo = {
|
|
@@ -1055,11 +992,6 @@ export class RouteConnectionHandler {
|
|
|
1055
992
|
console.log(
|
|
1056
993
|
`[${connectionId}] TLS renegotiation handler installed for SNI domain: ${serverName}`
|
|
1057
994
|
);
|
|
1058
|
-
if (this.settings.allowSessionTicket === false) {
|
|
1059
|
-
console.log(
|
|
1060
|
-
`[${connectionId}] Session ticket usage is disabled. Connection will be reset on reconnection attempts.`
|
|
1061
|
-
);
|
|
1062
|
-
}
|
|
1063
995
|
}
|
|
1064
996
|
}
|
|
1065
997
|
|
|
@@ -1074,14 +1006,7 @@ export class RouteConnectionHandler {
|
|
|
1074
1006
|
// Mark TLS handshake as complete for TLS connections
|
|
1075
1007
|
if (record.isTLS) {
|
|
1076
1008
|
record.tlsHandshakeComplete = true;
|
|
1077
|
-
|
|
1078
|
-
if (this.settings.enableTlsDebugLogging) {
|
|
1079
|
-
console.log(
|
|
1080
|
-
`[${connectionId}] TLS handshake complete for connection from ${record.remoteIP}`
|
|
1081
|
-
);
|
|
1082
|
-
}
|
|
1083
1009
|
}
|
|
1084
1010
|
});
|
|
1085
1011
|
}
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1012
|
+
}
|
|
@@ -338,10 +338,19 @@ export class RouteManager extends plugins.EventEmitter {
|
|
|
338
338
|
|
|
339
339
|
// Find the first matching route based on priority order
|
|
340
340
|
for (const route of routesForPort) {
|
|
341
|
-
// Check domain match
|
|
342
|
-
|
|
343
|
-
|
|
341
|
+
// Check domain match
|
|
342
|
+
// If the route has domain restrictions and we have a domain to check
|
|
343
|
+
if (route.match.domains) {
|
|
344
|
+
// If no domain was provided (non-TLS or no SNI), this route doesn't match
|
|
345
|
+
if (!domain) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
// If domain is provided but doesn't match the route's domains, skip
|
|
349
|
+
if (!this.matchRouteDomain(route, domain)) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
344
352
|
}
|
|
353
|
+
// If route has no domain restrictions, it matches all domains
|
|
345
354
|
|
|
346
355
|
// Check path match if specified in both route and request
|
|
347
356
|
if (path && route.match.path) {
|