UNPKG

@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
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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