smartproxy/ts/proxies/smart-proxy/network-proxy-bridge.ts

152 lines
4.4 KiB
TypeScript
Raw Normal View History

2025-05-09 21:21:28 +00:00
import * as plugins from '../../plugins.js';
import { NetworkProxy } from '../network-proxy/index.js';
2025-05-10 00:49:39 +00:00
import type { IConnectionRecord, ISmartProxyOptions } from './models/interfaces.js';
import type { IRouteConfig } from './models/route-types.js';
export class NetworkProxyBridge {
private networkProxy: NetworkProxy | null = null;
2025-05-09 21:21:28 +00:00
constructor(private settings: ISmartProxyOptions) {}
/**
2025-05-18 15:38:07 +00:00
* Get the NetworkProxy instance
*/
2025-05-18 15:38:07 +00:00
public getNetworkProxy(): NetworkProxy | null {
return this.networkProxy;
}
/**
* Initialize NetworkProxy instance
*/
public async initialize(): Promise<void> {
if (!this.networkProxy && this.settings.useNetworkProxy && this.settings.useNetworkProxy.length > 0) {
const networkProxyOptions: any = {
port: this.settings.networkProxyPort!,
portProxyIntegration: true,
2025-05-18 15:38:07 +00:00
logLevel: this.settings.enableDetailedLogging ? 'debug' : 'info'
};
this.networkProxy = new NetworkProxy(networkProxyOptions);
console.log(`Initialized NetworkProxy on port ${this.settings.networkProxyPort}`);
2025-05-10 00:49:39 +00:00
// Apply route configurations to NetworkProxy
await this.syncRoutesToNetworkProxy(this.settings.routes || []);
}
}
/**
2025-05-18 15:38:07 +00:00
* Sync routes to NetworkProxy
*/
2025-05-18 15:38:07 +00:00
public async syncRoutesToNetworkProxy(routes: IRouteConfig[]): Promise<void> {
if (!this.networkProxy) return;
2025-05-18 15:38:07 +00:00
// Convert routes to NetworkProxy format
const networkProxyConfigs = routes
.filter(route => {
// Check if this route matches any of the specified network proxy ports
const routePorts = Array.isArray(route.match.ports)
? route.match.ports
: [route.match.ports];
return routePorts.some(port =>
this.settings.useNetworkProxy?.includes(port)
);
})
.map(route => this.routeToNetworkProxyConfig(route));
// Apply configurations to NetworkProxy
await this.networkProxy.updateRouteConfigs(networkProxyConfigs);
}
/**
2025-05-18 15:38:07 +00:00
* Convert route to NetworkProxy configuration
*/
2025-05-18 15:38:07 +00:00
private routeToNetworkProxyConfig(route: IRouteConfig): any {
// Convert route to NetworkProxy domain config format
return {
domain: route.match.domains?.[0] || '*',
target: route.action.target,
tls: route.action.tls,
security: route.action.security
};
}
/**
2025-05-18 15:38:07 +00:00
* Check if connection should use NetworkProxy
*/
2025-05-18 15:38:07 +00:00
public shouldUseNetworkProxy(connection: IConnectionRecord, routeMatch: any): boolean {
// Only use NetworkProxy for TLS termination
return (
routeMatch.route.action.tls?.mode === 'terminate' ||
routeMatch.route.action.tls?.mode === 'terminate-and-reencrypt'
) && this.networkProxy !== null;
}
/**
2025-05-18 15:38:07 +00:00
* Forward connection to NetworkProxy
*/
2025-05-18 15:38:07 +00:00
public async forwardToNetworkProxy(
connectionId: string,
socket: plugins.net.Socket,
record: IConnectionRecord,
2025-05-18 15:38:07 +00:00
initialChunk: Buffer,
networkProxyPort: number,
cleanupCallback: (reason: string) => void
): Promise<void> {
if (!this.networkProxy) {
2025-05-18 15:38:07 +00:00
throw new Error('NetworkProxy not initialized');
}
2025-05-18 15:38:07 +00:00
const proxySocket = new plugins.net.Socket();
await new Promise<void>((resolve, reject) => {
proxySocket.connect(networkProxyPort, 'localhost', () => {
console.log(`[${connectionId}] Connected to NetworkProxy for termination`);
resolve();
});
proxySocket.on('error', reject);
});
2025-05-18 15:38:07 +00:00
// Send initial chunk if present
if (initialChunk) {
proxySocket.write(initialChunk);
}
// Pipe the sockets together
socket.pipe(proxySocket);
proxySocket.pipe(socket);
// Handle cleanup
const cleanup = (reason: string) => {
socket.unpipe(proxySocket);
proxySocket.unpipe(socket);
proxySocket.destroy();
cleanupCallback(reason);
};
socket.on('end', () => cleanup('socket_end'));
socket.on('error', () => cleanup('socket_error'));
proxySocket.on('end', () => cleanup('proxy_end'));
proxySocket.on('error', () => cleanup('proxy_error'));
}
/**
2025-05-18 15:38:07 +00:00
* Start NetworkProxy
*/
2025-05-18 15:38:07 +00:00
public async start(): Promise<void> {
if (this.networkProxy) {
await this.networkProxy.start();
}
}
/**
2025-05-18 15:38:07 +00:00
* Stop NetworkProxy
*/
2025-05-18 15:38:07 +00:00
public async stop(): Promise<void> {
if (this.networkProxy) {
await this.networkProxy.stop();
this.networkProxy = null;
}
}
}