2025-05-09 17:28:27 +00:00
|
|
|
import * as plugins from '../../../plugins.js';
|
2025-05-09 22:46:53 +00:00
|
|
|
import type { IForwardConfig } from '../../../forwarding/config/forwarding-types.js';
|
2025-05-09 17:28:27 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Provision object for static or HTTP-01 certificate
|
|
|
|
*/
|
2025-05-09 22:46:53 +00:00
|
|
|
export type TSmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01';
|
2025-05-09 17:28:27 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Domain configuration with forwarding configuration
|
|
|
|
*/
|
2025-05-09 22:46:53 +00:00
|
|
|
export interface IDomainConfig {
|
2025-05-09 17:28:27 +00:00
|
|
|
domains: string[]; // Glob patterns for domain(s)
|
2025-05-09 22:46:53 +00:00
|
|
|
forwarding: IForwardConfig; // Unified forwarding configuration
|
2025-05-09 17:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Configuration options for the SmartProxy
|
|
|
|
*/
|
2025-05-09 22:46:53 +00:00
|
|
|
import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
|
|
|
|
export interface ISmartProxyOptions {
|
2025-05-09 17:28:27 +00:00
|
|
|
fromPort: number;
|
|
|
|
toPort: number;
|
|
|
|
targetIP?: string; // Global target host to proxy to, defaults to 'localhost'
|
2025-05-09 22:46:53 +00:00
|
|
|
domainConfigs: IDomainConfig[];
|
2025-05-09 17:28:27 +00:00
|
|
|
sniEnabled?: boolean;
|
|
|
|
defaultAllowedIPs?: string[];
|
|
|
|
defaultBlockedIPs?: string[];
|
|
|
|
preserveSourceIP?: boolean;
|
|
|
|
|
|
|
|
// TLS options
|
|
|
|
pfx?: Buffer;
|
|
|
|
key?: string | Buffer | Array<Buffer | string>;
|
|
|
|
passphrase?: string;
|
|
|
|
cert?: string | Buffer | Array<string | Buffer>;
|
|
|
|
ca?: string | Buffer | Array<string | Buffer>;
|
|
|
|
ciphers?: string;
|
|
|
|
honorCipherOrder?: boolean;
|
|
|
|
rejectUnauthorized?: boolean;
|
|
|
|
secureProtocol?: string;
|
|
|
|
servername?: string;
|
|
|
|
minVersion?: string;
|
|
|
|
maxVersion?: string;
|
|
|
|
|
|
|
|
// Timeout settings
|
|
|
|
initialDataTimeout?: number; // Timeout for initial data/SNI (ms), default: 60000 (60s)
|
|
|
|
socketTimeout?: number; // Socket inactivity timeout (ms), default: 3600000 (1h)
|
|
|
|
inactivityCheckInterval?: number; // How often to check for inactive connections (ms), default: 60000 (60s)
|
|
|
|
maxConnectionLifetime?: number; // Default max connection lifetime (ms), default: 86400000 (24h)
|
|
|
|
inactivityTimeout?: number; // Inactivity timeout (ms), default: 14400000 (4h)
|
|
|
|
|
|
|
|
gracefulShutdownTimeout?: number; // (ms) maximum time to wait for connections to close during shutdown
|
|
|
|
globalPortRanges: Array<{ from: number; to: number }>; // Global allowed port ranges
|
|
|
|
forwardAllGlobalRanges?: boolean; // When true, forwards all connections on global port ranges to the global targetIP
|
|
|
|
|
|
|
|
// Socket optimization settings
|
|
|
|
noDelay?: boolean; // Disable Nagle's algorithm (default: true)
|
|
|
|
keepAlive?: boolean; // Enable TCP keepalive (default: true)
|
|
|
|
keepAliveInitialDelay?: number; // Initial delay before sending keepalive probes (ms)
|
|
|
|
maxPendingDataSize?: number; // Maximum bytes to buffer during connection setup
|
|
|
|
|
|
|
|
// Enhanced features
|
|
|
|
disableInactivityCheck?: boolean; // Disable inactivity checking entirely
|
|
|
|
enableKeepAliveProbes?: boolean; // Enable TCP keep-alive probes
|
|
|
|
enableDetailedLogging?: boolean; // Enable detailed connection logging
|
|
|
|
enableTlsDebugLogging?: boolean; // Enable TLS handshake debug logging
|
|
|
|
enableRandomizedTimeouts?: boolean; // Randomize timeouts slightly to prevent thundering herd
|
|
|
|
allowSessionTicket?: boolean; // Allow TLS session ticket for reconnection (default: true)
|
|
|
|
|
|
|
|
// Rate limiting and security
|
|
|
|
maxConnectionsPerIP?: number; // Maximum simultaneous connections from a single IP
|
|
|
|
connectionRateLimitPerMinute?: number; // Max new connections per minute from a single IP
|
|
|
|
|
|
|
|
// Enhanced keep-alive settings
|
|
|
|
keepAliveTreatment?: 'standard' | 'extended' | 'immortal'; // How to treat keep-alive connections
|
|
|
|
keepAliveInactivityMultiplier?: number; // Multiplier for inactivity timeout for keep-alive connections
|
|
|
|
extendedKeepAliveLifetime?: number; // Extended lifetime for keep-alive connections (ms)
|
|
|
|
|
|
|
|
// NetworkProxy integration
|
|
|
|
useNetworkProxy?: number[]; // Array of ports to forward to NetworkProxy
|
|
|
|
networkProxyPort?: number; // Port where NetworkProxy is listening (default: 8443)
|
|
|
|
|
|
|
|
// ACME configuration options for SmartProxy
|
2025-05-09 22:46:53 +00:00
|
|
|
acme?: IAcmeOptions;
|
|
|
|
|
2025-05-09 17:28:27 +00:00
|
|
|
/**
|
|
|
|
* Optional certificate provider callback. Return 'http01' to use HTTP-01 challenges,
|
|
|
|
* or a static certificate object for immediate provisioning.
|
|
|
|
*/
|
2025-05-09 22:46:53 +00:00
|
|
|
certProvisionFunction?: (domain: string) => Promise<TSmartProxyCertProvisionObject>;
|
2025-05-09 17:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enhanced connection record
|
|
|
|
*/
|
2025-05-09 22:46:53 +00:00
|
|
|
export interface IConnectionRecord {
|
2025-05-09 17:28:27 +00:00
|
|
|
id: string; // Unique connection identifier
|
|
|
|
incoming: plugins.net.Socket;
|
|
|
|
outgoing: plugins.net.Socket | null;
|
|
|
|
incomingStartTime: number;
|
|
|
|
outgoingStartTime?: number;
|
|
|
|
outgoingClosedTime?: number;
|
|
|
|
lockedDomain?: string; // Used to lock this connection to the initial SNI
|
|
|
|
connectionClosed: boolean; // Flag to prevent multiple cleanup attempts
|
|
|
|
cleanupTimer?: NodeJS.Timeout; // Timer for max lifetime/inactivity
|
|
|
|
alertFallbackTimeout?: NodeJS.Timeout; // Timer for fallback after alert
|
|
|
|
lastActivity: number; // Last activity timestamp for inactivity detection
|
|
|
|
pendingData: Buffer[]; // Buffer to hold data during connection setup
|
|
|
|
pendingDataSize: number; // Track total size of pending data
|
|
|
|
|
|
|
|
// Enhanced tracking fields
|
|
|
|
bytesReceived: number; // Total bytes received
|
|
|
|
bytesSent: number; // Total bytes sent
|
|
|
|
remoteIP: string; // Remote IP (cached for logging after socket close)
|
|
|
|
localPort: number; // Local port (cached for logging)
|
|
|
|
isTLS: boolean; // Whether this connection is a TLS connection
|
|
|
|
tlsHandshakeComplete: boolean; // Whether the TLS handshake is complete
|
|
|
|
hasReceivedInitialData: boolean; // Whether initial data has been received
|
2025-05-09 22:46:53 +00:00
|
|
|
domainConfig?: IDomainConfig; // Associated domain config for this connection
|
2025-05-09 17:28:27 +00:00
|
|
|
|
|
|
|
// Keep-alive tracking
|
|
|
|
hasKeepAlive: boolean; // Whether keep-alive is enabled for this connection
|
|
|
|
inactivityWarningIssued?: boolean; // Whether an inactivity warning has been issued
|
|
|
|
incomingTerminationReason?: string | null; // Reason for incoming termination
|
|
|
|
outgoingTerminationReason?: string | null; // Reason for outgoing termination
|
|
|
|
|
|
|
|
// NetworkProxy tracking
|
|
|
|
usingNetworkProxy?: boolean; // Whether this connection is using a NetworkProxy
|
|
|
|
|
|
|
|
// Renegotiation handler
|
|
|
|
renegotiationHandler?: (chunk: Buffer) => void; // Handler for renegotiation detection
|
|
|
|
|
|
|
|
// Browser connection tracking
|
|
|
|
isBrowserConnection?: boolean; // Whether this connection appears to be from a browser
|
|
|
|
domainSwitches?: number; // Number of times the domain has been switched on this connection
|
2025-05-09 22:46:53 +00:00
|
|
|
}
|