fix(typescript): Refactor types and interfaces to use consistent I prefix and update related tests
This commit is contained in:
@ -2,26 +2,26 @@ import * as plugins from '../../plugins.js';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { type NetworkProxyOptions, type CertificateEntry, type Logger, createLogger } from './models/types.js';
|
||||
import { type INetworkProxyOptions, type ICertificateEntry, type ILogger, createLogger } from './models/types.js';
|
||||
import { Port80Handler } from '../../http/port80/port80-handler.js';
|
||||
import { CertificateEvents } from '../../certificate/events/certificate-events.js';
|
||||
import { buildPort80Handler } from '../../certificate/acme/acme-factory.js';
|
||||
import { subscribeToPort80Handler } from '../../core/utils/event-utils.js';
|
||||
import type { DomainOptions } from '../../certificate/models/certificate-types.js';
|
||||
import type { IDomainOptions } from '../../certificate/models/certificate-types.js';
|
||||
|
||||
/**
|
||||
* Manages SSL certificates for NetworkProxy including ACME integration
|
||||
*/
|
||||
export class CertificateManager {
|
||||
private defaultCertificates: { key: string; cert: string };
|
||||
private certificateCache: Map<string, CertificateEntry> = new Map();
|
||||
private certificateCache: Map<string, ICertificateEntry> = new Map();
|
||||
private port80Handler: Port80Handler | null = null;
|
||||
private externalPort80Handler: boolean = false;
|
||||
private certificateStoreDir: string;
|
||||
private logger: Logger;
|
||||
private logger: ILogger;
|
||||
private httpsServer: plugins.https.Server | null = null;
|
||||
|
||||
constructor(private options: NetworkProxyOptions) {
|
||||
constructor(private options: INetworkProxyOptions) {
|
||||
this.certificateStoreDir = path.resolve(options.acme?.certificateStore || './certs');
|
||||
this.logger = createLogger(options.logLevel || 'info');
|
||||
|
||||
@ -219,9 +219,9 @@ export class CertificateManager {
|
||||
|
||||
if (!certData) {
|
||||
this.logger.info(`No certificate found for ${domain}, registering for issuance`);
|
||||
|
||||
|
||||
// Register with new domain options format
|
||||
const domainOptions: DomainOptions = {
|
||||
const domainOptions: IDomainOptions = {
|
||||
domainName: domain,
|
||||
sslRedirect: true,
|
||||
acmeMaintenance: true
|
||||
@ -274,7 +274,7 @@ export class CertificateManager {
|
||||
/**
|
||||
* Gets a certificate for a domain
|
||||
*/
|
||||
public getCertificate(domain: string): CertificateEntry | undefined {
|
||||
public getCertificate(domain: string): ICertificateEntry | undefined {
|
||||
return this.certificateCache.get(domain);
|
||||
}
|
||||
|
||||
@ -300,7 +300,7 @@ export class CertificateManager {
|
||||
|
||||
try {
|
||||
// Use the new domain options format
|
||||
const domainOptions: DomainOptions = {
|
||||
const domainOptions: IDomainOptions = {
|
||||
domainName: domain,
|
||||
sslRedirect: true,
|
||||
acmeMaintenance: true
|
||||
@ -341,7 +341,7 @@ export class CertificateManager {
|
||||
}
|
||||
|
||||
// Register the domain for certificate issuance with new domain options format
|
||||
const domainOptions: DomainOptions = {
|
||||
const domainOptions: IDomainOptions = {
|
||||
domainName: domain,
|
||||
sslRedirect: true,
|
||||
acmeMaintenance: true
|
||||
|
@ -1,15 +1,15 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import { type NetworkProxyOptions, type ConnectionEntry, type Logger, createLogger } from './models/types.js';
|
||||
import { type INetworkProxyOptions, type IConnectionEntry, type ILogger, createLogger } from './models/types.js';
|
||||
|
||||
/**
|
||||
* Manages a pool of backend connections for efficient reuse
|
||||
*/
|
||||
export class ConnectionPool {
|
||||
private connectionPool: Map<string, Array<ConnectionEntry>> = new Map();
|
||||
private connectionPool: Map<string, Array<IConnectionEntry>> = new Map();
|
||||
private roundRobinPositions: Map<string, number> = new Map();
|
||||
private logger: Logger;
|
||||
private logger: ILogger;
|
||||
|
||||
constructor(private options: NetworkProxyOptions) {
|
||||
constructor(private options: INetworkProxyOptions) {
|
||||
this.logger = createLogger(options.logLevel || 'info');
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { AcmeOptions } from '../../../certificate/models/certificate-types.js';
|
||||
import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
|
||||
|
||||
/**
|
||||
* Configuration options for NetworkProxy
|
||||
*/
|
||||
export interface NetworkProxyOptions {
|
||||
export interface INetworkProxyOptions {
|
||||
port: number;
|
||||
maxConnections?: number;
|
||||
keepAliveTimeout?: number;
|
||||
@ -16,22 +16,22 @@ export interface NetworkProxyOptions {
|
||||
allowHeaders?: string;
|
||||
maxAge?: number;
|
||||
};
|
||||
|
||||
|
||||
// Settings for SmartProxy integration
|
||||
connectionPoolSize?: number; // Maximum connections to maintain in the pool to each backend
|
||||
portProxyIntegration?: boolean; // Flag to indicate this proxy is used by SmartProxy
|
||||
useExternalPort80Handler?: boolean; // Flag to indicate using external Port80Handler
|
||||
// Protocol to use when proxying to backends: HTTP/1.x or HTTP/2
|
||||
backendProtocol?: 'http1' | 'http2';
|
||||
|
||||
|
||||
// ACME certificate management options
|
||||
acme?: AcmeOptions;
|
||||
acme?: IAcmeOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for a certificate entry in the cache
|
||||
*/
|
||||
export interface CertificateEntry {
|
||||
export interface ICertificateEntry {
|
||||
key: string;
|
||||
cert: string;
|
||||
expires?: Date;
|
||||
@ -40,7 +40,7 @@ export interface CertificateEntry {
|
||||
/**
|
||||
* Interface for reverse proxy configuration
|
||||
*/
|
||||
export interface ReverseProxyConfig {
|
||||
export interface IReverseProxyConfig {
|
||||
destinationIps: string[];
|
||||
destinationPorts: number[];
|
||||
hostName: string;
|
||||
@ -62,7 +62,7 @@ export interface ReverseProxyConfig {
|
||||
/**
|
||||
* Interface for connection tracking in the pool
|
||||
*/
|
||||
export interface ConnectionEntry {
|
||||
export interface IConnectionEntry {
|
||||
socket: plugins.net.Socket;
|
||||
lastUsed: number;
|
||||
isIdle: boolean;
|
||||
@ -71,7 +71,7 @@ export interface ConnectionEntry {
|
||||
/**
|
||||
* WebSocket with heartbeat interface
|
||||
*/
|
||||
export interface WebSocketWithHeartbeat extends plugins.wsDefault {
|
||||
export interface IWebSocketWithHeartbeat extends plugins.wsDefault {
|
||||
lastPong: number;
|
||||
isAlive: boolean;
|
||||
}
|
||||
@ -79,7 +79,7 @@ export interface WebSocketWithHeartbeat extends plugins.wsDefault {
|
||||
/**
|
||||
* Logger interface for consistent logging across components
|
||||
*/
|
||||
export interface Logger {
|
||||
export interface ILogger {
|
||||
debug(message: string, data?: any): void;
|
||||
info(message: string, data?: any): void;
|
||||
warn(message: string, data?: any): void;
|
||||
@ -89,14 +89,14 @@ export interface Logger {
|
||||
/**
|
||||
* Creates a logger based on the specified log level
|
||||
*/
|
||||
export function createLogger(logLevel: string = 'info'): Logger {
|
||||
export function createLogger(logLevel: string = 'info'): ILogger {
|
||||
const logLevels = {
|
||||
error: 0,
|
||||
warn: 1,
|
||||
info: 2,
|
||||
debug: 3
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
debug: (message: string, data?: any) => {
|
||||
if (logLevels[logLevel] >= logLevels.debug) {
|
||||
@ -119,12 +119,4 @@ export function createLogger(logLevel: string = 'info'): Logger {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Backward compatibility interfaces
|
||||
export interface INetworkProxyOptions extends NetworkProxyOptions {}
|
||||
export interface ICertificateEntry extends CertificateEntry {}
|
||||
export interface IReverseProxyConfig extends ReverseProxyConfig {}
|
||||
export interface IConnectionEntry extends ConnectionEntry {}
|
||||
export interface IWebSocketWithHeartbeat extends WebSocketWithHeartbeat {}
|
||||
export interface ILogger extends Logger {}
|
||||
}
|
@ -3,9 +3,9 @@ import {
|
||||
createLogger
|
||||
} from './models/types.js';
|
||||
import type {
|
||||
NetworkProxyOptions,
|
||||
Logger,
|
||||
ReverseProxyConfig
|
||||
INetworkProxyOptions,
|
||||
ILogger,
|
||||
IReverseProxyConfig
|
||||
} from './models/types.js';
|
||||
import { CertificateManager } from './certificate-manager.js';
|
||||
import { ConnectionPool } from './connection-pool.js';
|
||||
@ -24,8 +24,8 @@ export class NetworkProxy implements IMetricsTracker {
|
||||
return {};
|
||||
}
|
||||
// Configuration
|
||||
public options: NetworkProxyOptions;
|
||||
public proxyConfigs: ReverseProxyConfig[] = [];
|
||||
public options: INetworkProxyOptions;
|
||||
public proxyConfigs: IReverseProxyConfig[] = [];
|
||||
|
||||
// Server instances (HTTP/2 with HTTP/1 fallback)
|
||||
public httpsServer: any;
|
||||
@ -54,12 +54,12 @@ export class NetworkProxy implements IMetricsTracker {
|
||||
private connectionPoolCleanupInterval: NodeJS.Timeout;
|
||||
|
||||
// Logger
|
||||
private logger: Logger;
|
||||
private logger: ILogger;
|
||||
|
||||
/**
|
||||
* Creates a new NetworkProxy instance
|
||||
*/
|
||||
constructor(optionsArg: NetworkProxyOptions) {
|
||||
constructor(optionsArg: INetworkProxyOptions) {
|
||||
// Set default options
|
||||
this.options = {
|
||||
port: optionsArg.port,
|
||||
@ -328,7 +328,7 @@ export class NetworkProxy implements IMetricsTracker {
|
||||
* Updates proxy configurations
|
||||
*/
|
||||
public async updateProxyConfigs(
|
||||
proxyConfigsArg: ReverseProxyConfig[]
|
||||
proxyConfigsArg: IReverseProxyConfig[]
|
||||
): Promise<void> {
|
||||
this.logger.info(`Updating proxy configurations (${proxyConfigsArg.length} configs)`);
|
||||
|
||||
@ -385,8 +385,8 @@ export class NetworkProxy implements IMetricsTracker {
|
||||
allowedIPs?: string[];
|
||||
}>,
|
||||
sslKeyPair?: { key: string; cert: string }
|
||||
): ReverseProxyConfig[] {
|
||||
const proxyConfigs: ReverseProxyConfig[] = [];
|
||||
): IReverseProxyConfig[] {
|
||||
const proxyConfigs: IReverseProxyConfig[] = [];
|
||||
|
||||
// Use default certificates if not provided
|
||||
const defaultCerts = this.certificateManager.getDefaultCertificates();
|
||||
@ -478,7 +478,7 @@ export class NetworkProxy implements IMetricsTracker {
|
||||
/**
|
||||
* Gets all proxy configurations currently in use
|
||||
*/
|
||||
public getProxyConfigs(): ReverseProxyConfig[] {
|
||||
public getProxyConfigs(): IReverseProxyConfig[] {
|
||||
return [...this.proxyConfigs];
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import { type NetworkProxyOptions, type Logger, createLogger, type ReverseProxyConfig } from './models/types.js';
|
||||
import { type INetworkProxyOptions, type ILogger, createLogger, type IReverseProxyConfig } from './models/types.js';
|
||||
import { ConnectionPool } from './connection-pool.js';
|
||||
import { ProxyRouter } from '../../http/router/index.js';
|
||||
|
||||
@ -19,13 +19,13 @@ export type MetricsTracker = IMetricsTracker;
|
||||
*/
|
||||
export class RequestHandler {
|
||||
private defaultHeaders: { [key: string]: string } = {};
|
||||
private logger: Logger;
|
||||
private logger: ILogger;
|
||||
private metricsTracker: IMetricsTracker | null = null;
|
||||
// HTTP/2 client sessions for backend proxying
|
||||
private h2Sessions: Map<string, plugins.http2.ClientHttp2Session> = new Map();
|
||||
|
||||
constructor(
|
||||
private options: NetworkProxyOptions,
|
||||
private options: INetworkProxyOptions,
|
||||
private connectionPool: ConnectionPool,
|
||||
private router: ProxyRouter
|
||||
) {
|
||||
@ -137,7 +137,7 @@ export class RequestHandler {
|
||||
this.applyDefaultHeaders(res);
|
||||
|
||||
// Determine routing configuration
|
||||
let proxyConfig: ReverseProxyConfig | undefined;
|
||||
let proxyConfig: IReverseProxyConfig | undefined;
|
||||
try {
|
||||
proxyConfig = this.router.routeReq(req);
|
||||
} catch (err) {
|
||||
@ -235,7 +235,7 @@ export class RequestHandler {
|
||||
// Remove host header to avoid issues with virtual hosts on target server
|
||||
// The host header should match the target server's expected hostname
|
||||
if (options.headers && options.headers.host) {
|
||||
if ((proxyConfig as ReverseProxyConfig).rewriteHostHeader) {
|
||||
if ((proxyConfig as IReverseProxyConfig).rewriteHostHeader) {
|
||||
options.headers.host = `${destination.host}:${destination.port}`;
|
||||
}
|
||||
}
|
||||
@ -426,7 +426,7 @@ export class RequestHandler {
|
||||
outboundHeaders[key] = value;
|
||||
}
|
||||
}
|
||||
if (outboundHeaders.host && (proxyConfig as any).rewriteHostHeader) {
|
||||
if (outboundHeaders.host && (proxyConfig as IReverseProxyConfig).rewriteHostHeader) {
|
||||
outboundHeaders.host = `${destination.host}:${destination.port}`;
|
||||
}
|
||||
// Create HTTP/1 proxy request
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import { type NetworkProxyOptions, type WebSocketWithHeartbeat, type Logger, createLogger, type ReverseProxyConfig } from './models/types.js';
|
||||
import { type INetworkProxyOptions, type IWebSocketWithHeartbeat, type ILogger, createLogger, type IReverseProxyConfig } from './models/types.js';
|
||||
import { ConnectionPool } from './connection-pool.js';
|
||||
import { ProxyRouter } from '../../http/router/index.js';
|
||||
|
||||
@ -9,10 +9,10 @@ import { ProxyRouter } from '../../http/router/index.js';
|
||||
export class WebSocketHandler {
|
||||
private heartbeatInterval: NodeJS.Timeout | null = null;
|
||||
private wsServer: plugins.ws.WebSocketServer | null = null;
|
||||
private logger: Logger;
|
||||
private logger: ILogger;
|
||||
|
||||
constructor(
|
||||
private options: NetworkProxyOptions,
|
||||
private options: INetworkProxyOptions,
|
||||
private connectionPool: ConnectionPool,
|
||||
private router: ProxyRouter
|
||||
) {
|
||||
@ -30,7 +30,7 @@ export class WebSocketHandler {
|
||||
});
|
||||
|
||||
// Handle WebSocket connections
|
||||
this.wsServer.on('connection', (wsIncoming: WebSocketWithHeartbeat, req: plugins.http.IncomingMessage) => {
|
||||
this.wsServer.on('connection', (wsIncoming: IWebSocketWithHeartbeat, req: plugins.http.IncomingMessage) => {
|
||||
this.handleWebSocketConnection(wsIncoming, req);
|
||||
});
|
||||
|
||||
@ -56,9 +56,9 @@ export class WebSocketHandler {
|
||||
}
|
||||
|
||||
this.logger.debug(`WebSocket heartbeat check for ${this.wsServer.clients.size} clients`);
|
||||
|
||||
|
||||
this.wsServer.clients.forEach((ws: plugins.wsDefault) => {
|
||||
const wsWithHeartbeat = ws as WebSocketWithHeartbeat;
|
||||
const wsWithHeartbeat = ws as IWebSocketWithHeartbeat;
|
||||
|
||||
if (wsWithHeartbeat.isAlive === false) {
|
||||
this.logger.debug('Terminating inactive WebSocket connection');
|
||||
@ -79,7 +79,7 @@ export class WebSocketHandler {
|
||||
/**
|
||||
* Handle a new WebSocket connection
|
||||
*/
|
||||
private handleWebSocketConnection(wsIncoming: WebSocketWithHeartbeat, req: plugins.http.IncomingMessage): void {
|
||||
private handleWebSocketConnection(wsIncoming: IWebSocketWithHeartbeat, req: plugins.http.IncomingMessage): void {
|
||||
try {
|
||||
// Initialize heartbeat tracking
|
||||
wsIncoming.isAlive = true;
|
||||
@ -127,7 +127,7 @@ export class WebSocketHandler {
|
||||
}
|
||||
|
||||
// Override host header if needed
|
||||
if ((proxyConfig as ReverseProxyConfig).rewriteHostHeader) {
|
||||
if ((proxyConfig as IReverseProxyConfig).rewriteHostHeader) {
|
||||
headers['host'] = `${destination.host}:${destination.port}`;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import type {
|
||||
ConnectionRecord,
|
||||
DomainConfig,
|
||||
SmartProxyOptions,
|
||||
IConnectionRecord,
|
||||
IDomainConfig,
|
||||
ISmartProxyOptions,
|
||||
} from './models/interfaces.js';
|
||||
import { ConnectionManager } from './connection-manager.js';
|
||||
import { SecurityManager } from './security-manager.js';
|
||||
@ -12,14 +12,14 @@ import { NetworkProxyBridge } from './network-proxy-bridge.js';
|
||||
import { TimeoutManager } from './timeout-manager.js';
|
||||
import { PortRangeManager } from './port-range-manager.js';
|
||||
import type { ForwardingHandler } from '../../forwarding/handlers/base-handler.js';
|
||||
import type { ForwardingType } from '../../forwarding/config/forwarding-types.js';
|
||||
import type { TForwardingType } from '../../forwarding/config/forwarding-types.js';
|
||||
|
||||
/**
|
||||
* Handles new connection processing and setup logic
|
||||
*/
|
||||
export class ConnectionHandler {
|
||||
constructor(
|
||||
private settings: SmartProxyOptions,
|
||||
private settings: ISmartProxyOptions,
|
||||
private connectionManager: ConnectionManager,
|
||||
private securityManager: SecurityManager,
|
||||
private domainConfigManager: DomainConfigManager,
|
||||
@ -102,7 +102,7 @@ export class ConnectionHandler {
|
||||
*/
|
||||
private handleNetworkProxyConnection(
|
||||
socket: plugins.net.Socket,
|
||||
record: ConnectionRecord
|
||||
record: IConnectionRecord
|
||||
): void {
|
||||
const connectionId = record.id;
|
||||
let initialDataReceived = false;
|
||||
@ -307,7 +307,7 @@ export class ConnectionHandler {
|
||||
/**
|
||||
* Handle a standard (non-NetworkProxy) connection
|
||||
*/
|
||||
private handleStandardConnection(socket: plugins.net.Socket, record: ConnectionRecord): void {
|
||||
private handleStandardConnection(socket: plugins.net.Socket, record: IConnectionRecord): void {
|
||||
const connectionId = record.id;
|
||||
const localPort = record.localPort;
|
||||
|
||||
@ -382,7 +382,7 @@ export class ConnectionHandler {
|
||||
const setupConnection = (
|
||||
serverName: string,
|
||||
initialChunk?: Buffer,
|
||||
forcedDomain?: DomainConfig,
|
||||
forcedDomain?: IDomainConfig,
|
||||
overridePort?: number
|
||||
) => {
|
||||
// Clear the initial timeout since we've received data
|
||||
@ -500,7 +500,7 @@ export class ConnectionHandler {
|
||||
const globalDomainConfig = {
|
||||
domains: ['global'],
|
||||
forwarding: {
|
||||
type: 'http-only' as ForwardingType,
|
||||
type: 'http-only' as TForwardingType,
|
||||
target: {
|
||||
host: this.settings.targetIP!,
|
||||
port: this.settings.toPort
|
||||
@ -730,8 +730,8 @@ export class ConnectionHandler {
|
||||
*/
|
||||
private setupDirectConnection(
|
||||
socket: plugins.net.Socket,
|
||||
record: ConnectionRecord,
|
||||
domainConfig?: DomainConfig,
|
||||
record: IConnectionRecord,
|
||||
domainConfig?: IDomainConfig,
|
||||
serverName?: string,
|
||||
initialChunk?: Buffer,
|
||||
overridePort?: number
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import type { ConnectionRecord, SmartProxyOptions } from './models/interfaces.js';
|
||||
import type { IConnectionRecord, ISmartProxyOptions } from './models/interfaces.js';
|
||||
import { SecurityManager } from './security-manager.js';
|
||||
import { TimeoutManager } from './timeout-manager.js';
|
||||
|
||||
@ -7,14 +7,14 @@ import { TimeoutManager } from './timeout-manager.js';
|
||||
* Manages connection lifecycle, tracking, and cleanup
|
||||
*/
|
||||
export class ConnectionManager {
|
||||
private connectionRecords: Map<string, ConnectionRecord> = new Map();
|
||||
private connectionRecords: Map<string, IConnectionRecord> = new Map();
|
||||
private terminationStats: {
|
||||
incoming: Record<string, number>;
|
||||
outgoing: Record<string, number>;
|
||||
} = { incoming: {}, outgoing: {} };
|
||||
|
||||
constructor(
|
||||
private settings: SmartProxyOptions,
|
||||
private settings: ISmartProxyOptions,
|
||||
private securityManager: SecurityManager,
|
||||
private timeoutManager: TimeoutManager
|
||||
) {}
|
||||
@ -30,12 +30,12 @@ export class ConnectionManager {
|
||||
/**
|
||||
* Create and track a new connection
|
||||
*/
|
||||
public createConnection(socket: plugins.net.Socket): ConnectionRecord {
|
||||
public createConnection(socket: plugins.net.Socket): IConnectionRecord {
|
||||
const connectionId = this.generateConnectionId();
|
||||
const remoteIP = socket.remoteAddress || '';
|
||||
const localPort = socket.localPort || 0;
|
||||
|
||||
const record: ConnectionRecord = {
|
||||
const record: IConnectionRecord = {
|
||||
id: connectionId,
|
||||
incoming: socket,
|
||||
outgoing: null,
|
||||
@ -66,7 +66,7 @@ export class ConnectionManager {
|
||||
/**
|
||||
* Track an existing connection
|
||||
*/
|
||||
public trackConnection(connectionId: string, record: ConnectionRecord): void {
|
||||
public trackConnection(connectionId: string, record: IConnectionRecord): void {
|
||||
this.connectionRecords.set(connectionId, record);
|
||||
this.securityManager.trackConnectionByIP(record.remoteIP, connectionId);
|
||||
}
|
||||
@ -74,14 +74,14 @@ export class ConnectionManager {
|
||||
/**
|
||||
* Get a connection by ID
|
||||
*/
|
||||
public getConnection(connectionId: string): ConnectionRecord | undefined {
|
||||
public getConnection(connectionId: string): IConnectionRecord | undefined {
|
||||
return this.connectionRecords.get(connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active connections
|
||||
*/
|
||||
public getConnections(): Map<string, ConnectionRecord> {
|
||||
public getConnections(): Map<string, IConnectionRecord> {
|
||||
return this.connectionRecords;
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ export class ConnectionManager {
|
||||
/**
|
||||
* Initiates cleanup once for a connection
|
||||
*/
|
||||
public initiateCleanupOnce(record: ConnectionRecord, reason: string = 'normal'): void {
|
||||
public initiateCleanupOnce(record: IConnectionRecord, reason: string = 'normal'): void {
|
||||
if (this.settings.enableDetailedLogging) {
|
||||
console.log(`[${record.id}] Connection cleanup initiated for ${record.remoteIP} (${reason})`);
|
||||
}
|
||||
@ -110,11 +110,11 @@ export class ConnectionManager {
|
||||
|
||||
this.cleanupConnection(record, reason);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clean up a connection record
|
||||
*/
|
||||
public cleanupConnection(record: ConnectionRecord, reason: string = 'normal'): void {
|
||||
public cleanupConnection(record: IConnectionRecord, reason: string = 'normal'): void {
|
||||
if (!record.connectionClosed) {
|
||||
record.connectionClosed = true;
|
||||
|
||||
@ -178,7 +178,7 @@ export class ConnectionManager {
|
||||
/**
|
||||
* Helper method to clean up a socket
|
||||
*/
|
||||
private cleanupSocket(record: ConnectionRecord, side: 'incoming' | 'outgoing', socket: plugins.net.Socket): void {
|
||||
private cleanupSocket(record: IConnectionRecord, side: 'incoming' | 'outgoing', socket: plugins.net.Socket): void {
|
||||
try {
|
||||
if (!socket.destroyed) {
|
||||
// Try graceful shutdown first, then force destroy after a short timeout
|
||||
@ -213,7 +213,7 @@ export class ConnectionManager {
|
||||
/**
|
||||
* Creates a generic error handler for incoming or outgoing sockets
|
||||
*/
|
||||
public handleError(side: 'incoming' | 'outgoing', record: ConnectionRecord) {
|
||||
public handleError(side: 'incoming' | 'outgoing', record: IConnectionRecord) {
|
||||
return (err: Error) => {
|
||||
const code = (err as any).code;
|
||||
let reason = 'error';
|
||||
@ -256,7 +256,7 @@ export class ConnectionManager {
|
||||
/**
|
||||
* Creates a generic close handler for incoming or outgoing sockets
|
||||
*/
|
||||
public handleClose(side: 'incoming' | 'outgoing', record: ConnectionRecord) {
|
||||
public handleClose(side: 'incoming' | 'outgoing', record: IConnectionRecord) {
|
||||
return () => {
|
||||
if (this.settings.enableDetailedLogging) {
|
||||
console.log(`[${record.id}] Connection closed on ${side} side from ${record.remoteIP}`);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import type { DomainConfig, SmartProxyOptions } from './models/interfaces.js';
|
||||
import type { ForwardingType, ForwardConfig } from '../../forwarding/config/forwarding-types.js';
|
||||
import type { IDomainConfig, ISmartProxyOptions } from './models/interfaces.js';
|
||||
import type { TForwardingType, IForwardConfig } from '../../forwarding/config/forwarding-types.js';
|
||||
import type { ForwardingHandler } from '../../forwarding/handlers/base-handler.js';
|
||||
import { ForwardingHandlerFactory } from '../../forwarding/factory/forwarding-factory.js';
|
||||
|
||||
@ -9,17 +9,17 @@ import { ForwardingHandlerFactory } from '../../forwarding/factory/forwarding-fa
|
||||
*/
|
||||
export class DomainConfigManager {
|
||||
// Track round-robin indices for domain configs
|
||||
private domainTargetIndices: Map<DomainConfig, number> = new Map();
|
||||
private domainTargetIndices: Map<IDomainConfig, number> = new Map();
|
||||
|
||||
// Cache forwarding handlers for each domain config
|
||||
private forwardingHandlers: Map<DomainConfig, ForwardingHandler> = new Map();
|
||||
private forwardingHandlers: Map<IDomainConfig, ForwardingHandler> = new Map();
|
||||
|
||||
constructor(private settings: SmartProxyOptions) {}
|
||||
constructor(private settings: ISmartProxyOptions) {}
|
||||
|
||||
/**
|
||||
* Updates the domain configurations
|
||||
*/
|
||||
public updateDomainConfigs(newDomainConfigs: DomainConfig[]): void {
|
||||
public updateDomainConfigs(newDomainConfigs: IDomainConfig[]): void {
|
||||
this.settings.domainConfigs = newDomainConfigs;
|
||||
|
||||
// Reset target indices for removed configs
|
||||
@ -31,7 +31,7 @@ export class DomainConfigManager {
|
||||
}
|
||||
|
||||
// Clear handlers for removed configs and create handlers for new configs
|
||||
const handlersToRemove: DomainConfig[] = [];
|
||||
const handlersToRemove: IDomainConfig[] = [];
|
||||
for (const [config] of this.forwardingHandlers) {
|
||||
if (!currentConfigSet.has(config)) {
|
||||
handlersToRemove.push(config);
|
||||
@ -55,29 +55,29 @@ export class DomainConfigManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all domain configurations
|
||||
*/
|
||||
public getDomainConfigs(): DomainConfig[] {
|
||||
public getDomainConfigs(): IDomainConfig[] {
|
||||
return this.settings.domainConfigs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find domain config matching a server name
|
||||
*/
|
||||
public findDomainConfig(serverName: string): DomainConfig | undefined {
|
||||
public findDomainConfig(serverName: string): IDomainConfig | undefined {
|
||||
if (!serverName) return undefined;
|
||||
|
||||
|
||||
return this.settings.domainConfigs.find((config) =>
|
||||
config.domains.some((d) => plugins.minimatch(serverName, d))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find domain config for a specific port
|
||||
*/
|
||||
public findDomainConfigForPort(port: number): DomainConfig | undefined {
|
||||
public findDomainConfigForPort(port: number): IDomainConfig | undefined {
|
||||
return this.settings.domainConfigs.find(
|
||||
(domain) => {
|
||||
const portRanges = domain.forwarding?.advanced?.portRanges;
|
||||
@ -98,7 +98,7 @@ export class DomainConfigManager {
|
||||
/**
|
||||
* Get target IP with round-robin support
|
||||
*/
|
||||
public getTargetIP(domainConfig: DomainConfig): string {
|
||||
public getTargetIP(domainConfig: IDomainConfig): string {
|
||||
const targetHosts = Array.isArray(domainConfig.forwarding.target.host)
|
||||
? domainConfig.forwarding.target.host
|
||||
: [domainConfig.forwarding.target.host];
|
||||
@ -117,21 +117,21 @@ export class DomainConfigManager {
|
||||
* Get target host with round-robin support (for tests)
|
||||
* This is just an alias for getTargetIP for easier test compatibility
|
||||
*/
|
||||
public getTargetHost(domainConfig: DomainConfig): string {
|
||||
public getTargetHost(domainConfig: IDomainConfig): string {
|
||||
return this.getTargetIP(domainConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get target port from domain config
|
||||
*/
|
||||
public getTargetPort(domainConfig: DomainConfig, defaultPort: number): number {
|
||||
public getTargetPort(domainConfig: IDomainConfig, defaultPort: number): number {
|
||||
return domainConfig.forwarding.target.port || defaultPort;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a domain should use NetworkProxy
|
||||
*/
|
||||
public shouldUseNetworkProxy(domainConfig: DomainConfig): boolean {
|
||||
public shouldUseNetworkProxy(domainConfig: IDomainConfig): boolean {
|
||||
const forwardingType = this.getForwardingType(domainConfig);
|
||||
return forwardingType === 'https-terminate-to-http' ||
|
||||
forwardingType === 'https-terminate-to-https';
|
||||
@ -140,7 +140,7 @@ export class DomainConfigManager {
|
||||
/**
|
||||
* Gets the NetworkProxy port for a domain
|
||||
*/
|
||||
public getNetworkProxyPort(domainConfig: DomainConfig): number | undefined {
|
||||
public getNetworkProxyPort(domainConfig: IDomainConfig): number | undefined {
|
||||
// First check if we should use NetworkProxy at all
|
||||
if (!this.shouldUseNetworkProxy(domainConfig)) {
|
||||
return undefined;
|
||||
@ -148,14 +148,14 @@ export class DomainConfigManager {
|
||||
|
||||
return domainConfig.forwarding.advanced?.networkProxyPort || this.settings.networkProxyPort;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get effective allowed and blocked IPs for a domain
|
||||
*
|
||||
* This method combines domain-specific security rules from the forwarding configuration
|
||||
* with global security defaults when necessary.
|
||||
*/
|
||||
public getEffectiveIPRules(domainConfig: DomainConfig): {
|
||||
public getEffectiveIPRules(domainConfig: IDomainConfig): {
|
||||
allowedIPs: string[],
|
||||
blockedIPs: string[]
|
||||
} {
|
||||
@ -201,7 +201,7 @@ export class DomainConfigManager {
|
||||
/**
|
||||
* Get connection timeout for a domain
|
||||
*/
|
||||
public getConnectionTimeout(domainConfig?: DomainConfig): number {
|
||||
public getConnectionTimeout(domainConfig?: IDomainConfig): number {
|
||||
if (domainConfig?.forwarding.advanced?.timeout) {
|
||||
return domainConfig.forwarding.advanced.timeout;
|
||||
}
|
||||
@ -212,7 +212,7 @@ export class DomainConfigManager {
|
||||
/**
|
||||
* Creates a forwarding handler for a domain configuration
|
||||
*/
|
||||
private createForwardingHandler(domainConfig: DomainConfig): ForwardingHandler {
|
||||
private createForwardingHandler(domainConfig: IDomainConfig): ForwardingHandler {
|
||||
// Create a new handler using the factory
|
||||
const handler = ForwardingHandlerFactory.createHandler(domainConfig.forwarding);
|
||||
|
||||
@ -228,7 +228,7 @@ export class DomainConfigManager {
|
||||
* Gets a forwarding handler for a domain config
|
||||
* If no handler exists, creates one
|
||||
*/
|
||||
public getForwardingHandler(domainConfig: DomainConfig): ForwardingHandler {
|
||||
public getForwardingHandler(domainConfig: IDomainConfig): ForwardingHandler {
|
||||
// If we already have a handler, return it
|
||||
if (this.forwardingHandlers.has(domainConfig)) {
|
||||
return this.forwardingHandlers.get(domainConfig)!;
|
||||
@ -244,7 +244,7 @@ export class DomainConfigManager {
|
||||
/**
|
||||
* Gets the forwarding type for a domain config
|
||||
*/
|
||||
public getForwardingType(domainConfig?: DomainConfig): ForwardingType | undefined {
|
||||
public getForwardingType(domainConfig?: IDomainConfig): TForwardingType | undefined {
|
||||
if (!domainConfig?.forwarding) return undefined;
|
||||
return domainConfig.forwarding.type;
|
||||
}
|
||||
@ -252,7 +252,7 @@ export class DomainConfigManager {
|
||||
/**
|
||||
* Checks if the forwarding type requires TLS termination
|
||||
*/
|
||||
public requiresTlsTermination(domainConfig?: DomainConfig): boolean {
|
||||
public requiresTlsTermination(domainConfig?: IDomainConfig): boolean {
|
||||
if (!domainConfig) return false;
|
||||
|
||||
const forwardingType = this.getForwardingType(domainConfig);
|
||||
@ -263,7 +263,7 @@ export class DomainConfigManager {
|
||||
/**
|
||||
* Checks if the forwarding type supports HTTP
|
||||
*/
|
||||
public supportsHttp(domainConfig?: DomainConfig): boolean {
|
||||
public supportsHttp(domainConfig?: IDomainConfig): boolean {
|
||||
if (!domainConfig) return false;
|
||||
|
||||
const forwardingType = this.getForwardingType(domainConfig);
|
||||
@ -285,7 +285,7 @@ export class DomainConfigManager {
|
||||
/**
|
||||
* Checks if HTTP requests should be redirected to HTTPS
|
||||
*/
|
||||
public shouldRedirectToHttps(domainConfig?: DomainConfig): boolean {
|
||||
public shouldRedirectToHttps(domainConfig?: IDomainConfig): boolean {
|
||||
if (!domainConfig?.forwarding) return false;
|
||||
|
||||
// Only check for redirect if HTTP is enabled
|
||||
|
@ -1,28 +1,28 @@
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { ForwardConfig } from '../../../forwarding/config/forwarding-types.js';
|
||||
import type { IForwardConfig } from '../../../forwarding/config/forwarding-types.js';
|
||||
|
||||
/**
|
||||
* Provision object for static or HTTP-01 certificate
|
||||
*/
|
||||
export type SmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01';
|
||||
export type TSmartProxyCertProvisionObject = plugins.tsclass.network.ICert | 'http01';
|
||||
|
||||
/**
|
||||
* Domain configuration with forwarding configuration
|
||||
*/
|
||||
export interface DomainConfig {
|
||||
export interface IDomainConfig {
|
||||
domains: string[]; // Glob patterns for domain(s)
|
||||
forwarding: ForwardConfig; // Unified forwarding configuration
|
||||
forwarding: IForwardConfig; // Unified forwarding configuration
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options for the SmartProxy
|
||||
*/
|
||||
import type { AcmeOptions } from '../../../certificate/models/certificate-types.js';
|
||||
export interface SmartProxyOptions {
|
||||
import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
|
||||
export interface ISmartProxyOptions {
|
||||
fromPort: number;
|
||||
toPort: number;
|
||||
targetIP?: string; // Global target host to proxy to, defaults to 'localhost'
|
||||
domainConfigs: DomainConfig[];
|
||||
domainConfigs: IDomainConfig[];
|
||||
sniEnabled?: boolean;
|
||||
defaultAllowedIPs?: string[];
|
||||
defaultBlockedIPs?: string[];
|
||||
@ -81,19 +81,19 @@ export interface SmartProxyOptions {
|
||||
networkProxyPort?: number; // Port where NetworkProxy is listening (default: 8443)
|
||||
|
||||
// ACME configuration options for SmartProxy
|
||||
acme?: AcmeOptions;
|
||||
|
||||
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<SmartProxyCertProvisionObject>;
|
||||
certProvisionFunction?: (domain: string) => Promise<TSmartProxyCertProvisionObject>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced connection record
|
||||
*/
|
||||
export interface ConnectionRecord {
|
||||
export interface IConnectionRecord {
|
||||
id: string; // Unique connection identifier
|
||||
incoming: plugins.net.Socket;
|
||||
outgoing: plugins.net.Socket | null;
|
||||
@ -116,7 +116,7 @@ export interface ConnectionRecord {
|
||||
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
|
||||
domainConfig?: DomainConfig; // Associated domain config for this connection
|
||||
domainConfig?: IDomainConfig; // Associated domain config for this connection
|
||||
|
||||
// Keep-alive tracking
|
||||
hasKeepAlive: boolean; // Whether keep-alive is enabled for this connection
|
||||
@ -133,10 +133,4 @@ export interface ConnectionRecord {
|
||||
// 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
|
||||
}
|
||||
|
||||
// Backward compatibility types
|
||||
export type ISmartProxyCertProvisionObject = SmartProxyCertProvisionObject;
|
||||
export interface IDomainConfig extends DomainConfig {}
|
||||
export interface ISmartProxyOptions extends SmartProxyOptions {}
|
||||
export interface IConnectionRecord extends ConnectionRecord {}
|
||||
}
|
@ -3,8 +3,8 @@ import { NetworkProxy } from '../network-proxy/index.js';
|
||||
import { Port80Handler } from '../../http/port80/port80-handler.js';
|
||||
import { Port80HandlerEvents } from '../../core/models/common-types.js';
|
||||
import { subscribeToPort80Handler } from '../../core/utils/event-utils.js';
|
||||
import type { CertificateData } from '../../certificate/models/certificate-types.js';
|
||||
import type { ConnectionRecord, SmartProxyOptions, DomainConfig } from './models/interfaces.js';
|
||||
import type { ICertificateData } from '../../certificate/models/certificate-types.js';
|
||||
import type { IConnectionRecord, ISmartProxyOptions, IDomainConfig } from './models/interfaces.js';
|
||||
|
||||
/**
|
||||
* Manages NetworkProxy integration for TLS termination
|
||||
@ -13,7 +13,7 @@ export class NetworkProxyBridge {
|
||||
private networkProxy: NetworkProxy | null = null;
|
||||
private port80Handler: Port80Handler | null = null;
|
||||
|
||||
constructor(private settings: SmartProxyOptions) {}
|
||||
constructor(private settings: ISmartProxyOptions) {}
|
||||
|
||||
/**
|
||||
* Set the Port80Handler to use for certificate management
|
||||
@ -66,23 +66,23 @@ export class NetworkProxyBridge {
|
||||
/**
|
||||
* Handle certificate issuance or renewal events
|
||||
*/
|
||||
private handleCertificateEvent(data: CertificateData): void {
|
||||
private handleCertificateEvent(data: ICertificateData): void {
|
||||
if (!this.networkProxy) return;
|
||||
|
||||
|
||||
console.log(`Received certificate for ${data.domain} from Port80Handler, updating NetworkProxy`);
|
||||
|
||||
|
||||
try {
|
||||
// Find existing config for this domain
|
||||
const existingConfigs = this.networkProxy.getProxyConfigs()
|
||||
.filter(config => config.hostName === data.domain);
|
||||
|
||||
|
||||
if (existingConfigs.length > 0) {
|
||||
// Update existing configs with new certificate
|
||||
for (const config of existingConfigs) {
|
||||
config.privateKey = data.privateKey;
|
||||
config.publicKey = data.certificate;
|
||||
}
|
||||
|
||||
|
||||
// Apply updated configs
|
||||
this.networkProxy.updateProxyConfigs(existingConfigs)
|
||||
.then(() => console.log(`Updated certificate for ${data.domain} in NetworkProxy`))
|
||||
@ -95,11 +95,11 @@ export class NetworkProxyBridge {
|
||||
console.log(`Error handling certificate event: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply an external (static) certificate into NetworkProxy
|
||||
*/
|
||||
public applyExternalCertificate(data: CertificateData): void {
|
||||
public applyExternalCertificate(data: ICertificateData): void {
|
||||
if (!this.networkProxy) {
|
||||
console.log(`NetworkProxy not initialized: cannot apply external certificate for ${data.domain}`);
|
||||
return;
|
||||
@ -183,7 +183,7 @@ export class NetworkProxyBridge {
|
||||
public forwardToNetworkProxy(
|
||||
connectionId: string,
|
||||
socket: plugins.net.Socket,
|
||||
record: ConnectionRecord,
|
||||
record: IConnectionRecord,
|
||||
initialData: Buffer,
|
||||
customProxyPort?: number,
|
||||
onError?: (reason: string) => void
|
||||
|
@ -1,10 +1,10 @@
|
||||
import type { SmartProxyOptions } from './models/interfaces.js';
|
||||
import type { ISmartProxyOptions } from './models/interfaces.js';
|
||||
|
||||
/**
|
||||
* Manages port ranges and port-based configuration
|
||||
*/
|
||||
export class PortRangeManager {
|
||||
constructor(private settings: SmartProxyOptions) {}
|
||||
constructor(private settings: ISmartProxyOptions) {}
|
||||
|
||||
/**
|
||||
* Get all ports that should be listened on
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import type { SmartProxyOptions } from './models/interfaces.js';
|
||||
import type { ISmartProxyOptions } from './models/interfaces.js';
|
||||
|
||||
/**
|
||||
* Handles security aspects like IP tracking, rate limiting, and authorization
|
||||
@ -8,7 +8,7 @@ export class SecurityManager {
|
||||
private connectionsByIP: Map<string, Set<string>> = new Map();
|
||||
private connectionRateByIP: Map<string, number[]> = new Map();
|
||||
|
||||
constructor(private settings: SmartProxyOptions) {}
|
||||
constructor(private settings: ISmartProxyOptions) {}
|
||||
|
||||
/**
|
||||
* Get connections count by IP
|
||||
|
@ -13,15 +13,15 @@ import { ConnectionHandler } from './connection-handler.js';
|
||||
// External dependencies from migrated modules
|
||||
import { Port80Handler } from '../../http/port80/port80-handler.js';
|
||||
import { CertProvisioner } from '../../certificate/providers/cert-provisioner.js';
|
||||
import type { CertificateData } from '../../certificate/models/certificate-types.js';
|
||||
import type { ICertificateData } from '../../certificate/models/certificate-types.js';
|
||||
import { buildPort80Handler } from '../../certificate/acme/acme-factory.js';
|
||||
import type { ForwardingType } from '../../forwarding/config/forwarding-types.js';
|
||||
import type { TForwardingType } from '../../forwarding/config/forwarding-types.js';
|
||||
import { createPort80HandlerOptions } from '../../common/port80-adapter.js';
|
||||
|
||||
// Import types from models
|
||||
import type { SmartProxyOptions, DomainConfig } from './models/interfaces.js';
|
||||
import type { ISmartProxyOptions, IDomainConfig } from './models/interfaces.js';
|
||||
// Provide backward compatibility types
|
||||
export type { SmartProxyOptions as IPortProxySettings, DomainConfig as IDomainConfig };
|
||||
export type { ISmartProxyOptions as IPortProxySettings, IDomainConfig };
|
||||
|
||||
/**
|
||||
* SmartProxy - Main class that coordinates all components
|
||||
@ -46,7 +46,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
// CertProvisioner for unified certificate workflows
|
||||
private certProvisioner?: CertProvisioner;
|
||||
|
||||
constructor(settingsArg: SmartProxyOptions) {
|
||||
constructor(settingsArg: ISmartProxyOptions) {
|
||||
super();
|
||||
// Set reasonable defaults for all settings
|
||||
this.settings = {
|
||||
@ -63,12 +63,12 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
keepAliveInitialDelay: settingsArg.keepAliveInitialDelay || 10000,
|
||||
maxPendingDataSize: settingsArg.maxPendingDataSize || 10 * 1024 * 1024,
|
||||
disableInactivityCheck: settingsArg.disableInactivityCheck || false,
|
||||
enableKeepAliveProbes:
|
||||
enableKeepAliveProbes:
|
||||
settingsArg.enableKeepAliveProbes !== undefined ? settingsArg.enableKeepAliveProbes : true,
|
||||
enableDetailedLogging: settingsArg.enableDetailedLogging || false,
|
||||
enableTlsDebugLogging: settingsArg.enableTlsDebugLogging || false,
|
||||
enableRandomizedTimeouts: settingsArg.enableRandomizedTimeouts || false,
|
||||
allowSessionTicket:
|
||||
allowSessionTicket:
|
||||
settingsArg.allowSessionTicket !== undefined ? settingsArg.allowSessionTicket : true,
|
||||
maxConnectionsPerIP: settingsArg.maxConnectionsPerIP || 100,
|
||||
connectionRateLimitPerMinute: settingsArg.connectionRateLimitPerMinute || 300,
|
||||
@ -126,7 +126,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
/**
|
||||
* The settings for the port proxy
|
||||
*/
|
||||
public settings: SmartProxyOptions;
|
||||
public settings: ISmartProxyOptions;
|
||||
|
||||
/**
|
||||
* Initialize the Port80Handler for ACME certificate management
|
||||
@ -413,7 +413,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
/**
|
||||
* Updates the domain configurations for the proxy
|
||||
*/
|
||||
public async updateDomainConfigs(newDomainConfigs: DomainConfig[]): Promise<void> {
|
||||
public async updateDomainConfigs(newDomainConfigs: IDomainConfig[]): Promise<void> {
|
||||
console.log(`Updating domain configurations (${newDomainConfigs.length} configs)`);
|
||||
|
||||
// Update domain configs in DomainConfigManager
|
||||
@ -475,7 +475,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
} else {
|
||||
// Static certificate (e.g., DNS-01 provisioned) supports wildcards
|
||||
const certObj = provision as plugins.tsclass.network.ICert;
|
||||
const certData: CertificateData = {
|
||||
const certData: ICertificateData = {
|
||||
domain: certObj.domainName,
|
||||
certificate: certObj.publicKey,
|
||||
privateKey: certObj.privateKey,
|
||||
|
@ -1,10 +1,10 @@
|
||||
import type { ConnectionRecord, SmartProxyOptions } from './models/interfaces.js';
|
||||
import type { IConnectionRecord, ISmartProxyOptions } from './models/interfaces.js';
|
||||
|
||||
/**
|
||||
* Manages timeouts and inactivity tracking for connections
|
||||
*/
|
||||
export class TimeoutManager {
|
||||
constructor(private settings: SmartProxyOptions) {}
|
||||
constructor(private settings: ISmartProxyOptions) {}
|
||||
|
||||
/**
|
||||
* Ensure timeout values don't exceed Node.js max safe integer
|
||||
@ -28,7 +28,7 @@ export class TimeoutManager {
|
||||
/**
|
||||
* Update connection activity timestamp
|
||||
*/
|
||||
public updateActivity(record: ConnectionRecord): void {
|
||||
public updateActivity(record: IConnectionRecord): void {
|
||||
record.lastActivity = Date.now();
|
||||
|
||||
// Clear any inactivity warning
|
||||
@ -36,11 +36,11 @@ export class TimeoutManager {
|
||||
record.inactivityWarningIssued = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate effective inactivity timeout based on connection type
|
||||
*/
|
||||
public getEffectiveInactivityTimeout(record: ConnectionRecord): number {
|
||||
public getEffectiveInactivityTimeout(record: IConnectionRecord): number {
|
||||
let effectiveTimeout = this.settings.inactivityTimeout || 14400000; // 4 hours default
|
||||
|
||||
// For immortal keep-alive connections, use an extremely long timeout
|
||||
@ -60,7 +60,7 @@ export class TimeoutManager {
|
||||
/**
|
||||
* Calculate effective max lifetime based on connection type
|
||||
*/
|
||||
public getEffectiveMaxLifetime(record: ConnectionRecord): number {
|
||||
public getEffectiveMaxLifetime(record: IConnectionRecord): number {
|
||||
// Use domain-specific timeout from forwarding.advanced if available
|
||||
const baseTimeout = record.domainConfig?.forwarding?.advanced?.timeout ||
|
||||
this.settings.maxConnectionLifetime ||
|
||||
@ -91,8 +91,8 @@ export class TimeoutManager {
|
||||
* @returns The cleanup timer
|
||||
*/
|
||||
public setupConnectionTimeout(
|
||||
record: ConnectionRecord,
|
||||
onTimeout: (record: ConnectionRecord, reason: string) => void
|
||||
record: IConnectionRecord,
|
||||
onTimeout: (record: IConnectionRecord, reason: string) => void
|
||||
): NodeJS.Timeout {
|
||||
// Clear any existing timer
|
||||
if (record.cleanupTimer) {
|
||||
@ -120,7 +120,7 @@ export class TimeoutManager {
|
||||
* Check for inactivity on a connection
|
||||
* @returns Object with check results
|
||||
*/
|
||||
public checkInactivity(record: ConnectionRecord): {
|
||||
public checkInactivity(record: IConnectionRecord): {
|
||||
isInactive: boolean;
|
||||
shouldWarn: boolean;
|
||||
inactivityTime: number;
|
||||
@ -169,7 +169,7 @@ export class TimeoutManager {
|
||||
/**
|
||||
* Apply socket timeout settings
|
||||
*/
|
||||
public applySocketTimeouts(record: ConnectionRecord): void {
|
||||
public applySocketTimeouts(record: IConnectionRecord): void {
|
||||
// Skip for immortal keep-alive connections
|
||||
if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') {
|
||||
// Disable timeouts completely for immortal connections
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import type { SmartProxyOptions } from './models/interfaces.js';
|
||||
import type { ISmartProxyOptions } from './models/interfaces.js';
|
||||
import { SniHandler } from '../../tls/sni/sni-handler.js';
|
||||
|
||||
/**
|
||||
@ -16,7 +16,7 @@ interface IConnectionInfo {
|
||||
* Manages TLS-related operations including SNI extraction and validation
|
||||
*/
|
||||
export class TlsManager {
|
||||
constructor(private settings: SmartProxyOptions) {}
|
||||
constructor(private settings: ISmartProxyOptions) {}
|
||||
|
||||
/**
|
||||
* Check if a data chunk appears to be a TLS handshake
|
||||
|
Reference in New Issue
Block a user