@push.rocks/smartproxy 3.17.1 → 3.18.1

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.17.1',
6
+ version: '3.18.1',
7
7
  description: 'A powerful proxy package that effectively handles high traffic, with features such as SSL/TLS support, port proxying, WebSocket handling, and dynamic routing with authentication options.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx3QkFBd0I7SUFDOUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLDRMQUE0TDtDQUMxTSxDQUFBIn0=
@@ -1,9 +1,9 @@
1
1
  import * as plugins from './plugins.js';
2
2
  /** Domain configuration with per‐domain allowed port ranges */
3
3
  export interface IDomainConfig {
4
- domain: string | string[];
4
+ domains: string[];
5
5
  allowedIPs: string[];
6
- targetIP?: string;
6
+ targetIPs?: string[];
7
7
  portRanges?: Array<{
8
8
  from: number;
9
9
  to: number;
@@ -14,7 +14,7 @@ export interface IPortProxySettings extends plugins.tls.TlsOptions {
14
14
  fromPort: number;
15
15
  toPort: number;
16
16
  targetIP?: string;
17
- domains: IDomainConfig[];
17
+ domainConfigs: IDomainConfig[];
18
18
  sniEnabled?: boolean;
19
19
  defaultAllowedIPs?: string[];
20
20
  preserveSourceIP?: boolean;
@@ -30,9 +30,11 @@ export declare class PortProxy {
30
30
  settings: IPortProxySettings;
31
31
  private connectionRecords;
32
32
  private connectionLogger;
33
+ private domainTargetIndices;
33
34
  private terminationStats;
34
35
  constructor(settingsArg: IPortProxySettings);
35
36
  private incrementTerminationStat;
37
+ private getTargetIP;
36
38
  start(): Promise<void>;
37
39
  stop(): Promise<void>;
38
40
  }
@@ -66,6 +66,8 @@ export class PortProxy {
66
66
  // Unified record tracking each connection pair.
67
67
  this.connectionRecords = new Set();
68
68
  this.connectionLogger = null;
69
+ // Map to track round robin indices for each domain config.
70
+ this.domainTargetIndices = new Map();
69
71
  this.terminationStats = {
70
72
  incoming: {},
71
73
  outgoing: {},
@@ -79,6 +81,15 @@ export class PortProxy {
79
81
  incrementTerminationStat(side, reason) {
80
82
  this.terminationStats[side][reason] = (this.terminationStats[side][reason] || 0) + 1;
81
83
  }
84
+ getTargetIP(domainConfig) {
85
+ if (domainConfig.targetIPs && domainConfig.targetIPs.length > 0) {
86
+ const currentIndex = this.domainTargetIndices.get(domainConfig) || 0;
87
+ const ip = domainConfig.targetIPs[currentIndex % domainConfig.targetIPs.length];
88
+ this.domainTargetIndices.set(domainConfig, currentIndex + 1);
89
+ return ip;
90
+ }
91
+ return this.settings.targetIP;
92
+ }
82
93
  async start() {
83
94
  // Define a unified connection handler for all listening ports.
84
95
  const connectionHandler = (socket) => {
@@ -169,18 +180,11 @@ export class PortProxy {
169
180
  // If a forcedDomain is provided (port-based routing), use it; otherwise, use SNI-based lookup.
170
181
  const domainConfig = forcedDomain
171
182
  ? forcedDomain
172
- : (serverName ? this.settings.domains.find(config => {
173
- if (typeof config.domain === 'string') {
174
- return plugins.minimatch(serverName, config.domain);
175
- }
176
- else {
177
- return config.domain.some(d => plugins.minimatch(serverName, d));
178
- }
179
- }) : undefined);
183
+ : (serverName ? this.settings.domainConfigs.find(config => config.domains.some(d => plugins.minimatch(serverName, d))) : undefined);
180
184
  // If a matching domain config exists, check its allowedIPs.
181
185
  if (domainConfig) {
182
186
  if (!isAllowed(remoteIP, domainConfig.allowedIPs)) {
183
- return rejectIncomingConnection('rejected', `Connection rejected: IP ${remoteIP} not allowed for domain ${Array.isArray(domainConfig.domain) ? domainConfig.domain.join(', ') : domainConfig.domain}`);
187
+ return rejectIncomingConnection('rejected', `Connection rejected: IP ${remoteIP} not allowed for domain ${domainConfig.domains.join(', ')}`);
184
188
  }
185
189
  }
186
190
  else if (this.settings.defaultAllowedIPs) {
@@ -189,7 +193,7 @@ export class PortProxy {
189
193
  return rejectIncomingConnection('rejected', `Connection rejected: IP ${remoteIP} not allowed by default allowed list`);
190
194
  }
191
195
  }
192
- const targetHost = domainConfig?.targetIP || this.settings.targetIP;
196
+ const targetHost = domainConfig ? this.getTargetIP(domainConfig) : this.settings.targetIP;
193
197
  const connectionOptions = {
194
198
  host: targetHost,
195
199
  port: overridePort !== undefined ? overridePort : this.settings.toPort,
@@ -201,7 +205,7 @@ export class PortProxy {
201
205
  connectionRecord.outgoing = targetSocket;
202
206
  connectionRecord.outgoingStartTime = Date.now();
203
207
  console.log(`Connection established: ${remoteIP} -> ${targetHost}:${connectionOptions.port}` +
204
- `${serverName ? ` (SNI: ${serverName})` : forcedDomain ? ` (Port-based for domain: ${Array.isArray(forcedDomain.domain) ? forcedDomain.domain.join(', ') : forcedDomain.domain})` : ''}`);
208
+ `${serverName ? ` (SNI: ${serverName})` : forcedDomain ? ` (Port-based for domain: ${forcedDomain.domains.join(', ')})` : ''}`);
205
209
  if (initialChunk) {
206
210
  socket.unshift(initialChunk);
207
211
  }
@@ -276,23 +280,23 @@ export class PortProxy {
276
280
  }
277
281
  console.log(`Port-based connection from ${remoteIP} on port ${localPort} forwarded to global target IP ${this.settings.targetIP}.`);
278
282
  setupConnection('', undefined, {
279
- domain: 'global',
283
+ domains: ['global'],
280
284
  allowedIPs: this.settings.defaultAllowedIPs || [],
281
- targetIP: this.settings.targetIP,
285
+ targetIPs: [this.settings.targetIP],
282
286
  portRanges: []
283
287
  }, localPort);
284
288
  return;
285
289
  }
286
290
  else {
287
291
  // Attempt to find a matching forced domain config based on the local port.
288
- const forcedDomain = this.settings.domains.find(domain => domain.portRanges && domain.portRanges.length > 0 && isPortInRanges(localPort, domain.portRanges));
292
+ const forcedDomain = this.settings.domainConfigs.find(domain => domain.portRanges && domain.portRanges.length > 0 && isPortInRanges(localPort, domain.portRanges));
289
293
  if (forcedDomain) {
290
294
  if (!isAllowed(remoteIP, forcedDomain.allowedIPs)) {
291
- console.log(`Connection from ${remoteIP} rejected: IP not allowed for domain ${Array.isArray(forcedDomain.domain) ? forcedDomain.domain.join(', ') : forcedDomain.domain} on port ${localPort}.`);
295
+ console.log(`Connection from ${remoteIP} rejected: IP not allowed for domain ${forcedDomain.domains.join(', ')} on port ${localPort}.`);
292
296
  socket.end();
293
297
  return;
294
298
  }
295
- console.log(`Port-based connection from ${remoteIP} on port ${localPort} matched domain ${Array.isArray(forcedDomain.domain) ? forcedDomain.domain.join(', ') : forcedDomain.domain}.`);
299
+ console.log(`Port-based connection from ${remoteIP} on port ${localPort} matched domain ${forcedDomain.domains.join(', ')}.`);
296
300
  setupConnection('', undefined, forcedDomain, localPort);
297
301
  return;
298
302
  }
@@ -310,7 +314,22 @@ export class PortProxy {
310
314
  socket.setTimeout(0);
311
315
  initialDataReceived = true;
312
316
  const serverName = extractSNI(chunk) || '';
317
+ // Lock the connection to the negotiated SNI.
318
+ connectionRecord.lockedDomain = serverName;
313
319
  console.log(`Received connection from ${remoteIP} with SNI: ${serverName}`);
320
+ // Delay adding the renegotiation listener until the next tick,
321
+ // so the initial ClientHello is not reprocessed.
322
+ setImmediate(() => {
323
+ socket.on('data', (renegChunk) => {
324
+ if (renegChunk.length > 0 && renegChunk.readUInt8(0) === 22) {
325
+ const newSNI = extractSNI(renegChunk);
326
+ if (newSNI && newSNI !== connectionRecord.lockedDomain) {
327
+ console.log(`Rehandshake detected with different SNI: ${newSNI} vs locked ${connectionRecord.lockedDomain}. Terminating connection.`);
328
+ cleanupOnce();
329
+ }
330
+ }
331
+ });
332
+ });
314
333
  setupConnection(serverName, chunk);
315
334
  });
316
335
  }
@@ -399,4 +418,4 @@ const isAllowed = (ip, patterns) => {
399
418
  const expandedPatterns = patterns.flatMap(normalizeIP);
400
419
  return normalizedIPVariants.some(ipVariant => expandedPatterns.some(pattern => plugins.minimatch(ipVariant, pattern)));
401
420
  };
402
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wb3J0cHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnBvcnRwcm94eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQXdCeEM7Ozs7R0FJRztBQUNILFNBQVMsVUFBVSxDQUFDLE1BQWM7SUFDaEMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUV4QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLElBQUksVUFBVSxLQUFLLEVBQUU7UUFBRSxPQUFPLFNBQVMsQ0FBQyxDQUFDLGlCQUFpQjtJQUUxRCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsWUFBWTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBRXZELE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDWCxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9DLElBQUksYUFBYSxLQUFLLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQyxDQUFDLGtCQUFrQjtJQUU3RCxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUMsd0NBQXdDO0lBQ3JELE1BQU0sSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsaUNBQWlDO0lBRW5ELE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakQsTUFBTSxJQUFJLENBQUMsR0FBRyxlQUFlLENBQUMsQ0FBQyxrQkFBa0I7SUFFakQsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FB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
421
+ //# 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.17.1",
3
+ "version": "3.18.1",
4
4
  "private": false,
5
5
  "description": "A powerful proxy package that effectively handles high traffic, with features such as SSL/TLS support, port proxying, WebSocket handling, and dynamic routing with authentication options.",
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.17.1',
6
+ version: '3.18.1',
7
7
  description: 'A powerful proxy package that effectively handles high traffic, with features such as SSL/TLS support, port proxying, WebSocket handling, and dynamic routing with authentication options.'
8
8
  }
@@ -2,10 +2,10 @@ import * as plugins from './plugins.js';
2
2
 
3
3
  /** Domain configuration with per‐domain allowed port ranges */
4
4
  export interface IDomainConfig {
5
- domain: string | string[]; // Glob pattern or patterns for domain(s)
6
- allowedIPs: string[]; // Glob patterns for allowed IPs
7
- targetIP?: string; // Optional target IP for this domain
8
- portRanges?: Array<{ from: number; to: number }>; // Optional domain-specific allowed port ranges
5
+ domains: string[]; // Glob patterns for domain(s)
6
+ allowedIPs: string[]; // Glob patterns for allowed IPs
7
+ targetIPs?: string[]; // If multiple targetIPs are given, use round robin.
8
+ portRanges?: Array<{ from: number; to: number }>; // Optional port ranges
9
9
  }
10
10
 
11
11
  /** Port proxy settings including global allowed port ranges */
@@ -13,7 +13,7 @@ export interface IPortProxySettings extends plugins.tls.TlsOptions {
13
13
  fromPort: number;
14
14
  toPort: number;
15
15
  targetIP?: string; // Global target host to proxy to, defaults to 'localhost'
16
- domains: IDomainConfig[];
16
+ domainConfigs: IDomainConfig[];
17
17
  sniEnabled?: boolean;
18
18
  defaultAllowedIPs?: string[];
19
19
  preserveSourceIP?: boolean;
@@ -90,6 +90,7 @@ interface IConnectionRecord {
90
90
  outgoing: plugins.net.Socket | null;
91
91
  incomingStartTime: number;
92
92
  outgoingStartTime?: number;
93
+ lockedDomain?: string; // New field to lock this connection to the initial SNI
93
94
  connectionClosed: boolean;
94
95
  cleanupTimer?: NodeJS.Timeout; // Timer to force cleanup after max lifetime/inactivity
95
96
  }
@@ -101,6 +102,9 @@ export class PortProxy {
101
102
  private connectionRecords: Set<IConnectionRecord> = new Set();
102
103
  private connectionLogger: NodeJS.Timeout | null = null;
103
104
 
105
+ // Map to track round robin indices for each domain config.
106
+ private domainTargetIndices: Map<IDomainConfig, number> = new Map();
107
+
104
108
  private terminationStats: {
105
109
  incoming: Record<string, number>;
106
110
  outgoing: Record<string, number>;
@@ -121,6 +125,16 @@ export class PortProxy {
121
125
  this.terminationStats[side][reason] = (this.terminationStats[side][reason] || 0) + 1;
122
126
  }
123
127
 
128
+ private getTargetIP(domainConfig: IDomainConfig): string {
129
+ if (domainConfig.targetIPs && domainConfig.targetIPs.length > 0) {
130
+ const currentIndex = this.domainTargetIndices.get(domainConfig) || 0;
131
+ const ip = domainConfig.targetIPs[currentIndex % domainConfig.targetIPs.length];
132
+ this.domainTargetIndices.set(domainConfig, currentIndex + 1);
133
+ return ip;
134
+ }
135
+ return this.settings.targetIP!;
136
+ }
137
+
124
138
  public async start() {
125
139
  // Define a unified connection handler for all listening ports.
126
140
  const connectionHandler = (socket: plugins.net.Socket) => {
@@ -213,18 +227,14 @@ export class PortProxy {
213
227
  // If a forcedDomain is provided (port-based routing), use it; otherwise, use SNI-based lookup.
214
228
  const domainConfig = forcedDomain
215
229
  ? forcedDomain
216
- : (serverName ? this.settings.domains.find(config => {
217
- if (typeof config.domain === 'string') {
218
- return plugins.minimatch(serverName, config.domain);
219
- } else {
220
- return config.domain.some(d => plugins.minimatch(serverName, d));
221
- }
222
- }) : undefined);
230
+ : (serverName ? this.settings.domainConfigs.find(config =>
231
+ config.domains.some(d => plugins.minimatch(serverName, d))
232
+ ) : undefined);
223
233
 
224
234
  // If a matching domain config exists, check its allowedIPs.
225
235
  if (domainConfig) {
226
236
  if (!isAllowed(remoteIP, domainConfig.allowedIPs)) {
227
- return rejectIncomingConnection('rejected', `Connection rejected: IP ${remoteIP} not allowed for domain ${Array.isArray(domainConfig.domain) ? domainConfig.domain.join(', ') : domainConfig.domain}`);
237
+ return rejectIncomingConnection('rejected', `Connection rejected: IP ${remoteIP} not allowed for domain ${domainConfig.domains.join(', ')}`);
228
238
  }
229
239
  } else if (this.settings.defaultAllowedIPs) {
230
240
  // Only check default allowed IPs if no domain config matched.
@@ -232,7 +242,7 @@ export class PortProxy {
232
242
  return rejectIncomingConnection('rejected', `Connection rejected: IP ${remoteIP} not allowed by default allowed list`);
233
243
  }
234
244
  }
235
- const targetHost = domainConfig?.targetIP || this.settings.targetIP!;
245
+ const targetHost = domainConfig ? this.getTargetIP(domainConfig) : this.settings.targetIP!;
236
246
  const connectionOptions: plugins.net.NetConnectOpts = {
237
247
  host: targetHost,
238
248
  port: overridePort !== undefined ? overridePort : this.settings.toPort,
@@ -247,7 +257,7 @@ export class PortProxy {
247
257
 
248
258
  console.log(
249
259
  `Connection established: ${remoteIP} -> ${targetHost}:${connectionOptions.port}` +
250
- `${serverName ? ` (SNI: ${serverName})` : forcedDomain ? ` (Port-based for domain: ${Array.isArray(forcedDomain.domain) ? forcedDomain.domain.join(', ') : forcedDomain.domain})` : ''}`
260
+ `${serverName ? ` (SNI: ${serverName})` : forcedDomain ? ` (Port-based for domain: ${forcedDomain.domains.join(', ')})` : ''}`
251
261
  );
252
262
 
253
263
  if (initialChunk) {
@@ -329,24 +339,24 @@ export class PortProxy {
329
339
  }
330
340
  console.log(`Port-based connection from ${remoteIP} on port ${localPort} forwarded to global target IP ${this.settings.targetIP}.`);
331
341
  setupConnection('', undefined, {
332
- domain: 'global',
342
+ domains: ['global'],
333
343
  allowedIPs: this.settings.defaultAllowedIPs || [],
334
- targetIP: this.settings.targetIP,
344
+ targetIPs: [this.settings.targetIP!],
335
345
  portRanges: []
336
346
  }, localPort);
337
347
  return;
338
348
  } else {
339
349
  // Attempt to find a matching forced domain config based on the local port.
340
- const forcedDomain = this.settings.domains.find(
350
+ const forcedDomain = this.settings.domainConfigs.find(
341
351
  domain => domain.portRanges && domain.portRanges.length > 0 && isPortInRanges(localPort, domain.portRanges)
342
352
  );
343
353
  if (forcedDomain) {
344
354
  if (!isAllowed(remoteIP, forcedDomain.allowedIPs)) {
345
- console.log(`Connection from ${remoteIP} rejected: IP not allowed for domain ${Array.isArray(forcedDomain.domain) ? forcedDomain.domain.join(', ') : forcedDomain.domain} on port ${localPort}.`);
355
+ console.log(`Connection from ${remoteIP} rejected: IP not allowed for domain ${forcedDomain.domains.join(', ')} on port ${localPort}.`);
346
356
  socket.end();
347
357
  return;
348
358
  }
349
- console.log(`Port-based connection from ${remoteIP} on port ${localPort} matched domain ${Array.isArray(forcedDomain.domain) ? forcedDomain.domain.join(', ') : forcedDomain.domain}.`);
359
+ console.log(`Port-based connection from ${remoteIP} on port ${localPort} matched domain ${forcedDomain.domains.join(', ')}.`);
350
360
  setupConnection('', undefined, forcedDomain, localPort);
351
361
  return;
352
362
  }
@@ -366,7 +376,22 @@ export class PortProxy {
366
376
  socket.setTimeout(0);
367
377
  initialDataReceived = true;
368
378
  const serverName = extractSNI(chunk) || '';
379
+ // Lock the connection to the negotiated SNI.
380
+ connectionRecord.lockedDomain = serverName;
369
381
  console.log(`Received connection from ${remoteIP} with SNI: ${serverName}`);
382
+ // Delay adding the renegotiation listener until the next tick,
383
+ // so the initial ClientHello is not reprocessed.
384
+ setImmediate(() => {
385
+ socket.on('data', (renegChunk: Buffer) => {
386
+ if (renegChunk.length > 0 && renegChunk.readUInt8(0) === 22) {
387
+ const newSNI = extractSNI(renegChunk);
388
+ if (newSNI && newSNI !== connectionRecord.lockedDomain) {
389
+ console.log(`Rehandshake detected with different SNI: ${newSNI} vs locked ${connectionRecord.lockedDomain}. Terminating connection.`);
390
+ cleanupOnce();
391
+ }
392
+ }
393
+ });
394
+ });
370
395
  setupConnection(serverName, chunk);
371
396
  });
372
397
  } else {