Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
2b69150545 | |||
85cc57ae10 | |||
e021b66898 | |||
865d21b36a | |||
58ba0d9362 | |||
ccccc5b8c8 | |||
d8466a866c | |||
119b643690 | |||
98f1e0df4c | |||
d6022c8f8a | |||
0ea0f02428 | |||
e452f55203 | |||
55f25f1976 | |||
98b7f3ed7f | |||
cb83caeafd | |||
7850a80452 | |||
ef8f583a90 | |||
2bdd6f8c1f | |||
99d28eafd1 | |||
788b444fcc | |||
4225abe3c4 | |||
74fdb58f84 | |||
bffdaffe39 | |||
67a4228518 | |||
681209f2e1 | |||
c415a6c361 | |||
009e3c4f0e | |||
f9c42975dc | |||
feef949afe | |||
8d3b07b1e6 | |||
51fe935f1f | |||
146fac73cf |
114
changelog.md
114
changelog.md
@ -1,5 +1,119 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-03-11 - 3.32.2 - fix(PortProxy)
|
||||
Simplify TLS handshake SNI extraction and update timeout settings in PortProxy for improved maintainability and reliability.
|
||||
|
||||
- Removed legacy and deprecated fields related to chained proxy configurations (isChainedProxy, chainPosition, aggressiveTlsRefresh).
|
||||
- Refactored the extractSNI functions to use a simpler, more robust approach for TLS ClientHello processing.
|
||||
- Adjusted default timeout and keep-alive settings to more standard values (e.g. initialDataTimeout set to 60s, socketTimeout to 1h).
|
||||
- Eliminated redundant TLS session cache and deep TLS refresh logic.
|
||||
- Improved logging and error handling during connection setup and renegotiation phases.
|
||||
|
||||
## 2025-03-11 - 3.32.1 - fix(portproxy)
|
||||
Relax TLS handshake and connection timeout settings for improved stability in chained proxy scenarios; update TLS session cache defaults and add keep-alive flags to connection records.
|
||||
|
||||
- Increased TLS session cache maximum entries from 10,000 to 20,000, expiry time from 24 hours to 7 days, and cleanup interval from 10 minutes to 30 minutes
|
||||
- Relaxed socket timeouts: standalone connections now use up to 6 hours, with chained proxies adjusted for 5–6 hours based on proxy position
|
||||
- Updated inactivity, connection, and initial handshake timeouts to provide a more relaxed behavior under high-traffic chained proxy scenarios
|
||||
- Increased keepAliveInitialDelay from 10 seconds to 30 seconds and introduced separate incoming and outgoing keep-alive flags
|
||||
- Enhanced TLS renegotiation handling with more detailed logging and temporary processing flags to avoid duplicate processing
|
||||
- Updated NetworkProxy integration to use optimized connection settings and more aggressive application-level keep-alive probes
|
||||
|
||||
## 2025-03-11 - 3.32.0 - feat(PortProxy)
|
||||
Enhance TLS session cache, SNI extraction, and chained proxy support in PortProxy. Improve handling of multiple and fragmented TLS records, and add new configuration options (isChainedProxy, chainPosition, aggressiveTlsRefresh, tlsSessionCache) for robust TLS certificate refresh.
|
||||
|
||||
- Implement TlsSessionCache with configurable cleanup, eviction, and statistics.
|
||||
- Improve extractSNIInfo to process multiple TLS records and partial handshake data.
|
||||
- Add new settings to detect chained proxy scenarios and adjust timeouts accordingly.
|
||||
- Enhance TLS state refresh with aggressive probing and deep refresh sequence.
|
||||
|
||||
## 2025-03-11 - 3.31.2 - fix(PortProxy)
|
||||
Improve SNI renegotiation handling by adding flexible domain configuration matching on rehandshake and session resumption events.
|
||||
|
||||
- When a rehandshake is detected with a changed SNI, first check existing domain config rules and log if allowed.
|
||||
- If the exact domain config is not found, additionally attempt flexible matching using parent domain and wildcard patterns.
|
||||
- For resumed sessions, try an exact match first and then use fallback logic to select a similar domain config based on matching target IP.
|
||||
- Enhanced logging added to help diagnose missing or mismatched domain configurations.
|
||||
|
||||
## 2025-03-11 - 3.31.1 - fix(PortProxy)
|
||||
Improve TLS handshake buffering and enhance debug logging for SNI forwarding in PortProxy
|
||||
|
||||
- Explicitly copy the initial TLS handshake data to prevent mutation before buffering
|
||||
- Log buffered TLS handshake data with SNI information for better diagnostics
|
||||
- Add detailed error logs on TLS connection failures, including server and domain config status
|
||||
- Output additional debug messages during ClientHello forwarding to verify proper TLS handshake processing
|
||||
|
||||
## 2025-03-11 - 3.31.0 - feat(PortProxy)
|
||||
Improve TLS handshake SNI extraction and add session resumption tracking in PortProxy
|
||||
|
||||
- Added ITlsSessionInfo interface and a global tlsSessionCache to track TLS session IDs for session resumption
|
||||
- Implemented a cleanup timer for the TLS session cache with startSessionCleanupTimer and stopSessionCleanupTimer
|
||||
- Enhanced extractSNIInfo to return detailed SNI information including session IDs, ticket details, and resumption status
|
||||
- Updated renegotiation handlers to use extractSNIInfo for proper SNI extraction during TLS rehandshake
|
||||
|
||||
## 2025-03-11 - 3.30.8 - fix(core)
|
||||
No changes in this commit.
|
||||
|
||||
|
||||
## 2025-03-11 - 3.30.7 - fix(PortProxy)
|
||||
Improve TLS renegotiation SNI handling by first checking if the new SNI is allowed under the existing domain config. If not, attempt to find an alternative domain config and update the locked domain accordingly; otherwise, terminate the connection on SNI mismatch.
|
||||
|
||||
- Added a preliminary check against the original domain config to allow re-handshakes if the new SNI matches allowed patterns.
|
||||
- If the original config does not allow, search for an alternative domain config and validate IP rules.
|
||||
- Update the locked domain when allowed, ensuring connection reuse with valid certificate context.
|
||||
- Terminate the connection if no suitable domain config is found or IP restrictions are violated.
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
## 2025-03-10 - 3.30.4 - fix(PortProxy)
|
||||
Fix TLS renegotiation handling and adjust TLS keep-alive timeouts in PortProxy implementation
|
||||
|
||||
- Allow TLS renegotiation data without an explicit SNI extraction to pass through, ensuring valid renegotiations are not dropped (critical for Chrome).
|
||||
- Update TLS keep-alive timeout from an aggressive 30 minutes to a more generous 4 hours to reduce unnecessary reconnections.
|
||||
- Increase inactivity thresholds for TLS connections from 20 minutes to 2 hours with an additional verification interval extended from 5 to 15 minutes.
|
||||
- Adjust long-lived TLS connection timeout from 45 minutes to 8 hours for improved certificate context refresh in chained proxy scenarios.
|
||||
|
||||
## 2025-03-10 - 3.30.3 - fix(classes.portproxy.ts)
|
||||
Simplify timeout management in PortProxy and fix chained proxy certificate refresh issues
|
||||
|
||||
- Reduced TLS keep-alive timeout from 8 hours to 30 minutes to ensure frequent certificate refresh
|
||||
- Added aggressive TLS state refresh after 20 minutes of inactivity and secondary verification checks
|
||||
- Lowered long-lived TLS connection lifetime from 12 hours to 45 minutes to prevent stale certificates
|
||||
- Removed configurable timeout settings from the public API in favor of hardcoded sensible defaults
|
||||
- Simplified internal timeout management to reduce code complexity and improve certificate handling in chained proxies
|
||||
|
||||
## 2025-03-10 - 3.31.0 - fix(classes.portproxy.ts)
|
||||
Simplified timeout management and fixed certificate issues in chained proxy scenarios
|
||||
|
||||
- Dramatically reduced TLS keep-alive timeout from 8 hours to 30 minutes to ensure fresh certificates
|
||||
- Added aggressive certificate refresh after 20 minutes of inactivity (down from 4 hours)
|
||||
- Added secondary verification checks for TLS refresh operations
|
||||
- Reduced long-lived TLS connection lifetime from 12 hours to 45 minutes
|
||||
- Removed configurable timeouts completely from the public API in favor of hardcoded sensible defaults
|
||||
- Simplified interface by removing no-longer-configurable settings while maintaining internal compatibility
|
||||
- Reduced overall code complexity by eliminating complex timeout management
|
||||
- Fixed chained proxy certificate issues by ensuring more frequent certificate refreshes in all deployment scenarios
|
||||
|
||||
## 2025-03-10 - 3.30.2 - fix(classes.portproxy.ts)
|
||||
Adjust TLS keep-alive timeout to refresh certificate context.
|
||||
|
||||
- Modified TLS keep-alive timeout for connections to 8 hours to refresh certificate context.
|
||||
- Updated timeout log messages for clarity on TLS certificate refresh.
|
||||
|
||||
## 2025-03-10 - 3.30.1 - fix(PortProxy)
|
||||
Improve TLS keep-alive management and fix whitespace formatting
|
||||
|
||||
- Implemented better handling for TLS keep-alive connections after sleep or long inactivity.
|
||||
- Reformatted whitespace for better readability and consistency.
|
||||
|
||||
## 2025-03-08 - 3.30.0 - feat(PortProxy)
|
||||
Add advanced TLS keep-alive handling and system sleep detection
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@push.rocks/smartproxy",
|
||||
"version": "3.30.0",
|
||||
"version": "3.32.2",
|
||||
"private": false,
|
||||
"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.",
|
||||
"main": "dist_ts/index.js",
|
||||
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartproxy',
|
||||
version: '3.30.0',
|
||||
version: '3.32.2',
|
||||
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.'
|
||||
}
|
||||
|
@ -100,10 +100,6 @@ interface IConnectionRecord {
|
||||
// New field for NetworkProxy tracking
|
||||
usingNetworkProxy?: boolean; // Whether this connection is using a NetworkProxy
|
||||
networkProxyIndex?: number; // Which NetworkProxy instance is being used
|
||||
|
||||
// Sleep detection fields
|
||||
possibleSystemSleep?: boolean; // Flag to indicate a possible system sleep was detected
|
||||
lastSleepDetection?: number; // Timestamp of the last sleep detection
|
||||
}
|
||||
|
||||
/**
|
||||
@ -485,21 +481,7 @@ export class PortProxy {
|
||||
});
|
||||
|
||||
// Update activity on data transfer
|
||||
socket.on('data', (chunk: Buffer) => {
|
||||
this.updateActivity(record);
|
||||
|
||||
// Check for potential TLS renegotiation or reconnection packets
|
||||
if (chunk.length > 0 && chunk[0] === 22) { // ContentType.handshake
|
||||
if (this.settings.enableDetailedLogging) {
|
||||
console.log(`[${connectionId}] Detected potential TLS handshake data while connected to NetworkProxy`);
|
||||
}
|
||||
|
||||
// Let the NetworkProxy handle the TLS renegotiation
|
||||
// Just update the activity timestamp to prevent timeouts
|
||||
record.lastActivity = Date.now();
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('data', () => this.updateActivity(record));
|
||||
proxySocket.on('data', () => this.updateActivity(record));
|
||||
|
||||
if (this.settings.enableDetailedLogging) {
|
||||
@ -853,31 +835,6 @@ export class PortProxy {
|
||||
}
|
||||
// No cleanup timer for immortal connections
|
||||
}
|
||||
// For TLS keep-alive connections, use a very extended timeout
|
||||
else if (record.hasKeepAlive && record.isTLS) {
|
||||
// For TLS keep-alive connections, use a very extended timeout
|
||||
// This helps prevent certificate errors after sleep/wake cycles
|
||||
const tlsKeepAliveTimeout = 14 * 24 * 60 * 60 * 1000; // 14 days for TLS keep-alive
|
||||
const safeTimeout = ensureSafeTimeout(tlsKeepAliveTimeout);
|
||||
|
||||
record.cleanupTimer = setTimeout(() => {
|
||||
console.log(
|
||||
`[${connectionId}] TLS keep-alive connection from ${record.remoteIP} exceeded extended lifetime (${plugins.prettyMs(
|
||||
tlsKeepAliveTimeout
|
||||
)}), forcing cleanup.`
|
||||
);
|
||||
this.initiateCleanupOnce(record, 'tls_extended_lifetime');
|
||||
}, safeTimeout);
|
||||
|
||||
// Make sure timeout doesn't keep the process alive
|
||||
if (record.cleanupTimer.unref) {
|
||||
record.cleanupTimer.unref();
|
||||
}
|
||||
|
||||
if (this.settings.enableDetailedLogging) {
|
||||
console.log(`[${connectionId}] TLS keep-alive connection with enhanced protection, lifetime: ${plugins.prettyMs(tlsKeepAliveTimeout)}`);
|
||||
}
|
||||
}
|
||||
// For extended keep-alive connections, use extended timeout
|
||||
else if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'extended') {
|
||||
const extendedTimeout = this.settings.extendedKeepAliveLifetime || 7 * 24 * 60 * 60 * 1000; // 7 days
|
||||
@ -993,74 +950,6 @@ export class PortProxy {
|
||||
this.terminationStats[side][reason] = (this.terminationStats[side][reason] || 0) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update connection activity timestamp with sleep detection
|
||||
*/
|
||||
private updateActivity(record: IConnectionRecord): void {
|
||||
// Get the current time
|
||||
const now = Date.now();
|
||||
|
||||
// Check if there was a large time gap that suggests system sleep
|
||||
if (record.lastActivity > 0) {
|
||||
const timeDiff = now - record.lastActivity;
|
||||
|
||||
// If time difference is very large (> 30 minutes) and this is a keep-alive connection,
|
||||
// this might indicate system sleep rather than just inactivity
|
||||
if (timeDiff > 30 * 60 * 1000 && record.hasKeepAlive) {
|
||||
if (this.settings.enableDetailedLogging) {
|
||||
console.log(
|
||||
`[${record.id}] Detected possible system sleep for ${plugins.prettyMs(timeDiff)}. ` +
|
||||
`Preserving keep-alive connection.`
|
||||
);
|
||||
}
|
||||
|
||||
// For keep-alive connections after sleep, we should refresh the TLS state if needed
|
||||
if (record.isTLS && record.tlsHandshakeComplete) {
|
||||
this.refreshTlsStateAfterSleep(record);
|
||||
}
|
||||
|
||||
// Mark that we detected sleep
|
||||
record.possibleSystemSleep = true;
|
||||
record.lastSleepDetection = now;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the activity timestamp
|
||||
record.lastActivity = now;
|
||||
|
||||
// Clear any inactivity warning
|
||||
if (record.inactivityWarningIssued) {
|
||||
record.inactivityWarningIssued = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh TLS state after sleep detection
|
||||
*/
|
||||
private refreshTlsStateAfterSleep(record: IConnectionRecord): void {
|
||||
// Skip if we're using a NetworkProxy as it handles its own TLS state
|
||||
if (record.usingNetworkProxy) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// For outgoing connections that might need to be refreshed
|
||||
if (record.outgoing && !record.outgoing.destroyed) {
|
||||
// Send a zero-byte packet to test the connection
|
||||
record.outgoing.write(Buffer.alloc(0));
|
||||
|
||||
if (this.settings.enableDetailedLogging) {
|
||||
console.log(`[${record.id}] Sent refresh packet after sleep detection`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(`[${record.id}] Error refreshing TLS state: ${err}`);
|
||||
|
||||
// If we can't refresh, don't terminate - client will re-establish if needed
|
||||
// Just log the issue but preserve the connection
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up a connection record.
|
||||
* Destroys both incoming and outgoing sockets, clears timers, and removes the record.
|
||||
@ -1169,6 +1058,18 @@ export class PortProxy {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update connection activity timestamp
|
||||
*/
|
||||
private updateActivity(record: IConnectionRecord): void {
|
||||
record.lastActivity = Date.now();
|
||||
|
||||
// Clear any inactivity warning
|
||||
if (record.inactivityWarningIssued) {
|
||||
record.inactivityWarningIssued = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get target IP with round-robin support
|
||||
*/
|
||||
@ -1344,10 +1245,7 @@ export class PortProxy {
|
||||
outgoingTerminationReason: null,
|
||||
|
||||
// Initialize NetworkProxy tracking fields
|
||||
usingNetworkProxy: false,
|
||||
|
||||
// Initialize sleep detection fields
|
||||
possibleSystemSleep: false
|
||||
usingNetworkProxy: false
|
||||
};
|
||||
|
||||
// Apply keep-alive settings if enabled
|
||||
@ -1813,42 +1711,6 @@ export class PortProxy {
|
||||
|
||||
const inactivityTime = now - record.lastActivity;
|
||||
|
||||
// Special handling for TLS keep-alive connections
|
||||
if (record.hasKeepAlive && record.isTLS && inactivityTime > this.settings.inactivityTimeout! / 2) {
|
||||
// For TLS keep-alive connections that are getting stale, try to refresh before closing
|
||||
if (!record.inactivityWarningIssued) {
|
||||
console.log(
|
||||
`[${id}] TLS keep-alive connection from ${record.remoteIP} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
||||
`Attempting to preserve connection.`
|
||||
);
|
||||
|
||||
// Set warning flag but give a much longer grace period for TLS connections
|
||||
record.inactivityWarningIssued = true;
|
||||
|
||||
// For TLS connections, extend the last activity time considerably
|
||||
// This gives browsers more time to re-establish the connection properly
|
||||
record.lastActivity = now - (this.settings.inactivityTimeout! / 3);
|
||||
|
||||
// Try to stimulate the connection with a probe packet
|
||||
if (record.outgoing && !record.outgoing.destroyed) {
|
||||
try {
|
||||
// For TLS connections, send a proper TLS heartbeat-like packet
|
||||
// This is just a small empty buffer that won't affect the TLS session
|
||||
record.outgoing.write(Buffer.alloc(0));
|
||||
|
||||
if (this.settings.enableDetailedLogging) {
|
||||
console.log(`[${id}] Sent TLS keep-alive probe packet`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(`[${id}] Error sending TLS probe packet: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't proceed to the normal inactivity check logic
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Use extended timeout for extended-treatment keep-alive connections
|
||||
let effectiveTimeout = this.settings.inactivityTimeout!;
|
||||
if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'extended') {
|
||||
@ -1881,26 +1743,13 @@ export class PortProxy {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// MODIFIED: For TLS connections, be more lenient before closing
|
||||
if (record.isTLS && record.hasKeepAlive) {
|
||||
// For TLS keep-alive connections, add additional grace period
|
||||
// This helps with browsers reconnecting after sleep
|
||||
console.log(
|
||||
`[${id}] TLS keep-alive connection from ${record.remoteIP} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
||||
`Adding extra grace period.`
|
||||
);
|
||||
|
||||
// Give additional time for browsers to reconnect properly
|
||||
record.lastActivity = now - (effectiveTimeout / 2);
|
||||
} else {
|
||||
// For non-keep-alive or after warning, close the connection
|
||||
console.log(
|
||||
`[${id}] Inactivity check: No activity on connection from ${record.remoteIP} ` +
|
||||
`for ${plugins.prettyMs(inactivityTime)}.` +
|
||||
(record.hasKeepAlive ? ' Despite keep-alive being enabled.' : '')
|
||||
);
|
||||
this.cleanupConnection(record, 'inactivity');
|
||||
}
|
||||
// For non-keep-alive or after warning, close the connection
|
||||
console.log(
|
||||
`[${id}] Inactivity check: No activity on connection from ${record.remoteIP} ` +
|
||||
`for ${plugins.prettyMs(inactivityTime)}.` +
|
||||
(record.hasKeepAlive ? ' Despite keep-alive being enabled.' : '')
|
||||
);
|
||||
this.cleanupConnection(record, 'inactivity');
|
||||
}
|
||||
} else if (inactivityTime <= effectiveTimeout && record.inactivityWarningIssued) {
|
||||
// If activity detected after warning, clear the warning
|
||||
|
Reference in New Issue
Block a user