@push.rocks/smartproxy
Version:
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.
132 lines • 9.83 kB
JavaScript
import * as plugins from './plugins.js';
import { SniHandler } from './classes.pp.snihandler.js';
/**
* Manages TLS-related operations including SNI extraction and validation
*/
export class TlsManager {
constructor(settings) {
this.settings = settings;
}
/**
* Check if a data chunk appears to be a TLS handshake
*/
isTlsHandshake(chunk) {
return SniHandler.isTlsHandshake(chunk);
}
/**
* Check if a data chunk appears to be a TLS ClientHello
*/
isClientHello(chunk) {
return SniHandler.isClientHello(chunk);
}
/**
* Extract Server Name Indication (SNI) from TLS handshake
*/
extractSNI(chunk, connInfo, previousDomain) {
// Use the SniHandler to process the TLS packet
return SniHandler.processTlsPacket(chunk, connInfo, this.settings.enableTlsDebugLogging || false, previousDomain);
}
/**
* Handle session resumption attempts
*/
handleSessionResumption(chunk, connectionId, hasSNI) {
// Skip if session tickets are allowed
if (this.settings.allowSessionTicket !== false) {
return { shouldBlock: false };
}
// Check for session resumption attempt
const resumptionInfo = SniHandler.hasSessionResumption(chunk, this.settings.enableTlsDebugLogging || false);
// If this is a resumption attempt without SNI, block it
if (resumptionInfo.isResumption && !hasSNI && !resumptionInfo.hasSNI) {
if (this.settings.enableTlsDebugLogging) {
console.log(`[${connectionId}] Session resumption detected without SNI and allowSessionTicket=false. ` +
`Terminating connection to force new TLS handshake.`);
}
return {
shouldBlock: true,
reason: 'session_ticket_blocked'
};
}
return { shouldBlock: false };
}
/**
* Check for SNI mismatch during renegotiation
*/
checkRenegotiationSNI(chunk, connInfo, expectedDomain, connectionId) {
// Only process if this looks like a TLS ClientHello
if (!this.isClientHello(chunk)) {
return { hasMismatch: false };
}
try {
// Extract SNI with renegotiation support
const newSNI = SniHandler.extractSNIWithResumptionSupport(chunk, connInfo, this.settings.enableTlsDebugLogging || false);
// Skip if no SNI was found
if (!newSNI)
return { hasMismatch: false };
// Check for SNI mismatch
if (newSNI !== expectedDomain) {
if (this.settings.enableTlsDebugLogging) {
console.log(`[${connectionId}] Renegotiation with different SNI: ${expectedDomain} -> ${newSNI}. ` +
`Terminating connection - SNI domain switching is not allowed.`);
}
return { hasMismatch: true, extractedSNI: newSNI };
}
else if (this.settings.enableTlsDebugLogging) {
console.log(`[${connectionId}] Renegotiation detected with same SNI: ${newSNI}. Allowing.`);
}
}
catch (err) {
console.log(`[${connectionId}] Error processing ClientHello: ${err}. Allowing connection to continue.`);
}
return { hasMismatch: false };
}
/**
* Create a renegotiation handler function for a connection
*/
createRenegotiationHandler(connectionId, lockedDomain, connInfo, onMismatch) {
return (chunk) => {
const result = this.checkRenegotiationSNI(chunk, connInfo, lockedDomain, connectionId);
if (result.hasMismatch) {
onMismatch(connectionId, 'sni_mismatch');
}
};
}
/**
* Analyze TLS connection for browser fingerprinting
* This helps identify browser vs non-browser connections
*/
analyzeClientHello(chunk) {
// Default result
const result = {
isBrowserConnection: false,
isRenewal: false,
hasSNI: false
};
try {
// Check if it's a ClientHello
if (!this.isClientHello(chunk)) {
return result;
}
// Check for session resumption
const resumptionInfo = SniHandler.hasSessionResumption(chunk, this.settings.enableTlsDebugLogging || false);
// Extract SNI
const sni = SniHandler.extractSNI(chunk, this.settings.enableTlsDebugLogging || false);
// Update result
result.isRenewal = resumptionInfo.isResumption;
result.hasSNI = !!sni;
// Browsers typically:
// 1. Send SNI extension
// 2. Have a variety of extensions (ALPN, etc.)
// 3. Use standard cipher suites
// ...more complex heuristics could be implemented here
// Simple heuristic: presence of SNI suggests browser
result.isBrowserConnection = !!sni;
return result;
}
catch (err) {
console.log(`Error analyzing ClientHello: ${err}`);
return result;
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wcC50bHNtYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5wcC50bHNtYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBRXhDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQVl4RDs7R0FFRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBQ3JCLFlBQW9CLFFBQTRCO1FBQTVCLGFBQVEsR0FBUixRQUFRLENBQW9CO0lBQUcsQ0FBQztJQUVwRDs7T0FFRztJQUNJLGNBQWMsQ0FBQyxLQUFhO1FBQ2pDLE9BQU8sVUFBVSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxhQUFhLENBQUMsS0FBYTtRQUNoQyxPQUFPLFVBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksVUFBVSxDQUNmLEtBQWEsRUFDYixRQUF5QixFQUN6QixjQUF1QjtRQUV2QiwrQ0FBK0M7UUFDL0MsT0FBTyxVQUFVLENBQUMsZ0JBQWdCLENBQ2hDLEtBQUssRUFDTCxRQUFRLEVBQ1IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsSUFBSSxLQUFLLEVBQzVDLGNBQWMsQ0FDZixDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ksdUJBQXVCLENBQzVCLEtBQWEsRUFDYixZQUFvQixFQUNwQixNQUFlO1FBRWYsc0NBQXNDO1FBQ3RDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQ2hDLENBQUM7UUFFRCx1Q0FBdUM7UUFDdkMsTUFBTSxjQUFjLEdBQUcsVUFBVSxDQUFDLG9CQUFvQixDQUNwRCxLQUFL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