feat(proxy): Start implementing PROXY protocol support and WrappedSocket class for enhanced client IP handling
This commit is contained in:
143
readme.hints.md
143
readme.hints.md
@@ -661,4 +661,145 @@ Updated all forwarding handlers to use the new centralized socket utilities:
|
||||
- Reduced code duplication
|
||||
|
||||
### Migration Notes
|
||||
No user-facing changes. All forwarding handlers now use the same robust socket handling as the main SmartProxy connection handler.
|
||||
No user-facing changes. All forwarding handlers now use the same robust socket handling as the main SmartProxy connection handler.
|
||||
|
||||
## WrappedSocket Class Evaluation for PROXY Protocol (v19.5.19+)
|
||||
|
||||
### Current Socket Handling Architecture
|
||||
- Sockets are handled directly as `net.Socket` instances throughout the codebase
|
||||
- Socket augmentation via TypeScript module augmentation for TLS properties
|
||||
- Metadata tracked separately in `IConnectionRecord` objects
|
||||
- Socket utilities provide helper functions but don't encapsulate the socket
|
||||
- Connection records track extensive metadata (IDs, timestamps, byte counters, TLS state, etc.)
|
||||
|
||||
### Evaluation: Should We Introduce a WrappedSocket Class?
|
||||
|
||||
**Yes, a WrappedSocket class would make sense**, particularly for PROXY protocol implementation and future extensibility.
|
||||
|
||||
### Design Considerations for WrappedSocket
|
||||
|
||||
```typescript
|
||||
class WrappedSocket {
|
||||
private socket: net.Socket;
|
||||
private connectionId: string;
|
||||
private metadata: {
|
||||
realClientIP?: string; // From PROXY protocol
|
||||
realClientPort?: number; // From PROXY protocol
|
||||
proxyIP?: string; // Immediate connection IP
|
||||
proxyPort?: number; // Immediate connection port
|
||||
bytesReceived: number;
|
||||
bytesSent: number;
|
||||
lastActivity: number;
|
||||
isTLS: boolean;
|
||||
// ... other metadata
|
||||
};
|
||||
|
||||
// PROXY protocol handling
|
||||
private proxyProtocolParsed: boolean = false;
|
||||
private pendingData: Buffer[] = [];
|
||||
|
||||
constructor(socket: net.Socket) {
|
||||
this.socket = socket;
|
||||
this.setupHandlers();
|
||||
}
|
||||
|
||||
// Getters for clean access
|
||||
get remoteAddress(): string {
|
||||
return this.metadata.realClientIP || this.socket.remoteAddress || '';
|
||||
}
|
||||
|
||||
get remotePort(): number {
|
||||
return this.metadata.realClientPort || this.socket.remotePort || 0;
|
||||
}
|
||||
|
||||
get isFromTrustedProxy(): boolean {
|
||||
return !!this.metadata.realClientIP;
|
||||
}
|
||||
|
||||
// PROXY protocol parsing
|
||||
async parseProxyProtocol(trustedProxies: string[]): Promise<boolean> {
|
||||
// Implementation here
|
||||
}
|
||||
|
||||
// Delegate socket methods
|
||||
write(data: any): boolean {
|
||||
this.metadata.bytesSent += Buffer.byteLength(data);
|
||||
return this.socket.write(data);
|
||||
}
|
||||
|
||||
destroy(error?: Error): void {
|
||||
this.socket.destroy(error);
|
||||
}
|
||||
|
||||
// Event forwarding
|
||||
on(event: string, listener: Function): this {
|
||||
this.socket.on(event, listener);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Implementation Benefits
|
||||
|
||||
1. **Encapsulation**: Bundle socket + metadata + behavior in one place
|
||||
2. **PROXY Protocol Integration**: Cleaner handling without modifying existing socket code
|
||||
3. **State Management**: Centralized socket state tracking and validation
|
||||
4. **API Consistency**: Uniform interface for all socket operations
|
||||
5. **Future Extensibility**: Easy to add new socket-level features (compression, encryption, etc.)
|
||||
6. **Type Safety**: Better TypeScript support without module augmentation
|
||||
7. **Testing**: Easier to mock and test socket behavior
|
||||
|
||||
### Implementation Drawbacks
|
||||
|
||||
1. **Major Refactoring**: Would require changes throughout the codebase
|
||||
2. **Performance Overhead**: Additional abstraction layer (minimal but present)
|
||||
3. **Compatibility**: Need to maintain event emitter compatibility
|
||||
4. **Learning Curve**: Developers need to understand the wrapper
|
||||
|
||||
### Recommended Approach: Phased Implementation
|
||||
|
||||
**Phase 1: PROXY Protocol Only** (Immediate)
|
||||
- Create minimal `ProxyProtocolSocket` wrapper for new connections from trusted proxies
|
||||
- Use in connection handler when receiving from trusted proxy IPs
|
||||
- Minimal disruption to existing code
|
||||
|
||||
```typescript
|
||||
class ProxyProtocolSocket {
|
||||
constructor(
|
||||
public socket: net.Socket,
|
||||
public realClientIP?: string,
|
||||
public realClientPort?: number
|
||||
) {}
|
||||
|
||||
get remoteAddress(): string {
|
||||
return this.realClientIP || this.socket.remoteAddress || '';
|
||||
}
|
||||
|
||||
get remotePort(): number {
|
||||
return this.realClientPort || this.socket.remotePort || 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 2: Gradual Migration** (Future)
|
||||
- Extend wrapper with more functionality
|
||||
- Migrate critical paths to use wrapper
|
||||
- Add performance monitoring
|
||||
|
||||
**Phase 3: Full Adoption** (Long-term)
|
||||
- Complete migration to WrappedSocket
|
||||
- Remove socket augmentation
|
||||
- Standardize all socket handling
|
||||
|
||||
### Decision Summary
|
||||
|
||||
✅ **Implement minimal ProxyProtocolSocket for immediate PROXY protocol support**
|
||||
- Low risk, high value
|
||||
- Solves the immediate proxy chain connection limit issue
|
||||
- Sets foundation for future improvements
|
||||
- Can be implemented alongside existing code
|
||||
|
||||
📋 **Consider full WrappedSocket for future major version**
|
||||
- Cleaner architecture
|
||||
- Better maintainability
|
||||
- But requires significant refactoring
|
Reference in New Issue
Block a user