Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
60a0ad106d | |||
a70c123007 | |||
46aa7620b0 | |||
f72db86e37 | |||
d612df107e | |||
1c34578c36 |
19
changelog.md
19
changelog.md
@ -1,5 +1,24 @@
|
||||
# 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)
|
||||
Replace closeNotify alert with handshake failure alert in TLS ClientHello handling to properly signal missing SNI and enforce session ticket restrictions.
|
||||
|
||||
- Switched alert data sent on missing SNI from closeNotifyAlert to sslHandshakeFailureAlertData.
|
||||
- Ensures consistent TLS alert behavior during handshake failure.
|
||||
|
||||
## 2025-03-16 - 4.1.8 - fix(ConnectionHandler/tls)
|
||||
Change the TLS alert sent when a ClientHello lacks SNI: use the close_notify alert instead of handshake_failure to prompt immediate retry with SNI.
|
||||
|
||||
- Replaced the previously sent handshake_failure alert (code 0x28) with a close_notify alert (code 0x00) in the TLS session resumption handling in ConnectionHandler.
|
||||
- This change encourages clients to immediately retry and include SNI when allowSessionTicket is false.
|
||||
|
||||
## 2025-03-16 - 4.1.7 - fix(classes.pp.connectionhandler)
|
||||
Improve TLS alert handling in ClientHello when SNI is missing and session tickets are disallowed
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@push.rocks/smartproxy",
|
||||
"version": "4.1.7",
|
||||
"version": "4.1.10",
|
||||
"private": false,
|
||||
"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.",
|
||||
"main": "dist_ts/index.js",
|
||||
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartproxy',
|
||||
version: '4.1.7',
|
||||
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.'
|
||||
}
|
||||
|
@ -595,42 +595,49 @@ export class ConnectionHandler {
|
||||
0x28, // handshake_failure alert (40) instead of unrecognized_name (112)
|
||||
]);
|
||||
|
||||
const closeNotifyAlert = Buffer.from([
|
||||
0x15, // Alert record type
|
||||
0x03,
|
||||
0x03, // TLS 1.2 version
|
||||
0x00,
|
||||
0x02, // Length
|
||||
0x01, // Warning alert level (1)
|
||||
0x00, // close_notify alert (0)
|
||||
]);
|
||||
|
||||
try {
|
||||
// Use cork/uncork to ensure the alert is sent as a single packet
|
||||
socket.cork();
|
||||
const writeSuccessful = socket.write(sslHandshakeFailureAlertData);
|
||||
const writeSuccessful = socket.write(serverNameUnknownAlertData);
|
||||
socket.uncork();
|
||||
|
||||
// Function to handle the clean socket termination
|
||||
|
||||
// Function to handle the clean socket termination - but more gradually
|
||||
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();
|
||||
|
||||
// Allow a short delay for the alert and FIN to be transmitted
|
||||
// before we fully close the socket
|
||||
|
||||
// Log the cleanup but wait for natural closure
|
||||
setTimeout(() => {
|
||||
if (!socket.destroyed) {
|
||||
socket.destroy();
|
||||
}
|
||||
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 the data was successfully written to the kernel buffer,
|
||||
// we can finish the connection after a short delay to ensure transmission
|
||||
setTimeout(finishConnection, 50);
|
||||
// Wait longer before ending connection to ensure alert is processed by client
|
||||
setTimeout(finishConnection, 200); // Increased from 50ms to 200ms
|
||||
} else {
|
||||
// If the kernel buffer was full, wait for the drain event
|
||||
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(() => {
|
||||
socket.removeAllListeners('drain');
|
||||
finishConnection();
|
||||
}, 250);
|
||||
}, 400); // Increased from 250ms to 400ms
|
||||
}
|
||||
} catch (err) {
|
||||
// If we can't send the alert, fall back to immediate termination
|
||||
|
Reference in New Issue
Block a user