fix(PortProxy): Improve TLS keep-alive management and fix whitespace formatting
This commit is contained in:
parent
4465cac807
commit
146fac73cf
@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 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)
|
## 2025-03-08 - 3.30.0 - feat(PortProxy)
|
||||||
Add advanced TLS keep-alive handling and system sleep detection
|
Add advanced TLS keep-alive handling and system sleep detection
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartproxy',
|
name: '@push.rocks/smartproxy',
|
||||||
version: '3.30.0',
|
version: '3.30.1',
|
||||||
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.'
|
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.'
|
||||||
}
|
}
|
||||||
|
@ -379,8 +379,8 @@ export class PortProxy {
|
|||||||
|
|
||||||
// Feature flags
|
// Feature flags
|
||||||
disableInactivityCheck: settingsArg.disableInactivityCheck || false,
|
disableInactivityCheck: settingsArg.disableInactivityCheck || false,
|
||||||
enableKeepAliveProbes: settingsArg.enableKeepAliveProbes !== undefined
|
enableKeepAliveProbes:
|
||||||
? settingsArg.enableKeepAliveProbes : true, // Enable by default
|
settingsArg.enableKeepAliveProbes !== undefined ? settingsArg.enableKeepAliveProbes : true, // Enable by default
|
||||||
enableDetailedLogging: settingsArg.enableDetailedLogging || false,
|
enableDetailedLogging: settingsArg.enableDetailedLogging || false,
|
||||||
enableTlsDebugLogging: settingsArg.enableTlsDebugLogging || false,
|
enableTlsDebugLogging: settingsArg.enableTlsDebugLogging || false,
|
||||||
enableRandomizedTimeouts: settingsArg.enableRandomizedTimeouts || false, // Disable randomization by default
|
enableRandomizedTimeouts: settingsArg.enableRandomizedTimeouts || false, // Disable randomization by default
|
||||||
@ -417,15 +417,23 @@ export class PortProxy {
|
|||||||
serverName?: string
|
serverName?: string
|
||||||
): void {
|
): void {
|
||||||
// Determine which NetworkProxy to use
|
// Determine which NetworkProxy to use
|
||||||
const proxyIndex = domainConfig.networkProxyIndex !== undefined
|
const proxyIndex =
|
||||||
? domainConfig.networkProxyIndex
|
domainConfig.networkProxyIndex !== undefined ? domainConfig.networkProxyIndex : 0;
|
||||||
: 0;
|
|
||||||
|
|
||||||
// Validate the NetworkProxy index
|
// Validate the NetworkProxy index
|
||||||
if (proxyIndex < 0 || proxyIndex >= this.networkProxies.length) {
|
if (proxyIndex < 0 || proxyIndex >= this.networkProxies.length) {
|
||||||
console.log(`[${connectionId}] Invalid NetworkProxy index: ${proxyIndex}. Using fallback direct connection.`);
|
console.log(
|
||||||
|
`[${connectionId}] Invalid NetworkProxy index: ${proxyIndex}. Using fallback direct connection.`
|
||||||
|
);
|
||||||
// Fall back to direct connection
|
// Fall back to direct connection
|
||||||
return this.setupDirectConnection(connectionId, socket, record, domainConfig, serverName, initialData);
|
return this.setupDirectConnection(
|
||||||
|
connectionId,
|
||||||
|
socket,
|
||||||
|
record,
|
||||||
|
domainConfig,
|
||||||
|
serverName,
|
||||||
|
initialData
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const networkProxy = this.networkProxies[proxyIndex];
|
const networkProxy = this.networkProxies[proxyIndex];
|
||||||
@ -441,7 +449,7 @@ export class PortProxy {
|
|||||||
// Create a connection to the NetworkProxy
|
// Create a connection to the NetworkProxy
|
||||||
const proxySocket = plugins.net.connect({
|
const proxySocket = plugins.net.connect({
|
||||||
host: proxyHost,
|
host: proxyHost,
|
||||||
port: proxyPort
|
port: proxyPort,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Store the outgoing socket in the record
|
// Store the outgoing socket in the record
|
||||||
@ -479,7 +487,9 @@ export class PortProxy {
|
|||||||
|
|
||||||
socket.on('close', () => {
|
socket.on('close', () => {
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${connectionId}] Client connection closed after forwarding to NetworkProxy`);
|
console.log(
|
||||||
|
`[${connectionId}] Client connection closed after forwarding to NetworkProxy`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this.cleanupConnection(record, 'client_closed');
|
this.cleanupConnection(record, 'client_closed');
|
||||||
});
|
});
|
||||||
@ -489,9 +499,12 @@ export class PortProxy {
|
|||||||
this.updateActivity(record);
|
this.updateActivity(record);
|
||||||
|
|
||||||
// Check for potential TLS renegotiation or reconnection packets
|
// Check for potential TLS renegotiation or reconnection packets
|
||||||
if (chunk.length > 0 && chunk[0] === 22) { // ContentType.handshake
|
if (chunk.length > 0 && chunk[0] === 22) {
|
||||||
|
// ContentType.handshake
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${connectionId}] Detected potential TLS handshake data while connected to NetworkProxy`);
|
console.log(
|
||||||
|
`[${connectionId}] Detected potential TLS handshake data while connected to NetworkProxy`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the NetworkProxy handle the TLS renegotiation
|
// Let the NetworkProxy handle the TLS renegotiation
|
||||||
@ -603,7 +616,9 @@ export class PortProxy {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Ignore errors - these are optional enhancements
|
// Ignore errors - these are optional enhancements
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${connectionId}] Enhanced TCP keep-alive not supported for outgoing socket: ${err}`);
|
console.log(
|
||||||
|
`[${connectionId}] Enhanced TCP keep-alive not supported for outgoing socket: ${err}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -660,7 +675,9 @@ export class PortProxy {
|
|||||||
// For keep-alive connections, just log a warning instead of closing
|
// For keep-alive connections, just log a warning instead of closing
|
||||||
if (record.hasKeepAlive) {
|
if (record.hasKeepAlive) {
|
||||||
console.log(
|
console.log(
|
||||||
`[${connectionId}] Timeout event on incoming keep-alive connection from ${record.remoteIP} after ${plugins.prettyMs(
|
`[${connectionId}] Timeout event on incoming keep-alive connection from ${
|
||||||
|
record.remoteIP
|
||||||
|
} after ${plugins.prettyMs(
|
||||||
this.settings.socketTimeout || 3600000
|
this.settings.socketTimeout || 3600000
|
||||||
)}. Connection preserved.`
|
)}. Connection preserved.`
|
||||||
);
|
);
|
||||||
@ -670,9 +687,9 @@ export class PortProxy {
|
|||||||
|
|
||||||
// For non-keep-alive connections, proceed with normal cleanup
|
// For non-keep-alive connections, proceed with normal cleanup
|
||||||
console.log(
|
console.log(
|
||||||
`[${connectionId}] Timeout on incoming side from ${record.remoteIP} after ${plugins.prettyMs(
|
`[${connectionId}] Timeout on incoming side from ${
|
||||||
this.settings.socketTimeout || 3600000
|
record.remoteIP
|
||||||
)}`
|
} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}`
|
||||||
);
|
);
|
||||||
if (record.incomingTerminationReason === null) {
|
if (record.incomingTerminationReason === null) {
|
||||||
record.incomingTerminationReason = 'timeout';
|
record.incomingTerminationReason = 'timeout';
|
||||||
@ -685,7 +702,9 @@ export class PortProxy {
|
|||||||
// For keep-alive connections, just log a warning instead of closing
|
// For keep-alive connections, just log a warning instead of closing
|
||||||
if (record.hasKeepAlive) {
|
if (record.hasKeepAlive) {
|
||||||
console.log(
|
console.log(
|
||||||
`[${connectionId}] Timeout event on outgoing keep-alive connection from ${record.remoteIP} after ${plugins.prettyMs(
|
`[${connectionId}] Timeout event on outgoing keep-alive connection from ${
|
||||||
|
record.remoteIP
|
||||||
|
} after ${plugins.prettyMs(
|
||||||
this.settings.socketTimeout || 3600000
|
this.settings.socketTimeout || 3600000
|
||||||
)}. Connection preserved.`
|
)}. Connection preserved.`
|
||||||
);
|
);
|
||||||
@ -695,9 +714,9 @@ export class PortProxy {
|
|||||||
|
|
||||||
// For non-keep-alive connections, proceed with normal cleanup
|
// For non-keep-alive connections, proceed with normal cleanup
|
||||||
console.log(
|
console.log(
|
||||||
`[${connectionId}] Timeout on outgoing side from ${record.remoteIP} after ${plugins.prettyMs(
|
`[${connectionId}] Timeout on outgoing side from ${
|
||||||
this.settings.socketTimeout || 3600000
|
record.remoteIP
|
||||||
)}`
|
} after ${plugins.prettyMs(this.settings.socketTimeout || 3600000)}`
|
||||||
);
|
);
|
||||||
if (record.outgoingTerminationReason === null) {
|
if (record.outgoingTerminationReason === null) {
|
||||||
record.outgoingTerminationReason = 'timeout';
|
record.outgoingTerminationReason = 'timeout';
|
||||||
@ -713,7 +732,9 @@ export class PortProxy {
|
|||||||
targetSocket.setTimeout(0);
|
targetSocket.setTimeout(0);
|
||||||
|
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${connectionId}] Disabled socket timeouts for immortal keep-alive connection`);
|
console.log(
|
||||||
|
`[${connectionId}] Disabled socket timeouts for immortal keep-alive connection`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Set normal timeouts for other connections
|
// Set normal timeouts for other connections
|
||||||
@ -743,9 +764,7 @@ export class PortProxy {
|
|||||||
const combinedData = Buffer.concat(record.pendingData);
|
const combinedData = Buffer.concat(record.pendingData);
|
||||||
targetSocket.write(combinedData, (err) => {
|
targetSocket.write(combinedData, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(
|
console.log(`[${connectionId}] Error writing pending data to target: ${err.message}`);
|
||||||
`[${connectionId}] Error writing pending data to target: ${err.message}`
|
|
||||||
);
|
|
||||||
return this.initiateCleanupOnce(record, 'write_error');
|
return this.initiateCleanupOnce(record, 'write_error');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,7 +783,9 @@ export class PortProxy {
|
|||||||
? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
|
? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
|
||||||
: ''
|
: ''
|
||||||
}` +
|
}` +
|
||||||
` TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${record.hasKeepAlive ? 'Yes' : 'No'}`
|
` TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${
|
||||||
|
record.hasKeepAlive ? 'Yes' : 'No'
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
@ -795,7 +816,9 @@ export class PortProxy {
|
|||||||
? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
|
? ` (Port-based for domain: ${domainConfig.domains.join(', ')})`
|
||||||
: ''
|
: ''
|
||||||
}` +
|
}` +
|
||||||
` TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${record.hasKeepAlive ? 'Yes' : 'No'}`
|
` TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${
|
||||||
|
record.hasKeepAlive ? 'Yes' : 'No'
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
@ -849,7 +872,9 @@ export class PortProxy {
|
|||||||
// For immortal keep-alive connections, skip setting a timeout completely
|
// For immortal keep-alive connections, skip setting a timeout completely
|
||||||
if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') {
|
if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') {
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${connectionId}] Keep-alive connection with immortal treatment - no max lifetime`);
|
console.log(
|
||||||
|
`[${connectionId}] Keep-alive connection with immortal treatment - no max lifetime`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// No cleanup timer for immortal connections
|
// No cleanup timer for immortal connections
|
||||||
}
|
}
|
||||||
@ -862,7 +887,9 @@ export class PortProxy {
|
|||||||
|
|
||||||
record.cleanupTimer = setTimeout(() => {
|
record.cleanupTimer = setTimeout(() => {
|
||||||
console.log(
|
console.log(
|
||||||
`[${connectionId}] TLS keep-alive connection from ${record.remoteIP} exceeded extended lifetime (${plugins.prettyMs(
|
`[${connectionId}] TLS keep-alive connection from ${
|
||||||
|
record.remoteIP
|
||||||
|
} exceeded extended lifetime (${plugins.prettyMs(
|
||||||
tlsKeepAliveTimeout
|
tlsKeepAliveTimeout
|
||||||
)}), forcing cleanup.`
|
)}), forcing cleanup.`
|
||||||
);
|
);
|
||||||
@ -875,7 +902,11 @@ export class PortProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${connectionId}] TLS keep-alive connection with enhanced protection, lifetime: ${plugins.prettyMs(tlsKeepAliveTimeout)}`);
|
console.log(
|
||||||
|
`[${connectionId}] TLS keep-alive connection with enhanced protection, lifetime: ${plugins.prettyMs(
|
||||||
|
tlsKeepAliveTimeout
|
||||||
|
)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// For extended keep-alive connections, use extended timeout
|
// For extended keep-alive connections, use extended timeout
|
||||||
@ -885,9 +916,9 @@ export class PortProxy {
|
|||||||
|
|
||||||
record.cleanupTimer = setTimeout(() => {
|
record.cleanupTimer = setTimeout(() => {
|
||||||
console.log(
|
console.log(
|
||||||
`[${connectionId}] Keep-alive connection from ${record.remoteIP} exceeded extended lifetime (${plugins.prettyMs(
|
`[${connectionId}] Keep-alive connection from ${
|
||||||
extendedTimeout
|
record.remoteIP
|
||||||
)}), forcing cleanup.`
|
} exceeded extended lifetime (${plugins.prettyMs(extendedTimeout)}), forcing cleanup.`
|
||||||
);
|
);
|
||||||
this.initiateCleanupOnce(record, 'extended_lifetime');
|
this.initiateCleanupOnce(record, 'extended_lifetime');
|
||||||
}, safeTimeout);
|
}, safeTimeout);
|
||||||
@ -898,20 +929,25 @@ export class PortProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${connectionId}] Keep-alive connection with extended lifetime of ${plugins.prettyMs(extendedTimeout)}`);
|
console.log(
|
||||||
|
`[${connectionId}] Keep-alive connection with extended lifetime of ${plugins.prettyMs(
|
||||||
|
extendedTimeout
|
||||||
|
)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// For standard connections, use normal timeout
|
// For standard connections, use normal timeout
|
||||||
else {
|
else {
|
||||||
// Use domain-specific timeout if available, otherwise use default
|
// Use domain-specific timeout if available, otherwise use default
|
||||||
const connectionTimeout = record.domainConfig?.connectionTimeout || this.settings.maxConnectionLifetime!;
|
const connectionTimeout =
|
||||||
|
record.domainConfig?.connectionTimeout || this.settings.maxConnectionLifetime!;
|
||||||
const safeTimeout = ensureSafeTimeout(connectionTimeout);
|
const safeTimeout = ensureSafeTimeout(connectionTimeout);
|
||||||
|
|
||||||
record.cleanupTimer = setTimeout(() => {
|
record.cleanupTimer = setTimeout(() => {
|
||||||
console.log(
|
console.log(
|
||||||
`[${connectionId}] Connection from ${record.remoteIP} exceeded max lifetime (${plugins.prettyMs(
|
`[${connectionId}] Connection from ${
|
||||||
connectionTimeout
|
record.remoteIP
|
||||||
)}), forcing cleanup.`
|
} exceeded max lifetime (${plugins.prettyMs(connectionTimeout)}), forcing cleanup.`
|
||||||
);
|
);
|
||||||
this.initiateCleanupOnce(record, 'connection_timeout');
|
this.initiateCleanupOnce(record, 'connection_timeout');
|
||||||
}, safeTimeout);
|
}, safeTimeout);
|
||||||
@ -1010,14 +1046,25 @@ export class PortProxy {
|
|||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(
|
console.log(
|
||||||
`[${record.id}] Detected possible system sleep for ${plugins.prettyMs(timeDiff)}. ` +
|
`[${record.id}] Detected possible system sleep for ${plugins.prettyMs(timeDiff)}. ` +
|
||||||
`Preserving keep-alive connection.`
|
`Handling keep-alive connection after long inactivity.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For keep-alive connections after sleep, we should refresh the TLS state if needed
|
// For TLS keep-alive connections after sleep/long inactivity, force close
|
||||||
|
// to make browser establish a new connection with fresh certificate context
|
||||||
if (record.isTLS && record.tlsHandshakeComplete) {
|
if (record.isTLS && record.tlsHandshakeComplete) {
|
||||||
|
if (timeDiff > 4 * 60 * 60 * 1000) {
|
||||||
|
// If inactive for more than 4 hours
|
||||||
|
console.log(
|
||||||
|
`[${record.id}] TLS connection inactive for ${plugins.prettyMs(timeDiff)}. ` +
|
||||||
|
`Closing to force new connection with fresh certificate.`
|
||||||
|
);
|
||||||
|
return this.initiateCleanupOnce(record, 'certificate_refresh_needed');
|
||||||
|
} else {
|
||||||
|
// For shorter inactivity periods, try to refresh the TLS state
|
||||||
this.refreshTlsStateAfterSleep(record);
|
this.refreshTlsStateAfterSleep(record);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Mark that we detected sleep
|
// Mark that we detected sleep
|
||||||
record.possibleSystemSleep = true;
|
record.possibleSystemSleep = true;
|
||||||
@ -1046,7 +1093,21 @@ export class PortProxy {
|
|||||||
try {
|
try {
|
||||||
// For outgoing connections that might need to be refreshed
|
// For outgoing connections that might need to be refreshed
|
||||||
if (record.outgoing && !record.outgoing.destroyed) {
|
if (record.outgoing && !record.outgoing.destroyed) {
|
||||||
// Send a zero-byte packet to test the connection
|
// Check how long this connection has been established
|
||||||
|
const connectionAge = Date.now() - record.incomingStartTime;
|
||||||
|
const hourInMs = 60 * 60 * 1000;
|
||||||
|
|
||||||
|
// For TLS browser connections that are very old, it's better to force a new connection
|
||||||
|
// rather than trying to refresh the state, to avoid certificate issues
|
||||||
|
if (record.isTLS && record.hasKeepAlive && connectionAge > 12 * hourInMs) {
|
||||||
|
console.log(
|
||||||
|
`[${record.id}] Long-lived TLS connection (${plugins.prettyMs(connectionAge)}). ` +
|
||||||
|
`Closing to ensure proper certificate handling on browser reconnect.`
|
||||||
|
);
|
||||||
|
return this.initiateCleanupOnce(record, 'certificate_context_refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
// For newer connections, try to send a refresh packet
|
||||||
record.outgoing.write(Buffer.alloc(0));
|
record.outgoing.write(Buffer.alloc(0));
|
||||||
|
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
@ -1056,8 +1117,9 @@ export class PortProxy {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(`[${record.id}] Error refreshing TLS state: ${err}`);
|
console.log(`[${record.id}] Error refreshing TLS state: ${err}`);
|
||||||
|
|
||||||
// If we can't refresh, don't terminate - client will re-establish if needed
|
// If we hit an error, it's likely the connection is already broken
|
||||||
// Just log the issue but preserve the connection
|
// Force cleanup to ensure browser reconnects cleanly
|
||||||
|
return this.initiateCleanupOnce(record, 'tls_refresh_error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1158,7 +1220,9 @@ export class PortProxy {
|
|||||||
` Duration: ${plugins.prettyMs(
|
` Duration: ${plugins.prettyMs(
|
||||||
duration
|
duration
|
||||||
)}, Bytes IN: ${bytesReceived}, OUT: ${bytesSent}, ` +
|
)}, Bytes IN: ${bytesReceived}, OUT: ${bytesSent}, ` +
|
||||||
`TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${record.hasKeepAlive ? 'Yes' : 'No'}` +
|
`TLS: ${record.isTLS ? 'Yes' : 'No'}, Keep-Alive: ${
|
||||||
|
record.hasKeepAlive ? 'Yes' : 'No'
|
||||||
|
}` +
|
||||||
`${record.usingNetworkProxy ? `, NetworkProxy: ${record.networkProxyIndex}` : ''}`
|
`${record.usingNetworkProxy ? `, NetworkProxy: ${record.networkProxyIndex}` : ''}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -1190,7 +1254,10 @@ export class PortProxy {
|
|||||||
console.log(`[${record.id}] Connection cleanup initiated for ${record.remoteIP} (${reason})`);
|
console.log(`[${record.id}] Connection cleanup initiated for ${record.remoteIP} (${reason})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record.incomingTerminationReason === null || record.incomingTerminationReason === undefined) {
|
if (
|
||||||
|
record.incomingTerminationReason === null ||
|
||||||
|
record.incomingTerminationReason === undefined
|
||||||
|
) {
|
||||||
record.incomingTerminationReason = reason;
|
record.incomingTerminationReason = reason;
|
||||||
this.incrementTerminationStat('incoming', reason);
|
this.incrementTerminationStat('incoming', reason);
|
||||||
}
|
}
|
||||||
@ -1347,7 +1414,7 @@ export class PortProxy {
|
|||||||
usingNetworkProxy: false,
|
usingNetworkProxy: false,
|
||||||
|
|
||||||
// Initialize sleep detection fields
|
// Initialize sleep detection fields
|
||||||
possibleSystemSleep: false
|
possibleSystemSleep: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply keep-alive settings if enabled
|
// Apply keep-alive settings if enabled
|
||||||
@ -1368,7 +1435,9 @@ export class PortProxy {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Ignore errors - these are optional enhancements
|
// Ignore errors - these are optional enhancements
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${connectionId}] Enhanced TCP keep-alive settings not supported: ${err}`);
|
console.log(
|
||||||
|
`[${connectionId}] Enhanced TCP keep-alive settings not supported: ${err}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1808,17 +1877,24 @@ export class PortProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip inactivity check if disabled or for immortal keep-alive connections
|
// Skip inactivity check if disabled or for immortal keep-alive connections
|
||||||
if (!this.settings.disableInactivityCheck &&
|
if (
|
||||||
!(record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal')) {
|
!this.settings.disableInactivityCheck &&
|
||||||
|
!(record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal')
|
||||||
|
) {
|
||||||
const inactivityTime = now - record.lastActivity;
|
const inactivityTime = now - record.lastActivity;
|
||||||
|
|
||||||
// Special handling for TLS keep-alive connections
|
// Special handling for TLS keep-alive connections
|
||||||
if (record.hasKeepAlive && record.isTLS && inactivityTime > this.settings.inactivityTimeout! / 2) {
|
if (
|
||||||
|
record.hasKeepAlive &&
|
||||||
|
record.isTLS &&
|
||||||
|
inactivityTime > this.settings.inactivityTimeout! / 2
|
||||||
|
) {
|
||||||
// For TLS keep-alive connections that are getting stale, try to refresh before closing
|
// For TLS keep-alive connections that are getting stale, try to refresh before closing
|
||||||
if (!record.inactivityWarningIssued) {
|
if (!record.inactivityWarningIssued) {
|
||||||
console.log(
|
console.log(
|
||||||
`[${id}] TLS keep-alive connection from ${record.remoteIP} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
`[${id}] TLS keep-alive connection from ${
|
||||||
|
record.remoteIP
|
||||||
|
} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
||||||
`Attempting to preserve connection.`
|
`Attempting to preserve connection.`
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1827,7 +1903,7 @@ export class PortProxy {
|
|||||||
|
|
||||||
// For TLS connections, extend the last activity time considerably
|
// For TLS connections, extend the last activity time considerably
|
||||||
// This gives browsers more time to re-establish the connection properly
|
// This gives browsers more time to re-establish the connection properly
|
||||||
record.lastActivity = now - (this.settings.inactivityTimeout! / 3);
|
record.lastActivity = now - this.settings.inactivityTimeout! / 3;
|
||||||
|
|
||||||
// Try to stimulate the connection with a probe packet
|
// Try to stimulate the connection with a probe packet
|
||||||
if (record.outgoing && !record.outgoing.destroyed) {
|
if (record.outgoing && !record.outgoing.destroyed) {
|
||||||
@ -1860,7 +1936,9 @@ export class PortProxy {
|
|||||||
// For keep-alive connections, issue a warning first
|
// For keep-alive connections, issue a warning first
|
||||||
if (record.hasKeepAlive && !record.inactivityWarningIssued) {
|
if (record.hasKeepAlive && !record.inactivityWarningIssued) {
|
||||||
console.log(
|
console.log(
|
||||||
`[${id}] Warning: Keep-alive connection from ${record.remoteIP} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
`[${id}] Warning: Keep-alive connection from ${
|
||||||
|
record.remoteIP
|
||||||
|
} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
||||||
`Will close in 10 minutes if no activity.`
|
`Will close in 10 minutes if no activity.`
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1882,16 +1960,31 @@ export class PortProxy {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// MODIFIED: For TLS connections, be more lenient before closing
|
// MODIFIED: For TLS connections, be more lenient before closing
|
||||||
|
// For TLS browser connections, we need to handle certificate context properly
|
||||||
if (record.isTLS && record.hasKeepAlive) {
|
if (record.isTLS && record.hasKeepAlive) {
|
||||||
// For TLS keep-alive connections, add additional grace period
|
// For very long inactivity, it's better to close the connection
|
||||||
// This helps with browsers reconnecting after sleep
|
// so the browser establishes a new one with a fresh certificate context
|
||||||
|
if (inactivityTime > 6 * 60 * 60 * 1000) {
|
||||||
|
// 6 hours
|
||||||
console.log(
|
console.log(
|
||||||
`[${id}] TLS keep-alive connection from ${record.remoteIP} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
`[${id}] TLS keep-alive connection from ${
|
||||||
|
record.remoteIP
|
||||||
|
} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
||||||
|
`Closing to ensure proper certificate handling on browser reconnect.`
|
||||||
|
);
|
||||||
|
this.cleanupConnection(record, 'tls_certificate_refresh');
|
||||||
|
} else {
|
||||||
|
// For shorter inactivity periods, add grace period
|
||||||
|
console.log(
|
||||||
|
`[${id}] TLS keep-alive connection from ${
|
||||||
|
record.remoteIP
|
||||||
|
} inactive for ${plugins.prettyMs(inactivityTime)}. ` +
|
||||||
`Adding extra grace period.`
|
`Adding extra grace period.`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Give additional time for browsers to reconnect properly
|
// Give additional time for browsers to reconnect properly
|
||||||
record.lastActivity = now - (effectiveTimeout / 2);
|
record.lastActivity = now - effectiveTimeout / 2;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// For non-keep-alive or after warning, close the connection
|
// For non-keep-alive or after warning, close the connection
|
||||||
console.log(
|
console.log(
|
||||||
@ -1905,7 +1998,9 @@ export class PortProxy {
|
|||||||
} else if (inactivityTime <= effectiveTimeout && record.inactivityWarningIssued) {
|
} else if (inactivityTime <= effectiveTimeout && record.inactivityWarningIssued) {
|
||||||
// If activity detected after warning, clear the warning
|
// If activity detected after warning, clear the warning
|
||||||
if (this.settings.enableDetailedLogging) {
|
if (this.settings.enableDetailedLogging) {
|
||||||
console.log(`[${id}] Connection activity detected after inactivity warning, resetting warning`);
|
console.log(
|
||||||
|
`[${id}] Connection activity detected after inactivity warning, resetting warning`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
record.inactivityWarningIssued = false;
|
record.inactivityWarningIssued = false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user