From 74fdb58f8439bc9880d92c4385336cd0e39fbf59 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Tue, 11 Mar 2025 02:18:56 +0000 Subject: [PATCH] fix(PortProxy): Improve TLS renegotiation handling in PortProxy by validating the new SNI against allowed domain configurations. If the new SNI is permitted based on existing IP rules, update the locked domain to allow connection reuse; otherwise, terminate the connection to prevent misrouting. --- changelog.md | 6 ++++++ ts/00_commitinfo_data.ts | 2 +- ts/classes.portproxy.ts | 39 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index 525e0b1..287a1da 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # Changelog +## 2025-03-11 - 3.30.6 - fix(PortProxy) +Improve TLS renegotiation handling in PortProxy by validating the new SNI against allowed domain configurations. If the new SNI is permitted based on existing IP rules, update the locked domain to allow connection reuse; otherwise, terminate the connection to prevent misrouting. + +- Added logic to check if a new SNI during renegotiation is allowed by comparing IP rules from the matching domain configuration. +- Updated detailed logging to indicate when a valid SNI change is accepted and when it results in a mismatch termination. + ## 2025-03-10 - 3.30.5 - fix(internal) No uncommitted changes detected; project files and tests remain unchanged. diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 07e8f52..187b3f6 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartproxy', - version: '3.30.5', + version: '3.30.6', description: 'A powerful proxy package that effectively handles high traffic, with features such as SSL/TLS support, port proxying, WebSocket handling, and dynamic routing with authentication options.' } diff --git a/ts/classes.portproxy.ts b/ts/classes.portproxy.ts index 55b9f4e..ac5459d 100644 --- a/ts/classes.portproxy.ts +++ b/ts/classes.portproxy.ts @@ -871,10 +871,45 @@ export class PortProxy { return; } - // Only block if we positively identify a different SNI + // Check if the SNI has changed if (newSNI && newSNI !== record.lockedDomain) { + // Instead of immediately terminating, check if the new SNI would be allowed + // by the same ruleset that allowed the initial connection + const newDomainConfig = this.settings.domainConfigs.find((config) => + config.domains.some((d) => plugins.minimatch(newSNI, d)) + ); + + // If we found a matching domain config, check IP rules + if (newDomainConfig) { + const effectiveAllowedIPs = [ + ...newDomainConfig.allowedIPs, + ...(this.settings.defaultAllowedIPs || []), + ]; + const effectiveBlockedIPs = [ + ...(newDomainConfig.blockedIPs || []), + ...(this.settings.defaultBlockedIPs || []), + ]; + + // Check if the IP is allowed for the new domain + if (isGlobIPAllowed(record.remoteIP, effectiveAllowedIPs, effectiveBlockedIPs)) { + // Allow the domain switch - Chrome is reusing the connection for a different domain + if (this.settings.enableDetailedLogging) { + console.log( + `[${connectionId}] Rehandshake with new SNI: ${newSNI} (previously ${record.lockedDomain}). ` + + `New domain is allowed by rules, permitting connection reuse.` + ); + } + + // Update the locked domain to the new domain + record.lockedDomain = newSNI; + return; + } + } + + // If we get here, either no matching domain config was found or the IP is not allowed console.log( - `[${connectionId}] Rehandshake detected with different SNI: ${newSNI} vs locked ${record.lockedDomain}. Terminating connection.` + `[${connectionId}] Rehandshake detected with different SNI: ${newSNI} vs locked ${record.lockedDomain}. ` + + `New domain not allowed by rules. Terminating connection.` ); this.initiateCleanupOnce(record, 'sni_mismatch'); } else if (newSNI && this.settings.enableDetailedLogging) {