feat(PortProxy): Enhance PortProxy to support domain-specific target IPs

This commit is contained in:
Philipp Kunz 2025-02-21 19:34:11 +00:00
parent 9be9a426ad
commit 8e5bb12edb
4 changed files with 63 additions and 3 deletions

View File

@ -1,5 +1,12 @@
# Changelog # Changelog
## 2025-02-21 - 3.5.0 - feat(PortProxy)
Enhance PortProxy to support domain-specific target IPs
- Introduced support for domain-specific target IP configurations in PortProxy.
- Updated connection handling to prioritize domain-specific target IPs if provided.
- Added tests to verify forwarding based on domain-specific target IPs.
## 2025-02-21 - 3.4.4 - fix(PortProxy) ## 2025-02-21 - 3.4.4 - fix(PortProxy)
Fixed handling of SNI domain connections and IP allowance checks Fixed handling of SNI domain connections and IP allowance checks

View File

@ -95,6 +95,54 @@ tap.test('should forward TCP connections to custom host', async () => {
await customHostProxy.stop(); await customHostProxy.stop();
}); });
tap.test('should forward connections based on domain-specific target IP', async () => {
// Create a second test server on a different port
const TEST_SERVER_PORT_2 = TEST_SERVER_PORT + 100;
const testServer2 = await createTestServer(TEST_SERVER_PORT_2);
// Create a proxy with domain-specific target IPs
const domainProxy = new PortProxy({
fromPort: PROXY_PORT + 2,
toPort: TEST_SERVER_PORT, // default port
toHost: 'localhost', // default host
domains: [{
domain: 'domain1.test',
allowedIPs: ['127.0.0.1'],
targetIP: '127.0.0.1'
}, {
domain: 'domain2.test',
allowedIPs: ['127.0.0.1'],
targetIP: 'localhost'
}],
sniEnabled: false, // We'll test without SNI first since this is a TCP proxy test
defaultAllowedIPs: ['127.0.0.1']
});
await domainProxy.start();
// Test default connection (should use default host)
const response1 = await createTestClient(PROXY_PORT + 2, TEST_DATA);
expect(response1).toEqual(`Echo: ${TEST_DATA}`);
// Create another proxy with different default host
const domainProxy2 = new PortProxy({
fromPort: PROXY_PORT + 3,
toPort: TEST_SERVER_PORT,
toHost: '127.0.0.1',
domains: [],
sniEnabled: false,
defaultAllowedIPs: ['127.0.0.1']
});
await domainProxy2.start();
const response2 = await createTestClient(PROXY_PORT + 3, TEST_DATA);
expect(response2).toEqual(`Echo: ${TEST_DATA}`);
await domainProxy.stop();
await domainProxy2.stop();
await new Promise<void>((resolve) => testServer2.close(() => resolve()));
});
tap.test('should handle multiple concurrent connections', async () => { tap.test('should handle multiple concurrent connections', async () => {
const concurrentRequests = 5; const concurrentRequests = 5;
const requests = Array(concurrentRequests).fill(null).map((_, i) => const requests = Array(concurrentRequests).fill(null).map((_, i) =>

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartproxy', name: '@push.rocks/smartproxy',
version: '3.4.4', version: '3.5.0',
description: 'a proxy for handling high workloads of proxying' description: 'a proxy for handling high workloads of proxying'
} }

View File

@ -4,6 +4,7 @@ import * as plugins from './smartproxy.plugins.js';
export interface DomainConfig { export interface DomainConfig {
domain: string; // glob pattern for domain domain: string; // glob pattern for domain
allowedIPs: string[]; // glob patterns for IPs allowed to access this domain allowedIPs: string[]; // glob patterns for IPs allowed to access this domain
targetIP?: string; // Optional target IP for this domain
} }
export interface ProxySettings extends plugins.tls.TlsOptions { export interface ProxySettings extends plugins.tls.TlsOptions {
@ -118,11 +119,15 @@ export class PortProxy {
return; return;
} }
// Determine target host - use domain-specific targetIP if available
const domainConfig = serverName ? findMatchingDomain(serverName) : undefined;
const targetHost = domainConfig?.targetIP || this.settings.toHost!;
const to = plugins.net.createConnection({ const to = plugins.net.createConnection({
host: this.settings.toHost!, host: targetHost,
port: this.settings.toPort, port: this.settings.toPort,
}); });
console.log(`Connection established: ${remoteIP} -> ${this.settings.toHost}:${this.settings.toPort}${serverName ? ` (SNI: ${serverName})` : ''}`); console.log(`Connection established: ${remoteIP} -> ${targetHost}:${this.settings.toPort}${serverName ? ` (SNI: ${serverName})` : ''}`);
from.setTimeout(120000); from.setTimeout(120000);
from.pipe(to); from.pipe(to);
to.pipe(from); to.pipe(from);