This commit is contained in:
2025-05-10 00:49:39 +00:00
parent 3596d35f45
commit 529857220d
4 changed files with 270 additions and 501 deletions

View File

@ -1,12 +1,10 @@
import * as plugins from '../../plugins.js';
import type {
IConnectionRecord,
IDomainConfig,
ISmartProxyOptions
} from './models/interfaces.js';
import {
isRoutedOptions,
isLegacyOptions
isRoutedOptions
} from './models/interfaces.js';
import type {
IRouteConfig,
@ -14,13 +12,11 @@ import type {
} from './models/route-types.js';
import { ConnectionManager } from './connection-manager.js';
import { SecurityManager } from './security-manager.js';
import { DomainConfigManager } from './domain-config-manager.js';
import { TlsManager } from './tls-manager.js';
import { NetworkProxyBridge } from './network-proxy-bridge.js';
import { TimeoutManager } from './timeout-manager.js';
import { RouteManager } from './route-manager.js';
import type { ForwardingHandler } from '../../forwarding/handlers/base-handler.js';
import type { TForwardingType } from '../../forwarding/config/forwarding-types.js';
/**
* Handles new connection processing and setup logic with support for route-based configuration
@ -32,7 +28,6 @@ export class RouteConnectionHandler {
settings: ISmartProxyOptions,
private connectionManager: ConnectionManager,
private securityManager: SecurityManager,
private domainConfigManager: DomainConfigManager,
private tlsManager: TlsManager,
private networkProxyBridge: NetworkProxyBridge,
private timeoutManager: TimeoutManager,
@ -244,37 +239,20 @@ export class RouteConnectionHandler {
if (!routeMatch) {
console.log(`[${connectionId}] No route found for ${serverName || 'connection'} on port ${localPort}`);
// Fall back to legacy matching if we're using a hybrid configuration
const domainConfig = serverName
? this.domainConfigManager.findDomainConfig(serverName)
: this.domainConfigManager.findDomainConfigForPort(localPort);
if (domainConfig) {
if (this.settings.enableDetailedLogging) {
console.log(`[${connectionId}] Using legacy domain configuration for ${serverName || 'port ' + localPort}`);
}
// Associate this domain config with the connection
record.domainConfig = domainConfig;
// Handle the connection using the legacy setup
return this.handleLegacyConnection(socket, record, serverName, domainConfig, initialChunk);
}
// No matching route or domain config, use default/fallback handling
// No matching route, use default/fallback handling
console.log(`[${connectionId}] Using default route handling for connection`);
// Check default security settings
const defaultSecuritySettings = this.settings.defaults?.security;
if (defaultSecuritySettings) {
if (defaultSecuritySettings.allowedIPs && defaultSecuritySettings.allowedIPs.length > 0) {
if (defaultSecuritySettings.allowedIps && defaultSecuritySettings.allowedIps.length > 0) {
const isAllowed = this.securityManager.isIPAuthorized(
remoteIP,
defaultSecuritySettings.allowedIPs,
defaultSecuritySettings.blockedIPs || []
defaultSecuritySettings.allowedIps,
defaultSecuritySettings.blockedIps || []
);
if (!isAllowed) {
console.log(`[${connectionId}] IP ${remoteIP} not in default allowed list`);
socket.end();
@ -282,34 +260,24 @@ export class RouteConnectionHandler {
return;
}
}
} else if (this.settings.defaultAllowedIPs && this.settings.defaultAllowedIPs.length > 0) {
// Legacy default IP restrictions
const isAllowed = this.securityManager.isIPAuthorized(
remoteIP,
this.settings.defaultAllowedIPs,
this.settings.defaultBlockedIPs || []
);
if (!isAllowed) {
console.log(`[${connectionId}] IP ${remoteIP} not in default allowed list`);
socket.end();
this.connectionManager.cleanupConnection(record, 'ip_blocked');
return;
}
}
// Setup direct connection with default settings
let targetHost: string;
let targetPort: number;
if (this.settings.defaults?.target) {
// Use defaults from configuration
const targetHost = this.settings.defaults.target.host;
const targetPort = this.settings.defaults.target.port;
if (isRoutedOptions(this.settings) && this.settings.defaults?.target) {
// Use defaults from routed configuration
targetHost = this.settings.defaults.target.host;
targetPort = this.settings.defaults.target.port;
} else if (this.settings.targetIP && this.settings.toPort) {
// Fall back to legacy settings
targetHost = this.settings.targetIP;
targetPort = this.settings.toPort;
return this.setupDirectConnection(
socket,
record,
undefined,
serverName,
initialChunk,
undefined,
targetHost,
targetPort
);
} else {
// No default target available, terminate the connection
console.log(`[${connectionId}] No default target configured. Closing connection.`);
@ -317,17 +285,6 @@ export class RouteConnectionHandler {
this.connectionManager.cleanupConnection(record, 'no_default_target');
return;
}
return this.setupDirectConnection(
socket,
record,
undefined,
serverName,
initialChunk,
undefined,
targetHost,
targetPort
);
}
// A matching route was found
@ -575,114 +532,8 @@ export class RouteConnectionHandler {
}
/**
* Handle a connection using legacy domain configuration
* Legacy connection handling has been removed in favor of pure route-based approach
*/
private handleLegacyConnection(
socket: plugins.net.Socket,
record: IConnectionRecord,
serverName: string,
domainConfig: IDomainConfig,
initialChunk?: Buffer
): void {
const connectionId = record.id;
// Get the forwarding type for this domain
const forwardingType = this.domainConfigManager.getForwardingType(domainConfig);
// IP validation
const ipRules = this.domainConfigManager.getEffectiveIPRules(domainConfig);
if (!this.securityManager.isIPAuthorized(record.remoteIP, ipRules.allowedIPs, ipRules.blockedIPs)) {
console.log(
`[${connectionId}] Connection rejected: IP ${record.remoteIP} not allowed for domain ${domainConfig.domains.join(', ')}`
);
socket.end();
this.connectionManager.initiateCleanupOnce(record, 'ip_blocked');
return;
}
// Handle based on forwarding type
switch (forwardingType) {
case 'http-only':
// For HTTP-only configs with TLS traffic
if (record.isTLS) {
console.log(`[${connectionId}] Received TLS connection for HTTP-only domain ${serverName}`);
socket.end();
this.connectionManager.initiateCleanupOnce(record, 'wrong_protocol');
return;
}
break;
case 'https-passthrough':
// For TLS passthrough with TLS traffic
if (record.isTLS) {
try {
const handler = this.domainConfigManager.getForwardingHandler(domainConfig);
if (this.settings.enableDetailedLogging) {
console.log(`[${connectionId}] Using forwarding handler for SNI passthrough to ${serverName}`);
}
// Handle the connection using the handler
return handler.handleConnection(socket);
} catch (err) {
console.log(`[${connectionId}] Error using forwarding handler: ${err}`);
}
}
break;
case 'https-terminate-to-http':
case 'https-terminate-to-https':
// For TLS termination with TLS traffic
if (record.isTLS) {
const networkProxyPort = this.domainConfigManager.getNetworkProxyPort(domainConfig);
if (this.settings.enableDetailedLogging) {
console.log(`[${connectionId}] Using TLS termination (${forwardingType}) for ${serverName} on port ${networkProxyPort}`);
}
// Forward to NetworkProxy with domain-specific port
return this.networkProxyBridge.forwardToNetworkProxy(
connectionId,
socket,
record,
initialChunk!,
networkProxyPort,
(reason) => this.connectionManager.initiateCleanupOnce(record, reason)
);
}
break;
}
// If we're still here, use the forwarding handler if available
try {
const handler = this.domainConfigManager.getForwardingHandler(domainConfig);
if (this.settings.enableDetailedLogging) {
console.log(`[${connectionId}] Using general forwarding handler for domain ${serverName || 'unknown'}`);
}
// Handle the connection using the handler
return handler.handleConnection(socket);
} catch (err) {
console.log(`[${connectionId}] Error using forwarding handler: ${err}`);
}
// Fallback: set up direct connection
const targetIp = this.domainConfigManager.getTargetIP(domainConfig);
const targetPort = this.domainConfigManager.getTargetPort(domainConfig, this.settings.toPort);
return this.setupDirectConnection(
socket,
record,
domainConfig,
serverName,
initialChunk,
undefined,
targetIp,
targetPort
);
}
/**
* Sets up a direct connection to the target
@ -690,7 +541,7 @@ export class RouteConnectionHandler {
private setupDirectConnection(
socket: plugins.net.Socket,
record: IConnectionRecord,
domainConfig?: IDomainConfig,
_unused?: any, // kept for backward compatibility
serverName?: string,
initialChunk?: Buffer,
overridePort?: number,
@ -698,22 +549,15 @@ export class RouteConnectionHandler {
targetPort?: number
): void {
const connectionId = record.id;
// Determine target host and port if not provided
const finalTargetHost = targetHost || (domainConfig
? this.domainConfigManager.getTargetIP(domainConfig)
: this.settings.defaults?.target?.host
? this.settings.defaults.target.host
: this.settings.targetIP!);
// Determine target port - first try explicit port, then forwarding config, then fallback
const finalTargetPort = targetPort || (overridePort !== undefined
? overridePort
: domainConfig
? this.domainConfigManager.getTargetPort(domainConfig, this.settings.toPort)
: this.settings.defaults?.target?.port
? this.settings.defaults.target.port
: this.settings.toPort);
// Determine target host and port if not provided
const finalTargetHost = targetHost ||
(this.settings.defaults?.target?.host || 'localhost');
// Determine target port
const finalTargetPort = targetPort ||
(overridePort !== undefined ? overridePort :
(this.settings.defaults?.target?.port || 443));
// Setup connection options
const connectionOptions: plugins.net.NetConnectOpts = {