@push.rocks/smartproxy 19.6.1 → 19.6.6

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