@push.rocks/smartproxy 19.5.19 → 19.5.20

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.
Files changed (101) hide show
  1. package/dist_ts/core/models/index.d.ts +2 -0
  2. package/dist_ts/core/models/index.js +3 -1
  3. package/dist_ts/core/models/socket-types.d.ts +14 -0
  4. package/dist_ts/core/models/socket-types.js +15 -0
  5. package/dist_ts/core/models/wrapped-socket.d.ts +34 -0
  6. package/dist_ts/core/models/wrapped-socket.js +82 -0
  7. package/dist_ts/core/routing/index.d.ts +11 -0
  8. package/dist_ts/core/routing/index.js +17 -0
  9. package/dist_ts/core/routing/matchers/domain.d.ts +34 -0
  10. package/dist_ts/core/routing/matchers/domain.js +91 -0
  11. package/dist_ts/core/routing/matchers/header.d.ts +32 -0
  12. package/dist_ts/core/routing/matchers/header.js +94 -0
  13. package/dist_ts/core/routing/matchers/index.d.ts +18 -0
  14. package/dist_ts/core/routing/matchers/index.js +20 -0
  15. package/dist_ts/core/routing/matchers/ip.d.ts +53 -0
  16. package/dist_ts/core/routing/matchers/ip.js +169 -0
  17. package/dist_ts/core/routing/matchers/path.d.ts +44 -0
  18. package/dist_ts/core/routing/matchers/path.js +148 -0
  19. package/dist_ts/core/routing/route-manager.d.ts +88 -0
  20. package/dist_ts/core/routing/route-manager.js +342 -0
  21. package/dist_ts/core/routing/route-utils.d.ts +28 -0
  22. package/dist_ts/core/routing/route-utils.js +67 -0
  23. package/dist_ts/core/routing/specificity.d.ts +30 -0
  24. package/dist_ts/core/routing/specificity.js +115 -0
  25. package/dist_ts/core/routing/types.d.ts +41 -0
  26. package/dist_ts/core/routing/types.js +5 -0
  27. package/dist_ts/core/utils/index.d.ts +0 -2
  28. package/dist_ts/core/utils/index.js +1 -3
  29. package/dist_ts/core/utils/route-manager.d.ts +0 -30
  30. package/dist_ts/core/utils/route-manager.js +6 -47
  31. package/dist_ts/core/utils/route-utils.d.ts +2 -68
  32. package/dist_ts/core/utils/route-utils.js +21 -218
  33. package/dist_ts/core/utils/security-utils.js +4 -4
  34. package/dist_ts/index.d.ts +2 -5
  35. package/dist_ts/index.js +5 -11
  36. package/dist_ts/proxies/http-proxy/http-proxy.d.ts +0 -1
  37. package/dist_ts/proxies/http-proxy/http-proxy.js +15 -60
  38. package/dist_ts/proxies/http-proxy/models/types.d.ts +0 -90
  39. package/dist_ts/proxies/http-proxy/models/types.js +1 -242
  40. package/dist_ts/proxies/http-proxy/request-handler.d.ts +3 -5
  41. package/dist_ts/proxies/http-proxy/request-handler.js +20 -171
  42. package/dist_ts/proxies/http-proxy/websocket-handler.d.ts +2 -5
  43. package/dist_ts/proxies/http-proxy/websocket-handler.js +15 -23
  44. package/dist_ts/proxies/index.d.ts +2 -2
  45. package/dist_ts/proxies/index.js +4 -3
  46. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +3 -1
  47. package/dist_ts/proxies/smart-proxy/connection-manager.js +15 -7
  48. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.d.ts +2 -1
  49. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +5 -2
  50. package/dist_ts/proxies/smart-proxy/index.d.ts +1 -1
  51. package/dist_ts/proxies/smart-proxy/index.js +2 -2
  52. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +6 -2
  53. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +1 -1
  54. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +48 -25
  55. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +1 -1
  56. package/dist_ts/proxies/smart-proxy/smart-proxy.js +15 -4
  57. package/dist_ts/proxies/smart-proxy/utils/route-utils.js +10 -43
  58. package/dist_ts/routing/router/http-router.d.ts +89 -0
  59. package/dist_ts/routing/router/http-router.js +205 -0
  60. package/dist_ts/routing/router/index.d.ts +2 -5
  61. package/dist_ts/routing/router/index.js +3 -4
  62. package/package.json +1 -1
  63. package/readme.delete.md +187 -0
  64. package/readme.hints.md +189 -1
  65. package/readme.plan.md +621 -0
  66. package/readme.routing.md +341 -0
  67. package/ts/core/models/index.ts +2 -0
  68. package/ts/core/models/socket-types.ts +21 -0
  69. package/ts/core/models/wrapped-socket.ts +99 -0
  70. package/ts/core/routing/index.ts +21 -0
  71. package/ts/core/routing/matchers/domain.ts +119 -0
  72. package/ts/core/routing/matchers/header.ts +120 -0
  73. package/ts/core/routing/matchers/index.ts +22 -0
  74. package/ts/core/routing/matchers/ip.ts +207 -0
  75. package/ts/core/routing/matchers/path.ts +184 -0
  76. package/ts/core/{utils → routing}/route-manager.ts +7 -57
  77. package/ts/core/routing/route-utils.ts +88 -0
  78. package/ts/core/routing/specificity.ts +141 -0
  79. package/ts/core/routing/types.ts +49 -0
  80. package/ts/core/utils/index.ts +0 -2
  81. package/ts/core/utils/security-utils.ts +3 -7
  82. package/ts/index.ts +4 -14
  83. package/ts/proxies/http-proxy/http-proxy.ts +13 -68
  84. package/ts/proxies/http-proxy/models/types.ts +0 -324
  85. package/ts/proxies/http-proxy/request-handler.ts +15 -186
  86. package/ts/proxies/http-proxy/websocket-handler.ts +15 -26
  87. package/ts/proxies/index.ts +3 -2
  88. package/ts/proxies/smart-proxy/connection-manager.ts +15 -7
  89. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +6 -2
  90. package/ts/proxies/smart-proxy/index.ts +1 -1
  91. package/ts/proxies/smart-proxy/models/interfaces.ts +8 -2
  92. package/ts/proxies/smart-proxy/route-connection-handler.ts +58 -30
  93. package/ts/proxies/smart-proxy/smart-proxy.ts +15 -3
  94. package/ts/proxies/smart-proxy/utils/route-utils.ts +11 -49
  95. package/ts/routing/router/http-router.ts +266 -0
  96. package/ts/routing/router/index.ts +3 -8
  97. package/readme.problems.md +0 -170
  98. package/ts/core/utils/route-utils.ts +0 -312
  99. package/ts/proxies/smart-proxy/route-manager.ts +0 -554
  100. package/ts/routing/router/proxy-router.ts +0 -437
  101. package/ts/routing/router/route-router.ts +0 -482
package/readme.plan.md ADDED
@@ -0,0 +1,621 @@
1
+ # PROXY Protocol Implementation Plan
2
+
3
+ ## ⚠️ CRITICAL: Implementation Order
4
+
5
+ **Phase 1 (ProxyProtocolSocket/WrappedSocket) MUST be completed first!**
6
+
7
+ The ProxyProtocolSocket class is the foundation that enables all PROXY protocol functionality. No protocol parsing or integration can happen until this wrapper class is fully implemented and tested.
8
+
9
+ 1. **FIRST**: Implement ProxyProtocolSocket (the WrappedSocket)
10
+ 2. **THEN**: Add PROXY protocol parser
11
+ 3. **THEN**: Integrate with connection handlers
12
+ 4. **FINALLY**: Add security and validation
13
+
14
+ ## Overview
15
+ Implement PROXY protocol support in SmartProxy to preserve client IP information through proxy chains, solving the connection limit accumulation issue where inner proxies see all connections as coming from the outer proxy's IP.
16
+
17
+ ## Problem Statement
18
+ - In proxy chains, the inner proxy sees all connections from the outer proxy's IP
19
+ - This causes the inner proxy to hit per-IP connection limits (default: 100)
20
+ - Results in connection rejections while outer proxy accumulates connections
21
+
22
+ ## Solution Design
23
+
24
+ ### 1. Core Features
25
+
26
+ #### 1.1 PROXY Protocol Parsing
27
+ - Support PROXY protocol v1 (text format) initially
28
+ - Parse incoming PROXY headers to extract:
29
+ - Real client IP address
30
+ - Real client port
31
+ - Proxy IP address
32
+ - Proxy port
33
+ - Protocol (TCP4/TCP6)
34
+
35
+ #### 1.2 PROXY Protocol Generation
36
+ - Add ability to send PROXY protocol headers when forwarding connections
37
+ - Configurable per route or target
38
+
39
+ #### 1.3 Trusted Proxy IPs
40
+ - New `proxyIPs` array in SmartProxy options
41
+ - Auto-enable PROXY protocol acceptance for connections from these IPs
42
+ - Reject PROXY protocol from untrusted sources (security)
43
+
44
+ ### 2. Configuration Schema
45
+
46
+ ```typescript
47
+ interface ISmartProxyOptions {
48
+ // ... existing options
49
+
50
+ // List of trusted proxy IPs that can send PROXY protocol
51
+ proxyIPs?: string[];
52
+
53
+ // Global option to accept PROXY protocol (defaults based on proxyIPs)
54
+ acceptProxyProtocol?: boolean;
55
+
56
+ // Global option to send PROXY protocol to all targets
57
+ sendProxyProtocol?: boolean;
58
+ }
59
+
60
+ interface IRouteAction {
61
+ // ... existing options
62
+
63
+ // Send PROXY protocol to this specific target
64
+ sendProxyProtocol?: boolean;
65
+ }
66
+ ```
67
+
68
+ ### 3. Implementation Steps
69
+
70
+ #### IMPORTANT: Phase 1 Must Be Completed First
71
+ The `ProxyProtocolSocket` (WrappedSocket) is the foundation for all PROXY protocol functionality. This wrapper class must be implemented and integrated BEFORE any PROXY protocol parsing can begin.
72
+
73
+ #### Phase 1: ProxyProtocolSocket (WrappedSocket) Foundation - ✅ COMPLETED (v19.5.19)
74
+ This phase creates the socket wrapper infrastructure that all subsequent phases depend on.
75
+
76
+ 1. **Create WrappedSocket class** in `ts/core/models/wrapped-socket.ts` ✅
77
+ - Used JavaScript Proxy pattern instead of EventEmitter (avoids infinite loops)
78
+ - Properties for real client IP and port
79
+ - Transparent getters that return real or socket IP/port
80
+ - All socket methods/properties delegated via Proxy
81
+
82
+ 2. **Implement core wrapper functionality** ✅
83
+ - Constructor accepts regular socket + optional metadata
84
+ - `remoteAddress` getter returns real IP or falls back to socket IP
85
+ - `remotePort` getter returns real port or falls back to socket port
86
+ - `isFromTrustedProxy` property to check if it has real client info
87
+ - `setProxyInfo()` method to update real client details
88
+
89
+ 3. **Update ConnectionManager to handle wrapped sockets** ✅
90
+ - Accept either `net.Socket` or `WrappedSocket`
91
+ - Created `getUnderlyingSocket()` helper for socket utilities
92
+ - All socket utility functions extract underlying socket
93
+
94
+ 4. **Integration completed** ✅
95
+ - All incoming sockets wrapped in RouteConnectionHandler
96
+ - Socket forwarding verified working with wrapped sockets
97
+ - Type safety maintained with index signature
98
+
99
+ **Deliverables**: ✅ Working WrappedSocket that can wrap any socket and provide transparent access to client info.
100
+
101
+ #### Phase 2: PROXY Protocol Parser - DEPENDS ON PHASE 1
102
+ Only after WrappedSocket is working can we add protocol parsing.
103
+
104
+ 1. Create `ProxyProtocolParser` class in `ts/core/utils/proxy-protocol.ts`
105
+ 2. Implement v1 text format parsing
106
+ 3. Add validation and error handling
107
+ 4. Integrate parser to work WITH WrappedSocket (not into it)
108
+
109
+ #### Phase 3: Connection Handler Integration - DEPENDS ON PHASES 1 & 2
110
+ 1. ✅ Modify `RouteConnectionHandler` to create WrappedSocket for all connections
111
+ 2. Check if connection is from trusted proxy IP
112
+ 3. If trusted, attempt to parse PROXY protocol header
113
+ 4. Update wrapped socket with real client info
114
+ 5. Continue normal connection handling with wrapped socket
115
+
116
+ #### Phase 4: Outbound PROXY Protocol - DEPENDS ON PHASES 1-3
117
+ 1. Add PROXY header generation in `setupDirectConnection`
118
+ 2. Make it configurable per route
119
+ 3. Send header immediately after TCP connection
120
+ 4. Use ProxyProtocolSocket for outbound connections too
121
+
122
+ #### Phase 5: Security & Validation - FINAL PHASE
123
+ 1. Validate PROXY headers strictly
124
+ 2. Reject malformed headers
125
+ 3. Only accept from trusted IPs
126
+ 4. Add rate limiting for PROXY protocol parsing
127
+
128
+ ### 4. Design Decision: Socket Wrapper Architecture
129
+
130
+ #### Option A: Minimal Single Socket Wrapper
131
+ - **Scope**: Wraps individual sockets with metadata
132
+ - **Use Case**: PROXY protocol support with minimal refactoring
133
+ - **Pros**: Simple, low risk, easy migration
134
+ - **Cons**: Still need separate connection management
135
+
136
+ #### Option B: Comprehensive Connection Wrapper
137
+ - **Scope**: Manages socket pairs (incoming + outgoing) with all utilities
138
+ - **Use Case**: Complete connection lifecycle management
139
+ - **Pros**:
140
+ - Encapsulates all socket utilities (forwarding, cleanup, backpressure)
141
+ - Single object represents entire connection
142
+ - Cleaner API for connection handling
143
+ - **Cons**:
144
+ - Major architectural change
145
+ - Higher implementation risk
146
+ - More complex migration
147
+
148
+ #### Recommendation
149
+ Start with **Option A** (ProxyProtocolSocket) for immediate PROXY protocol support, then evaluate Option B based on:
150
+ - Performance impact of additional abstraction
151
+ - Code simplification benefits
152
+ - Team comfort with architectural change
153
+
154
+ ### 5. Code Implementation Details
155
+
156
+ #### 5.1 ProxyProtocolSocket (WrappedSocket) - PHASE 1 IMPLEMENTATION
157
+ This is the foundational wrapper class that MUST be implemented first. It wraps a regular socket and provides transparent access to the real client IP/port.
158
+
159
+ ```typescript
160
+ // ts/core/models/proxy-protocol-socket.ts
161
+ import { EventEmitter } from 'events';
162
+ import * as plugins from '../../../plugins.js';
163
+
164
+ /**
165
+ * ProxyProtocolSocket wraps a regular net.Socket to provide transparent access
166
+ * to the real client IP and port when behind a proxy using PROXY protocol.
167
+ *
168
+ * This is the FOUNDATION for all PROXY protocol support and must be implemented
169
+ * before any protocol parsing can occur.
170
+ */
171
+ export class ProxyProtocolSocket extends EventEmitter {
172
+ private realClientIP?: string;
173
+ private realClientPort?: number;
174
+
175
+ constructor(
176
+ public readonly socket: plugins.net.Socket,
177
+ realClientIP?: string,
178
+ realClientPort?: number
179
+ ) {
180
+ super();
181
+ this.realClientIP = realClientIP;
182
+ this.realClientPort = realClientPort;
183
+
184
+ // Forward all socket events
185
+ this.forwardSocketEvents();
186
+ }
187
+
188
+ /**
189
+ * Returns the real client IP if available, otherwise the socket's remote address
190
+ */
191
+ get remoteAddress(): string | undefined {
192
+ return this.realClientIP || this.socket.remoteAddress;
193
+ }
194
+
195
+ /**
196
+ * Returns the real client port if available, otherwise the socket's remote port
197
+ */
198
+ get remotePort(): number | undefined {
199
+ return this.realClientPort || this.socket.remotePort;
200
+ }
201
+
202
+ /**
203
+ * Indicates if this connection came through a trusted proxy
204
+ */
205
+ get isFromTrustedProxy(): boolean {
206
+ return !!this.realClientIP;
207
+ }
208
+
209
+ /**
210
+ * Updates the real client information (called after parsing PROXY protocol)
211
+ */
212
+ setProxyInfo(ip: string, port: number): void {
213
+ this.realClientIP = ip;
214
+ this.realClientPort = port;
215
+ }
216
+
217
+ // Pass-through all socket methods
218
+ write(data: any, encoding?: any, callback?: any): boolean {
219
+ return this.socket.write(data, encoding, callback);
220
+ }
221
+
222
+ end(data?: any, encoding?: any, callback?: any): this {
223
+ this.socket.end(data, encoding, callback);
224
+ return this;
225
+ }
226
+
227
+ destroy(error?: Error): this {
228
+ this.socket.destroy(error);
229
+ return this;
230
+ }
231
+
232
+ // ... implement all other socket methods as pass-through
233
+
234
+ /**
235
+ * Forward all events from the underlying socket
236
+ */
237
+ private forwardSocketEvents(): void {
238
+ const events = ['data', 'end', 'close', 'error', 'drain', 'timeout'];
239
+ events.forEach(event => {
240
+ this.socket.on(event, (...args) => {
241
+ this.emit(event, ...args);
242
+ });
243
+ });
244
+ }
245
+ }
246
+ ```
247
+
248
+ **KEY POINT**: This wrapper must be fully functional and tested BEFORE moving to Phase 2.
249
+
250
+ #### 4.2 ProxyProtocolParser (new file)
251
+ ```typescript
252
+ // ts/core/utils/proxy-protocol.ts
253
+ export class ProxyProtocolParser {
254
+ static readonly PROXY_V1_SIGNATURE = 'PROXY ';
255
+
256
+ static parse(chunk: Buffer): IProxyInfo | null {
257
+ // Implementation
258
+ }
259
+
260
+ static generate(info: IProxyInfo): Buffer {
261
+ // Implementation
262
+ }
263
+ }
264
+ ```
265
+
266
+ #### 4.3 Connection Handler Updates
267
+ ```typescript
268
+ // In handleConnection method
269
+ let wrappedSocket: ProxyProtocolSocket | plugins.net.Socket = socket;
270
+
271
+ // Wrap socket if from trusted proxy
272
+ if (this.settings.proxyIPs?.includes(socket.remoteAddress)) {
273
+ wrappedSocket = new ProxyProtocolSocket(socket);
274
+ }
275
+
276
+ // Create connection record with wrapped socket
277
+ const record = this.connectionManager.createConnection(wrappedSocket);
278
+
279
+ // In handleInitialData method
280
+ if (wrappedSocket instanceof ProxyProtocolSocket) {
281
+ const proxyInfo = await this.checkForProxyProtocol(chunk);
282
+ if (proxyInfo) {
283
+ wrappedSocket.setProxyInfo(proxyInfo.sourceIP, proxyInfo.sourcePort);
284
+ // Continue with remaining data after PROXY header
285
+ }
286
+ }
287
+ ```
288
+
289
+ #### 4.4 Security Manager Updates
290
+ - Accept socket or ProxyProtocolSocket
291
+ - Use `socket.remoteAddress` getter for real client IP
292
+ - Transparent handling of both socket types
293
+
294
+ ### 5. Configuration Examples
295
+
296
+ #### Basic Setup
297
+ ```typescript
298
+ // Outer proxy - sends PROXY protocol
299
+ const outerProxy = new SmartProxy({
300
+ ports: [443],
301
+ routes: [{
302
+ name: 'to-inner-proxy',
303
+ match: { ports: 443 },
304
+ action: {
305
+ type: 'forward',
306
+ target: { host: '195.201.98.232', port: 443 },
307
+ sendProxyProtocol: true // Enable for this route
308
+ }
309
+ }]
310
+ });
311
+
312
+ // Inner proxy - accepts PROXY protocol from outer proxy
313
+ const innerProxy = new SmartProxy({
314
+ ports: [443],
315
+ proxyIPs: ['212.95.99.130'], // Outer proxy IP
316
+ // acceptProxyProtocol: true is automatic for proxyIPs
317
+ routes: [{
318
+ name: 'to-backend',
319
+ match: { ports: 443 },
320
+ action: {
321
+ type: 'forward',
322
+ target: { host: '192.168.5.247', port: 443 }
323
+ }
324
+ }]
325
+ });
326
+ ```
327
+
328
+ ### 6. Testing Plan
329
+
330
+ #### Unit Tests
331
+ - PROXY protocol v1 parsing (valid/invalid formats)
332
+ - Header generation
333
+ - Trusted IP validation
334
+ - Connection record updates
335
+
336
+ #### Integration Tests
337
+ - Single proxy with PROXY protocol
338
+ - Proxy chain with PROXY protocol
339
+ - Security: reject from untrusted IPs
340
+ - Performance: minimal overhead
341
+ - Compatibility: works with TLS passthrough
342
+
343
+ #### Test Scenarios
344
+ 1. **Connection limit test**: Verify inner proxy sees real client IPs
345
+ 2. **Security test**: Ensure PROXY protocol rejected from untrusted sources
346
+ 3. **Compatibility test**: Verify no impact on non-PROXY connections
347
+ 4. **Performance test**: Measure overhead of PROXY protocol parsing
348
+
349
+ ### 7. Security Considerations
350
+
351
+ 1. **IP Spoofing Prevention**
352
+ - Only accept PROXY protocol from explicitly trusted IPs
353
+ - Validate all header fields
354
+ - Reject malformed headers immediately
355
+
356
+ 2. **Resource Protection**
357
+ - Limit PROXY header size (107 bytes for v1)
358
+ - Timeout for incomplete headers
359
+ - Rate limit connection attempts
360
+
361
+ 3. **Logging**
362
+ - Log all PROXY protocol acceptance/rejection
363
+ - Include real client IP in all connection logs
364
+
365
+ ### 8. Rollout Strategy
366
+
367
+ 1. **Phase 1**: Deploy parser and acceptance (backward compatible)
368
+ 2. **Phase 2**: Enable between controlled proxy pairs
369
+ 3. **Phase 3**: Monitor for issues and performance impact
370
+ 4. **Phase 4**: Expand to all proxy chains
371
+
372
+ ### 9. Success Metrics
373
+
374
+ - Inner proxy connection distribution matches outer proxy
375
+ - No more connection limit rejections in proxy chains
376
+ - Accurate client IP logging throughout the chain
377
+ - No performance degradation (<1ms added latency)
378
+
379
+ ### 10. Future Enhancements
380
+
381
+ - PROXY protocol v2 (binary format) support
382
+ - TLV extensions for additional metadata
383
+ - AWS VPC endpoint ID support
384
+ - Custom metadata fields
385
+
386
+ ## WrappedSocket Class Design
387
+
388
+ ### Overview
389
+ A WrappedSocket class has been evaluated and recommended to provide cleaner PROXY protocol integration and better socket management architecture.
390
+
391
+ ### Rationale for WrappedSocket
392
+
393
+ #### Current Challenges
394
+ - Sockets handled directly as `net.Socket` instances throughout codebase
395
+ - Metadata tracked separately in `IConnectionRecord` objects
396
+ - Socket augmentation via TypeScript module augmentation for TLS properties
397
+ - PROXY protocol would require modifying socket handling in multiple places
398
+
399
+ #### Benefits
400
+ 1. **Clean PROXY Protocol Integration** - Parse and store real client IP/port without modifying existing socket handling
401
+ 2. **Better Encapsulation** - Bundle socket + metadata + behavior together
402
+ 3. **Type Safety** - No more module augmentation needed
403
+ 4. **Future Extensibility** - Easy to add compression, metrics, etc.
404
+ 5. **Simplified Testing** - Easier to mock and test socket behavior
405
+
406
+ ### Implementation Strategy
407
+
408
+ #### Phase 1: Minimal ProxyProtocolSocket (Immediate)
409
+ Create a minimal wrapper for PROXY protocol support:
410
+
411
+ ```typescript
412
+ class ProxyProtocolSocket {
413
+ constructor(
414
+ public socket: net.Socket,
415
+ public realClientIP?: string,
416
+ public realClientPort?: number
417
+ ) {}
418
+
419
+ get remoteAddress(): string {
420
+ return this.realClientIP || this.socket.remoteAddress || '';
421
+ }
422
+
423
+ get remotePort(): number {
424
+ return this.realClientPort || this.socket.remotePort || 0;
425
+ }
426
+
427
+ get isFromTrustedProxy(): boolean {
428
+ return !!this.realClientIP;
429
+ }
430
+ }
431
+ ```
432
+
433
+ Integration points:
434
+ - Use in `RouteConnectionHandler` when receiving from trusted proxy IPs
435
+ - Update `ConnectionManager` to accept wrapped sockets
436
+ - Modify security checks to use `socket.remoteAddress` getter
437
+
438
+ #### Phase 2: Connection-Aware WrappedSocket (Alternative Design)
439
+ A more comprehensive design that manages both sides of a connection:
440
+
441
+ ```typescript
442
+ // Option A: Single Socket Wrapper (simpler)
443
+ class WrappedSocket extends EventEmitter {
444
+ private socket: net.Socket;
445
+ private connectionId: string;
446
+ private metadata: ISocketMetadata;
447
+
448
+ constructor(socket: net.Socket, metadata?: Partial<ISocketMetadata>) {
449
+ super();
450
+ this.socket = socket;
451
+ this.connectionId = this.generateId();
452
+ this.metadata = { ...defaultMetadata, ...metadata };
453
+ this.setupHandlers();
454
+ }
455
+
456
+ // ... single socket management
457
+ }
458
+
459
+ // Option B: Connection Pair Wrapper (comprehensive)
460
+ class WrappedConnection extends EventEmitter {
461
+ private connectionId: string;
462
+ private incoming: WrappedSocket;
463
+ private outgoing?: WrappedSocket;
464
+ private forwardingActive: boolean = false;
465
+
466
+ constructor(incomingSocket: net.Socket) {
467
+ super();
468
+ this.connectionId = this.generateId();
469
+ this.incoming = new WrappedSocket(incomingSocket);
470
+ }
471
+
472
+ // Connect to backend and set up forwarding
473
+ async connectToBackend(target: ITarget): Promise<void> {
474
+ const outgoingSocket = await this.createOutgoingConnection(target);
475
+ this.outgoing = new WrappedSocket(outgoingSocket);
476
+ await this.setupBidirectionalForwarding();
477
+ }
478
+
479
+ // Built-in forwarding logic from socket-utils
480
+ private async setupBidirectionalForwarding(): Promise<void> {
481
+ if (!this.outgoing) throw new Error('No outgoing socket');
482
+
483
+ // Handle data forwarding with backpressure
484
+ this.incoming.on('data', (chunk) => {
485
+ this.outgoing!.write(chunk, () => {
486
+ // Handle backpressure
487
+ });
488
+ });
489
+
490
+ this.outgoing.on('data', (chunk) => {
491
+ this.incoming.write(chunk, () => {
492
+ // Handle backpressure
493
+ });
494
+ });
495
+
496
+ // Handle connection lifecycle
497
+ const cleanup = (reason: string) => {
498
+ this.forwardingActive = false;
499
+ this.incoming.destroy();
500
+ this.outgoing?.destroy();
501
+ this.emit('closed', reason);
502
+ };
503
+
504
+ this.incoming.once('close', () => cleanup('incoming_closed'));
505
+ this.outgoing.once('close', () => cleanup('outgoing_closed'));
506
+
507
+ this.forwardingActive = true;
508
+ }
509
+
510
+ // PROXY protocol support
511
+ async handleProxyProtocol(trustedProxies: string[]): Promise<boolean> {
512
+ if (trustedProxies.includes(this.incoming.socket.remoteAddress)) {
513
+ const parsed = await this.incoming.parseProxyProtocol();
514
+ if (parsed && this.outgoing) {
515
+ // Forward PROXY protocol to backend if configured
516
+ await this.outgoing.sendProxyProtocol(this.incoming.realClientIP);
517
+ }
518
+ return parsed;
519
+ }
520
+ return false;
521
+ }
522
+
523
+ // Consolidated metrics
524
+ getMetrics(): IConnectionMetrics {
525
+ return {
526
+ connectionId: this.connectionId,
527
+ duration: Date.now() - this.startTime,
528
+ incoming: this.incoming.getMetrics(),
529
+ outgoing: this.outgoing?.getMetrics(),
530
+ totalBytes: this.getTotalBytes(),
531
+ state: this.getConnectionState()
532
+ };
533
+ }
534
+ }
535
+ ```
536
+
537
+ #### Phase 3: Full Migration (Long-term)
538
+ - Replace all `net.Socket` usage with `WrappedSocket`
539
+ - Remove socket augmentation from `socket-augmentation.ts`
540
+ - Update all socket utilities to work with wrapped sockets
541
+ - Standardize socket handling across all components
542
+
543
+ ### Integration with PROXY Protocol
544
+
545
+ The WrappedSocket class integrates seamlessly with PROXY protocol:
546
+
547
+ 1. **Connection Acceptance**:
548
+ ```typescript
549
+ const wrappedSocket = new ProxyProtocolSocket(socket);
550
+ if (this.isFromTrustedProxy(socket.remoteAddress)) {
551
+ await wrappedSocket.parseProxyProtocol(this.settings.proxyIPs);
552
+ }
553
+ ```
554
+
555
+ 2. **Security Checks**:
556
+ ```typescript
557
+ // Automatically uses real client IP if available
558
+ const clientIP = wrappedSocket.remoteAddress;
559
+ if (!this.securityManager.isIPAllowed(clientIP)) {
560
+ wrappedSocket.destroy();
561
+ }
562
+ ```
563
+
564
+ 3. **Connection Records**:
565
+ ```typescript
566
+ const record = this.connectionManager.createConnection(wrappedSocket);
567
+ // ConnectionManager uses wrappedSocket.remoteAddress transparently
568
+ ```
569
+
570
+ ### Option B Example: How It Would Replace Current Architecture
571
+
572
+ Instead of current approach with separate components:
573
+ ```typescript
574
+ // Current: Multiple separate components
575
+ const record = connectionManager.createConnection(socket);
576
+ const { cleanupClient, cleanupServer } = createIndependentSocketHandlers(
577
+ clientSocket, serverSocket, onBothClosed
578
+ );
579
+ setupBidirectionalForwarding(clientSocket, serverSocket, handlers);
580
+ ```
581
+
582
+ Option B would consolidate everything:
583
+ ```typescript
584
+ // Option B: Single connection object
585
+ const connection = new WrappedConnection(incomingSocket);
586
+ await connection.handleProxyProtocol(trustedProxies);
587
+ await connection.connectToBackend({ host: 'server', port: 443 });
588
+ // Everything is handled internally - forwarding, cleanup, metrics
589
+
590
+ connection.on('closed', (reason) => {
591
+ logger.log('Connection closed', connection.getMetrics());
592
+ });
593
+ ```
594
+
595
+ This would replace:
596
+ - `IConnectionRecord` - absorbed into WrappedConnection
597
+ - `socket-utils.ts` functions - methods on WrappedConnection
598
+ - Separate incoming/outgoing tracking - unified in one object
599
+ - Manual cleanup coordination - automatic lifecycle management
600
+
601
+ Additional benefits with Option B:
602
+ - **Connection Pooling Integration**: WrappedConnection could integrate with EnhancedConnectionPool for backend connections
603
+ - **Unified Metrics**: Single point for all connection statistics
604
+ - **Protocol Negotiation**: Handle PROXY, TLS, HTTP/2 upgrade in one place
605
+ - **Resource Management**: Automatic cleanup with LifecycleComponent pattern
606
+
607
+ ### Migration Path
608
+
609
+ 1. **Week 1-2**: Implement minimal ProxyProtocolSocket (Option A)
610
+ 2. **Week 3-4**: Test with PROXY protocol implementation
611
+ 3. **Month 2**: Prototype WrappedConnection (Option B) if beneficial
612
+ 4. **Month 3-6**: Gradual migration if Option B proves valuable
613
+ 5. **Future**: Complete adoption in next major version
614
+
615
+ ### Success Criteria
616
+
617
+ - PROXY protocol works transparently with wrapped sockets
618
+ - No performance regression (<0.1% overhead)
619
+ - Simplified code in connection handlers
620
+ - Better TypeScript type safety
621
+ - Easier to add new socket-level features