fix(connectionhandler): Increase delay timings for TLS alert transmission in session ticket blocking to allow graceful socket termination
This commit is contained in:
		| @@ -1,5 +1,12 @@ | |||||||
| # Changelog | # Changelog | ||||||
|  |  | ||||||
|  | ## 2025-03-16 - 4.1.10 - fix(connectionhandler) | ||||||
|  | Increase delay timings for TLS alert transmission in session ticket blocking to allow graceful socket termination | ||||||
|  |  | ||||||
|  | - Updated finishConnection: replaced immediate socket.destroy with a graceful end call | ||||||
|  | - Increased delay after successful write from 50ms to 200ms to allow alert processing | ||||||
|  | - Raised safety timeout from 250ms to 400ms when waiting for 'drain' event | ||||||
|  |  | ||||||
| ## 2025-03-16 - 4.1.9 - fix(ConnectionHandler) | ## 2025-03-16 - 4.1.9 - fix(ConnectionHandler) | ||||||
| Replace closeNotify alert with handshake failure alert in TLS ClientHello handling to properly signal missing SNI and enforce session ticket restrictions. | Replace closeNotify alert with handshake failure alert in TLS ClientHello handling to properly signal missing SNI and enforce session ticket restrictions. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,6 +3,6 @@ | |||||||
|  */ |  */ | ||||||
| export const commitinfo = { | export const commitinfo = { | ||||||
|   name: '@push.rocks/smartproxy', |   name: '@push.rocks/smartproxy', | ||||||
|   version: '4.1.9', |   version: '4.1.10', | ||||||
|   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.' |   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.' | ||||||
| } | } | ||||||
|   | |||||||
| @@ -611,36 +611,33 @@ export class ConnectionHandler { | |||||||
|               const writeSuccessful = socket.write(serverNameUnknownAlertData); |               const writeSuccessful = socket.write(serverNameUnknownAlertData); | ||||||
|               socket.uncork(); |               socket.uncork(); | ||||||
|                |                | ||||||
|               // Function to handle the clean socket termination |               // Function to handle the clean socket termination - but more gradually | ||||||
|               const finishConnection = () => { |               const finishConnection = () => { | ||||||
|                 // First call end() to initiate a graceful close (sends FIN) |                 // Give Chrome more time to process the alert before closing | ||||||
|  |                 // We won't call destroy() at all - just end() and let the socket close naturally | ||||||
|                 socket.end(); |                 socket.end(); | ||||||
|                  |                  | ||||||
|                 // Allow a short delay for the alert and FIN to be transmitted |                 // Log the cleanup but wait for natural closure | ||||||
|                 // before we fully close the socket |  | ||||||
|                 setTimeout(() => { |                 setTimeout(() => { | ||||||
|                   if (!socket.destroyed) { |  | ||||||
|                     socket.destroy(); |  | ||||||
|                   } |  | ||||||
|                   this.connectionManager.cleanupConnection(record, 'session_ticket_blocked_no_sni'); |                   this.connectionManager.cleanupConnection(record, 'session_ticket_blocked_no_sni'); | ||||||
|                 }, 150); // Short delay, but longer than the standard TCP ACK timeout |                 }, 300); // Longer delay to let socket cleanup happen naturally | ||||||
|               }; |               }; | ||||||
|                |                | ||||||
|               if (writeSuccessful) { |               if (writeSuccessful) { | ||||||
|                 // If the data was successfully written to the kernel buffer, |                 // Wait longer before ending connection to ensure alert is processed by client | ||||||
|                 // we can finish the connection after a short delay to ensure transmission |                 setTimeout(finishConnection, 200); // Increased from 50ms to 200ms | ||||||
|                 setTimeout(finishConnection, 50); |  | ||||||
|               } else { |               } else { | ||||||
|                 // If the kernel buffer was full, wait for the drain event |                 // If the kernel buffer was full, wait for the drain event | ||||||
|                 socket.once('drain', () => { |                 socket.once('drain', () => { | ||||||
|                   setTimeout(finishConnection, 50); |                   // Wait longer after drain as well | ||||||
|  |                   setTimeout(finishConnection, 200); | ||||||
|                 }); |                 }); | ||||||
|                  |                  | ||||||
|                 // Set a safety timeout in case drain never happens |                 // Safety timeout is increased too | ||||||
|                 setTimeout(() => { |                 setTimeout(() => { | ||||||
|                   socket.removeAllListeners('drain'); |                   socket.removeAllListeners('drain'); | ||||||
|                   finishConnection(); |                   finishConnection(); | ||||||
|                 }, 250); |                 }, 400); // Increased from 250ms to 400ms | ||||||
|               } |               } | ||||||
|             } catch (err) { |             } catch (err) { | ||||||
|               // If we can't send the alert, fall back to immediate termination |               // If we can't send the alert, fall back to immediate termination | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user