@push.rocks/smartproxy 3.16.2 → 3.16.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '3.16.2',
6
+ version: '3.16.3',
7
7
  description: 'A robust and versatile proxy package designed to handle high workloads, offering features like SSL redirection, port proxying, WebSocket support, and customizable routing and authentication.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLGdNQUFnTTtDQUM5TSxDQUFBIn0=
@@ -26,7 +26,7 @@ export interface IPortProxySettings extends plugins.tls.TlsOptions {
26
26
  forwardAllGlobalRanges?: boolean;
27
27
  }
28
28
  export declare class PortProxy {
29
- netServer: plugins.net.Server;
29
+ private netServers;
30
30
  settings: IPortProxySettings;
31
31
  private connectionRecords;
32
32
  private connectionLogger;
@@ -62,6 +62,7 @@ function extractSNI(buffer) {
62
62
  }
63
63
  export class PortProxy {
64
64
  constructor(settingsArg) {
65
+ this.netServers = [];
65
66
  // Unified record tracking each connection pair.
66
67
  this.connectionRecords = new Set();
67
68
  this.connectionLogger = null;
@@ -79,37 +80,8 @@ export class PortProxy {
79
80
  this.terminationStats[side][reason] = (this.terminationStats[side][reason] || 0) + 1;
80
81
  }
81
82
  async start() {
82
- // Helper to forcefully destroy sockets.
83
- const cleanUpSockets = (socketA, socketB) => {
84
- if (!socketA.destroyed)
85
- socketA.destroy();
86
- if (socketB && !socketB.destroyed)
87
- socketB.destroy();
88
- };
89
- // Normalize an IP to include both IPv4 and IPv6 representations.
90
- const normalizeIP = (ip) => {
91
- if (ip.startsWith('::ffff:')) {
92
- const ipv4 = ip.slice(7);
93
- return [ip, ipv4];
94
- }
95
- if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
96
- return [ip, `::ffff:${ip}`];
97
- }
98
- return [ip];
99
- };
100
- // Check if a given IP matches any of the glob patterns.
101
- const isAllowed = (ip, patterns) => {
102
- const normalizedIPVariants = normalizeIP(ip);
103
- const expandedPatterns = patterns.flatMap(normalizeIP);
104
- return normalizedIPVariants.some(ipVariant => expandedPatterns.some(pattern => plugins.minimatch(ipVariant, pattern)));
105
- };
106
- // Check if a port falls within any of the given port ranges.
107
- const isPortInRanges = (port, ranges) => {
108
- return ranges.some(range => port >= range.from && port <= range.to);
109
- };
110
- // Find a matching domain config based on SNI (fallback when port ranges aren’t used)
111
- const findMatchingDomain = (serverName) => this.settings.domains.find(config => plugins.minimatch(serverName, config.domain));
112
- this.netServer = plugins.net.createServer((socket) => {
83
+ // Define a unified connection handler for all listening ports.
84
+ const connectionHandler = (socket) => {
113
85
  const remoteIP = socket.remoteAddress || '';
114
86
  const localPort = socket.localPort; // The port on which this connection was accepted.
115
87
  const connectionRecord = {
@@ -130,7 +102,10 @@ export class PortProxy {
130
102
  if (connectionRecord.cleanupTimer) {
131
103
  clearTimeout(connectionRecord.cleanupTimer);
132
104
  }
133
- cleanUpSockets(connectionRecord.incoming, connectionRecord.outgoing || undefined);
105
+ if (!socket.destroyed)
106
+ socket.destroy();
107
+ if (connectionRecord.outgoing && !connectionRecord.outgoing.destroyed)
108
+ connectionRecord.outgoing.destroy();
134
109
  this.connectionRecords.delete(connectionRecord);
135
110
  console.log(`Connection from ${remoteIP} terminated. Active connections: ${this.connectionRecords.size}`);
136
111
  }
@@ -191,7 +166,7 @@ export class PortProxy {
191
166
  */
192
167
  const setupConnection = (serverName, initialChunk, forcedDomain) => {
193
168
  // If a forcedDomain is provided (port-based routing), use it; otherwise, use SNI-based lookup.
194
- const domainConfig = forcedDomain ? forcedDomain : (serverName ? findMatchingDomain(serverName) : undefined);
169
+ const domainConfig = forcedDomain ? forcedDomain : (serverName ? this.settings.domains.find(config => plugins.minimatch(serverName, config.domain)) : undefined);
195
170
  const defaultAllowed = this.settings.defaultAllowedIPs && isAllowed(remoteIP, this.settings.defaultAllowedIPs);
196
171
  if (!defaultAllowed && serverName && !forcedDomain) {
197
172
  if (!domainConfig) {
@@ -281,11 +256,10 @@ export class PortProxy {
281
256
  }
282
257
  };
283
258
  // --- PORT RANGE-BASED HANDLING ---
284
- // Check if the local port falls within any of the global port ranges.
285
- const isLocalPortInGlobalRange = this.settings.globalPortRanges && isPortInRanges(localPort, this.settings.globalPortRanges);
286
- if (isLocalPortInGlobalRange) {
259
+ // If the local port is one of the globally listened ports, we may have port-based rules.
260
+ if (this.settings.globalPortRanges && this.settings.globalPortRanges.length > 0) {
261
+ // If forwardAllGlobalRanges is enabled, always forward using the global targetIP.
287
262
  if (this.settings.forwardAllGlobalRanges) {
288
- // Forward connection to the global targetIP regardless of domain config.
289
263
  if (this.settings.defaultAllowedIPs && !isAllowed(remoteIP, this.settings.defaultAllowedIPs)) {
290
264
  console.log(`Connection from ${remoteIP} rejected: IP ${remoteIP} not allowed in global default allowed list.`);
291
265
  socket.end();
@@ -314,7 +288,7 @@ export class PortProxy {
314
288
  setupConnection('', undefined, forcedDomain);
315
289
  return;
316
290
  }
317
- // If no forced domain config is found for this port, fall through to SNI/default handling.
291
+ // Fall through to SNI/default handling if no forced domain config is found.
318
292
  }
319
293
  }
320
294
  // --- FALLBACK: SNI-BASED HANDLING (or default when SNI is disabled) ---
@@ -339,14 +313,35 @@ export class PortProxy {
339
313
  }
340
314
  setupConnection('');
341
315
  }
342
- })
343
- .on('error', (err) => {
344
- console.log(`Server Error: ${err.message}`);
345
- })
346
- .listen(this.settings.fromPort, () => {
347
- console.log(`PortProxy -> OK: Now listening on port ${this.settings.fromPort}` +
348
- `${this.settings.sniEnabled ? ' (SNI passthrough enabled)' : ''}`);
349
- });
316
+ };
317
+ // --- SETUP LISTENERS ---
318
+ // Determine which ports to listen on.
319
+ const listeningPorts = new Set();
320
+ if (this.settings.globalPortRanges && this.settings.globalPortRanges.length > 0) {
321
+ // Listen on every port defined by the global ranges.
322
+ for (const range of this.settings.globalPortRanges) {
323
+ for (let port = range.from; port <= range.to; port++) {
324
+ listeningPorts.add(port);
325
+ }
326
+ }
327
+ // Also ensure the default fromPort is listened to if it isn’t already in the ranges.
328
+ listeningPorts.add(this.settings.fromPort);
329
+ }
330
+ else {
331
+ listeningPorts.add(this.settings.fromPort);
332
+ }
333
+ // Create a server for each port.
334
+ for (const port of listeningPorts) {
335
+ const server = plugins.net
336
+ .createServer(connectionHandler)
337
+ .on('error', (err) => {
338
+ console.log(`Server Error on port ${port}: ${err.message}`);
339
+ });
340
+ server.listen(port, () => {
341
+ console.log(`PortProxy -> OK: Now listening on port ${port}${this.settings.sniEnabled ? ' (SNI passthrough enabled)' : ''}`);
342
+ });
343
+ this.netServers.push(server);
344
+ }
350
345
  // Log active connection count and longest running durations every 10 seconds.
351
346
  this.connectionLogger = setInterval(() => {
352
347
  const now = Date.now();
@@ -365,15 +360,35 @@ export class PortProxy {
365
360
  }, 10000);
366
361
  }
367
362
  async stop() {
368
- const done = plugins.smartpromise.defer();
369
- this.netServer.close(() => {
370
- done.resolve();
371
- });
363
+ // Close all servers.
364
+ const closePromises = this.netServers.map(server => new Promise((resolve) => {
365
+ server.close(() => resolve());
366
+ }));
372
367
  if (this.connectionLogger) {
373
368
  clearInterval(this.connectionLogger);
374
369
  this.connectionLogger = null;
375
370
  }
376
- await done.promise;
371
+ await Promise.all(closePromises);
377
372
  }
378
373
  }
379
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wb3J0cHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnBvcnRwcm94eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQXdCeEM7Ozs7R0FJRztBQUNILFNBQVMsVUFBVSxDQUFDLE1BQWM7SUFDaEMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUV4QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLElBQUksVUFBVSxLQUFLLEVBQUU7UUFBRSxPQUFPLFNBQVMsQ0FBQyxDQUFDLGlCQUFpQjtJQUUxRCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsWUFBWTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBRXZELE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDWCxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9DLElBQUksYUFBYSxLQUFLLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQyxDQUFDLGtCQUFrQjtJQUU3RCxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUMsd0NBQXdDO0lBQ3JELE1BQU0sSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsaUNBQWlDO0lBRW5ELE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakQsTUFBTSxJQUFJLENBQUMsR0FBRyxlQUFlLENBQUMsQ0FBQyxrQkFBa0I7SUFFakQsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FB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
374
+ // Helper: Check if a port falls within any of the given port ranges.
375
+ const isPortInRanges = (port, ranges) => {
376
+ return ranges.some(range => port >= range.from && port <= range.to);
377
+ };
378
+ // Helper: Check if a given IP matches any of the glob patterns.
379
+ const isAllowed = (ip, patterns) => {
380
+ const normalizeIP = (ip) => {
381
+ if (ip.startsWith('::ffff:')) {
382
+ const ipv4 = ip.slice(7);
383
+ return [ip, ipv4];
384
+ }
385
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
386
+ return [ip, `::ffff:${ip}`];
387
+ }
388
+ return [ip];
389
+ };
390
+ const normalizedIPVariants = normalizeIP(ip);
391
+ const expandedPatterns = patterns.flatMap(normalizeIP);
392
+ return normalizedIPVariants.some(ipVariant => expandedPatterns.some(pattern => plugins.minimatch(ipVariant, pattern)));
393
+ };
394
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wb3J0cHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnBvcnRwcm94eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQXdCeEM7Ozs7R0FJRztBQUNILFNBQVMsVUFBVSxDQUFDLE1BQWM7SUFDaEMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUV4QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLElBQUksVUFBVSxLQUFLLEVBQUU7UUFBRSxPQUFPLFNBQVMsQ0FBQyxDQUFDLGlCQUFpQjtJQUUxRCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsWUFBWTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBRXZELE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDWCxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9DLElBQUksYUFBYSxLQUFLLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQyxDQUFDLGtCQUFrQjtJQUU3RCxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUMsd0NBQXdDO0lBQ3JELE1BQU0sSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsaUNBQWlDO0lBRW5ELE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakQsTUFBTSxJQUFJLENBQUMsR0FBRyxlQUFlLENBQUMsQ0FBQyxrQkFBa0I7SUFFakQsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FB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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartproxy",
3
- "version": "3.16.2",
3
+ "version": "3.16.3",
4
4
  "private": false,
5
5
  "description": "A robust and versatile proxy package designed to handle high workloads, offering features like SSL redirection, port proxying, WebSocket support, and customizable routing and authentication.",
6
6
  "main": "dist_ts/index.js",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartproxy',
6
- version: '3.16.2',
6
+ version: '3.16.3',
7
7
  description: 'A robust and versatile proxy package designed to handle high workloads, offering features like SSL redirection, port proxying, WebSocket support, and customizable routing and authentication.'
8
8
  }
@@ -95,7 +95,7 @@ interface IConnectionRecord {
95
95
  }
96
96
 
97
97
  export class PortProxy {
98
- netServer: plugins.net.Server;
98
+ private netServers: plugins.net.Server[] = [];
99
99
  settings: IPortProxySettings;
100
100
  // Unified record tracking each connection pair.
101
101
  private connectionRecords: Set<IConnectionRecord> = new Set();
@@ -122,43 +122,8 @@ export class PortProxy {
122
122
  }
123
123
 
124
124
  public async start() {
125
- // Helper to forcefully destroy sockets.
126
- const cleanUpSockets = (socketA: plugins.net.Socket, socketB?: plugins.net.Socket) => {
127
- if (!socketA.destroyed) socketA.destroy();
128
- if (socketB && !socketB.destroyed) socketB.destroy();
129
- };
130
-
131
- // Normalize an IP to include both IPv4 and IPv6 representations.
132
- const normalizeIP = (ip: string): string[] => {
133
- if (ip.startsWith('::ffff:')) {
134
- const ipv4 = ip.slice(7);
135
- return [ip, ipv4];
136
- }
137
- if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
138
- return [ip, `::ffff:${ip}`];
139
- }
140
- return [ip];
141
- };
142
-
143
- // Check if a given IP matches any of the glob patterns.
144
- const isAllowed = (ip: string, patterns: string[]): boolean => {
145
- const normalizedIPVariants = normalizeIP(ip);
146
- const expandedPatterns = patterns.flatMap(normalizeIP);
147
- return normalizedIPVariants.some(ipVariant =>
148
- expandedPatterns.some(pattern => plugins.minimatch(ipVariant, pattern))
149
- );
150
- };
151
-
152
- // Check if a port falls within any of the given port ranges.
153
- const isPortInRanges = (port: number, ranges: Array<{ from: number; to: number }>): boolean => {
154
- return ranges.some(range => port >= range.from && port <= range.to);
155
- };
156
-
157
- // Find a matching domain config based on SNI (fallback when port ranges aren’t used)
158
- const findMatchingDomain = (serverName: string): IDomainConfig | undefined =>
159
- this.settings.domains.find(config => plugins.minimatch(serverName, config.domain));
160
-
161
- this.netServer = plugins.net.createServer((socket: plugins.net.Socket) => {
125
+ // Define a unified connection handler for all listening ports.
126
+ const connectionHandler = (socket: plugins.net.Socket) => {
162
127
  const remoteIP = socket.remoteAddress || '';
163
128
  const localPort = socket.localPort; // The port on which this connection was accepted.
164
129
  const connectionRecord: IConnectionRecord = {
@@ -181,7 +146,8 @@ export class PortProxy {
181
146
  if (connectionRecord.cleanupTimer) {
182
147
  clearTimeout(connectionRecord.cleanupTimer);
183
148
  }
184
- cleanUpSockets(connectionRecord.incoming, connectionRecord.outgoing || undefined);
149
+ if (!socket.destroyed) socket.destroy();
150
+ if (connectionRecord.outgoing && !connectionRecord.outgoing.destroyed) connectionRecord.outgoing.destroy();
185
151
  this.connectionRecords.delete(connectionRecord);
186
152
  console.log(`Connection from ${remoteIP} terminated. Active connections: ${this.connectionRecords.size}`);
187
153
  }
@@ -244,7 +210,7 @@ export class PortProxy {
244
210
  */
245
211
  const setupConnection = (serverName: string, initialChunk?: Buffer, forcedDomain?: IDomainConfig) => {
246
212
  // If a forcedDomain is provided (port-based routing), use it; otherwise, use SNI-based lookup.
247
- const domainConfig = forcedDomain ? forcedDomain : (serverName ? findMatchingDomain(serverName) : undefined);
213
+ const domainConfig = forcedDomain ? forcedDomain : (serverName ? this.settings.domains.find(config => plugins.minimatch(serverName, config.domain)) : undefined);
248
214
  const defaultAllowed = this.settings.defaultAllowedIPs && isAllowed(remoteIP, this.settings.defaultAllowedIPs);
249
215
 
250
216
  if (!defaultAllowed && serverName && !forcedDomain) {
@@ -344,13 +310,10 @@ export class PortProxy {
344
310
  };
345
311
 
346
312
  // --- PORT RANGE-BASED HANDLING ---
347
- // Check if the local port falls within any of the global port ranges.
348
- const isLocalPortInGlobalRange =
349
- this.settings.globalPortRanges && isPortInRanges(localPort, this.settings.globalPortRanges);
350
-
351
- if (isLocalPortInGlobalRange) {
313
+ // If the local port is one of the globally listened ports, we may have port-based rules.
314
+ if (this.settings.globalPortRanges && this.settings.globalPortRanges.length > 0) {
315
+ // If forwardAllGlobalRanges is enabled, always forward using the global targetIP.
352
316
  if (this.settings.forwardAllGlobalRanges) {
353
- // Forward connection to the global targetIP regardless of domain config.
354
317
  if (this.settings.defaultAllowedIPs && !isAllowed(remoteIP, this.settings.defaultAllowedIPs)) {
355
318
  console.log(`Connection from ${remoteIP} rejected: IP ${remoteIP} not allowed in global default allowed list.`);
356
319
  socket.end();
@@ -380,7 +343,7 @@ export class PortProxy {
380
343
  setupConnection('', undefined, forcedDomain);
381
344
  return;
382
345
  }
383
- // If no forced domain config is found for this port, fall through to SNI/default handling.
346
+ // Fall through to SNI/default handling if no forced domain config is found.
384
347
  }
385
348
  }
386
349
 
@@ -406,16 +369,36 @@ export class PortProxy {
406
369
  }
407
370
  setupConnection('');
408
371
  }
409
- })
410
- .on('error', (err: Error) => {
411
- console.log(`Server Error: ${err.message}`);
412
- })
413
- .listen(this.settings.fromPort, () => {
414
- console.log(
415
- `PortProxy -> OK: Now listening on port ${this.settings.fromPort}` +
416
- `${this.settings.sniEnabled ? ' (SNI passthrough enabled)' : ''}`
417
- );
372
+ };
373
+
374
+ // --- SETUP LISTENERS ---
375
+ // Determine which ports to listen on.
376
+ const listeningPorts = new Set<number>();
377
+ if (this.settings.globalPortRanges && this.settings.globalPortRanges.length > 0) {
378
+ // Listen on every port defined by the global ranges.
379
+ for (const range of this.settings.globalPortRanges) {
380
+ for (let port = range.from; port <= range.to; port++) {
381
+ listeningPorts.add(port);
382
+ }
383
+ }
384
+ // Also ensure the default fromPort is listened to if it isn’t already in the ranges.
385
+ listeningPorts.add(this.settings.fromPort);
386
+ } else {
387
+ listeningPorts.add(this.settings.fromPort);
388
+ }
389
+
390
+ // Create a server for each port.
391
+ for (const port of listeningPorts) {
392
+ const server = plugins.net
393
+ .createServer(connectionHandler)
394
+ .on('error', (err: Error) => {
395
+ console.log(`Server Error on port ${port}: ${err.message}`);
396
+ });
397
+ server.listen(port, () => {
398
+ console.log(`PortProxy -> OK: Now listening on port ${port}${this.settings.sniEnabled ? ' (SNI passthrough enabled)' : ''}`);
418
399
  });
400
+ this.netServers.push(server);
401
+ }
419
402
 
420
403
  // Log active connection count and longest running durations every 10 seconds.
421
404
  this.connectionLogger = setInterval(() => {
@@ -438,14 +421,41 @@ export class PortProxy {
438
421
  }
439
422
 
440
423
  public async stop() {
441
- const done = plugins.smartpromise.defer();
442
- this.netServer.close(() => {
443
- done.resolve();
444
- });
424
+ // Close all servers.
425
+ const closePromises: Promise<void>[] = this.netServers.map(
426
+ server =>
427
+ new Promise<void>((resolve) => {
428
+ server.close(() => resolve());
429
+ })
430
+ );
445
431
  if (this.connectionLogger) {
446
432
  clearInterval(this.connectionLogger);
447
433
  this.connectionLogger = null;
448
434
  }
449
- await done.promise;
435
+ await Promise.all(closePromises);
450
436
  }
451
- }
437
+ }
438
+
439
+ // Helper: Check if a port falls within any of the given port ranges.
440
+ const isPortInRanges = (port: number, ranges: Array<{ from: number; to: number }>): boolean => {
441
+ return ranges.some(range => port >= range.from && port <= range.to);
442
+ };
443
+
444
+ // Helper: Check if a given IP matches any of the glob patterns.
445
+ const isAllowed = (ip: string, patterns: string[]): boolean => {
446
+ const normalizeIP = (ip: string): string[] => {
447
+ if (ip.startsWith('::ffff:')) {
448
+ const ipv4 = ip.slice(7);
449
+ return [ip, ipv4];
450
+ }
451
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
452
+ return [ip, `::ffff:${ip}`];
453
+ }
454
+ return [ip];
455
+ };
456
+ const normalizedIPVariants = normalizeIP(ip);
457
+ const expandedPatterns = patterns.flatMap(normalizeIP);
458
+ return normalizedIPVariants.some(ipVariant =>
459
+ expandedPatterns.some(pattern => plugins.minimatch(ipVariant, pattern))
460
+ );
461
+ };