UNPKG

@push.rocks/smartproxy

Version:

A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.

156 lines 12.4 kB
import * as plugins from '../../plugins.js'; import { ForwardingHandler } from './base-handler.js'; import { ForwardingHandlerEvents } from '../config/forwarding-types.js'; import { createIndependentSocketHandlers, setupSocketHandlers, createSocketWithErrorHandler } from '../../core/utils/socket-utils.js'; /** * Handler for HTTPS passthrough (SNI forwarding without termination) */ export class HttpsPassthroughHandler extends ForwardingHandler { /** * Create a new HTTPS passthrough handler * @param config The forwarding configuration */ constructor(config) { super(config); // Validate that this is an HTTPS passthrough configuration if (config.type !== 'https-passthrough') { throw new Error(`Invalid configuration type for HttpsPassthroughHandler: ${config.type}`); } } /** * Initialize the handler * HTTPS passthrough handler doesn't need special initialization */ async initialize() { // Basic initialization from parent class await super.initialize(); } /** * Handle a TLS/SSL socket connection by forwarding it without termination * @param clientSocket The incoming socket from the client */ handleConnection(clientSocket) { // Get the target from configuration const target = this.getTargetFromConfig(); // Log the connection const remoteAddress = clientSocket.remoteAddress || 'unknown'; const remotePort = clientSocket.remotePort || 0; this.emit(ForwardingHandlerEvents.CONNECTED, { remoteAddress, remotePort, target: `${target.host}:${target.port}` }); // Track data transfer for logging let bytesSent = 0; let bytesReceived = 0; let serverSocket = null; let cleanupClient = null; let cleanupServer = null; // Create a connection to the target server with immediate error handling serverSocket = createSocketWithErrorHandler({ port: target.port, host: target.host, onError: async (error) => { // Server connection failed - clean up client socket immediately this.emit(ForwardingHandlerEvents.ERROR, { error: error.message, code: error.code || 'UNKNOWN', remoteAddress, target: `${target.host}:${target.port}` }); // Clean up the client socket since we can't forward if (!clientSocket.destroyed) { clientSocket.destroy(); } this.emit(ForwardingHandlerEvents.DISCONNECTED, { remoteAddress, bytesSent: 0, bytesReceived: 0, reason: `server_connection_failed: ${error.message}` }); }, onConnect: () => { // Connection successful - set up forwarding handlers const handlers = createIndependentSocketHandlers(clientSocket, serverSocket, (reason) => { this.emit(ForwardingHandlerEvents.DISCONNECTED, { remoteAddress, bytesSent, bytesReceived, reason }); }); cleanupClient = handlers.cleanupClient; cleanupServer = handlers.cleanupServer; // Setup handlers with custom timeout handling that doesn't close connections const timeout = this.getTimeout(); setupSocketHandlers(clientSocket, cleanupClient, (socket) => { // Just reset timeout, don't close socket.setTimeout(timeout); }, 'client'); setupSocketHandlers(serverSocket, cleanupServer, (socket) => { // Just reset timeout, don't close socket.setTimeout(timeout); }, 'server'); // Forward data from client to server clientSocket.on('data', (data) => { bytesSent += data.length; // Check if server socket is writable if (serverSocket && serverSocket.writable) { const flushed = serverSocket.write(data); // Handle backpressure if (!flushed) { clientSocket.pause(); serverSocket.once('drain', () => { clientSocket.resume(); }); } } this.emit(ForwardingHandlerEvents.DATA_FORWARDED, { direction: 'outbound', bytes: data.length, total: bytesSent }); }); // Forward data from server to client serverSocket.on('data', (data) => { bytesReceived += data.length; // Check if client socket is writable if (clientSocket.writable) { const flushed = clientSocket.write(data); // Handle backpressure if (!flushed) { serverSocket.pause(); clientSocket.once('drain', () => { serverSocket.resume(); }); } } this.emit(ForwardingHandlerEvents.DATA_FORWARDED, { direction: 'inbound', bytes: data.length, total: bytesReceived }); }); // Set initial timeouts - they will be reset on each timeout event clientSocket.setTimeout(timeout); serverSocket.setTimeout(timeout); } }); } /** * Handle an HTTP request - HTTPS passthrough doesn't support HTTP * @param req The HTTP request * @param res The HTTP response */ handleHttpRequest(_req, res) { // HTTPS passthrough doesn't support HTTP requests res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('HTTP not supported for this domain'); this.emit(ForwardingHandlerEvents.HTTP_RESPONSE, { statusCode: 404, headers: { 'Content-Type': 'text/plain' }, size: 'HTTP not supported for this domain'.length }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cHMtcGFzc3Rocm91Z2gtaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2ZvcndhcmRpbmcvaGFuZGxlcnMvaHR0cHMtcGFzc3Rocm91Z2gtaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXRELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxtQkFBbUIsRUFBRSw0QkFBNEIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRXRJOztHQUVHO0FBQ0gsTUFBTSxPQUFPLHVCQUF3QixTQUFRLGlCQUFpQjtJQUM1RDs7O09BR0c7SUFDSCxZQUFZLE1BQXNCO1FBQ2hDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVkLDJEQUEyRDtRQUMzRCxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssbUJBQW1CLEVBQUUsQ0FBQztZQUN4QyxNQUFNLElBQUksS0FBSyxDQUFDLDJEQUEyRCxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM1RixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxVQUFVO1FBQ3JCLHlDQUF5QztRQUN6QyxNQUFNLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksZ0JBQWdCLENBQUMsWUFBZ0M7UUFDdEQsb0NBQW9DO1FBQ3BDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRTFDLHFCQUFxQjtRQUNyQixNQUFNLGFBQWEsR0FBRyxZQUFZLENBQUMsYUFBYSxJQUFJLFNBQVMsQ0FBQztRQUM5RCxNQUFNLFVBQVUsR0FBRyxZQUFZLENBQUMsVUFBVSxJ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