214 lines
7.8 KiB
TypeScript
Raw Normal View History

import * as plugins from '../../../plugins.js';
2025-05-10 00:01:02 +00:00
import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
import type { IRouteConfig } from './route-types.js';
import type { TForwardingType } from '../../../forwarding/config/forwarding-types.js';
/**
* Provision object for static or HTTP-01 certificate
*/
export type TSmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01';
/**
2025-05-10 00:01:02 +00:00
* Alias for backward compatibility with code that uses IRoutedSmartProxyOptions
*/
export type IRoutedSmartProxyOptions = ISmartProxyOptions;
/**
* Legacy domain configuration interface for backward compatibility
*/
export interface IDomainConfig {
2025-05-10 00:01:02 +00:00
domains: string[];
forwarding: {
type: TForwardingType;
target: {
host: string | string[];
port: number;
};
acme?: {
enabled?: boolean;
maintenance?: boolean;
production?: boolean;
forwardChallenges?: {
host: string;
port: number;
useTls?: boolean;
};
};
http?: {
enabled?: boolean;
redirectToHttps?: boolean;
headers?: Record<string, string>;
};
https?: {
customCert?: {
key: string;
cert: string;
};
forwardSni?: boolean;
};
security?: {
allowedIps?: string[];
blockedIps?: string[];
maxConnections?: number;
};
advanced?: {
portRanges?: Array<{ from: number; to: number }>;
networkProxyPort?: number;
keepAlive?: boolean;
timeout?: number;
headers?: Record<string, string>;
};
};
}
/**
2025-05-10 00:01:02 +00:00
* Helper functions for type checking - now always assume route-based config
*/
export function isLegacyOptions(options: any): boolean {
return false; // No longer supporting legacy options
}
export function isRoutedOptions(options: any): boolean {
return true; // Always assume routed options
}
/**
* SmartProxy configuration options
*/
export interface ISmartProxyOptions {
2025-05-10 00:01:02 +00:00
// The unified configuration array (required)
routes: IRouteConfig[];
// Legacy options for backward compatibility
fromPort?: number;
toPort?: number;
sniEnabled?: boolean;
2025-05-10 00:01:02 +00:00
domainConfigs?: IDomainConfig[];
targetIP?: string;
defaultAllowedIPs?: string[];
defaultBlockedIPs?: string[];
2025-05-10 00:01:02 +00:00
globalPortRanges?: Array<{ from: number; to: number }>;
forwardAllGlobalRanges?: boolean;
preserveSourceIP?: boolean;
2025-05-10 00:01:02 +00:00
// Global/default settings
defaults?: {
target?: {
host: string; // Default host to use when not specified in routes
port: number; // Default port to use when not specified in routes
};
security?: {
allowedIPs?: string[]; // Default allowed IPs
blockedIPs?: string[]; // Default blocked IPs
maxConnections?: number; // Default max connections
};
preserveSourceIP?: boolean; // Default source IP preservation
};
// 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
// 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
acme?: IAcmeOptions;
/**
* Optional certificate provider callback. Return 'http01' to use HTTP-01 challenges,
* or a static certificate object for immediate provisioning.
*/
certProvisionFunction?: (domain: string) => Promise<TSmartProxyCertProvisionObject>;
}
/**
* Enhanced connection record
*/
export interface IConnectionRecord {
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
2025-05-10 00:01:02 +00:00
// Legacy property for backward compatibility
domainConfig?: IDomainConfig;
// 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-10 00:01:02 +00:00
routeConfig?: IRouteConfig; // Associated route config for this connection
// 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
}