update
This commit is contained in:
		| @@ -5,7 +5,7 @@ | ||||
| // TLS detector doesn't need plugins imports | ||||
| import type { IProtocolDetector } from '../models/interfaces.js'; | ||||
| import type { IDetectionResult, IDetectionOptions, IConnectionInfo } from '../models/detection-types.js'; | ||||
| import { readUInt16BE, BufferAccumulator } from '../utils/buffer-utils.js'; | ||||
| import { readUInt16BE } from '../utils/buffer-utils.js'; | ||||
| import { tlsVersionToString } from '../utils/parser-utils.js'; | ||||
|  | ||||
| // Import from protocols | ||||
| @@ -24,17 +24,6 @@ export class TlsDetector implements IProtocolDetector { | ||||
|    */ | ||||
|   private static readonly MIN_TLS_HEADER_SIZE = 5; | ||||
|    | ||||
|   /** | ||||
|    * Fragment tracking for incomplete handshakes | ||||
|    */ | ||||
|   private static fragmentedBuffers = new Map<string, BufferAccumulator>(); | ||||
|    | ||||
|   /** | ||||
|    * Create connection ID from context | ||||
|    */ | ||||
|   private createConnectionId(context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number }): string { | ||||
|     return `${context.sourceIp || 'unknown'}:${context.sourcePort || 0}->${context.destIp || 'unknown'}:${context.destPort || 0}`; | ||||
|   } | ||||
|    | ||||
|   /** | ||||
|    * Detect TLS protocol from buffer | ||||
| @@ -224,29 +213,11 @@ export class TlsDetector implements IProtocolDetector { | ||||
|    */ | ||||
|   detectWithContext( | ||||
|     buffer: Buffer, | ||||
|     context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number }, | ||||
|     _context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number }, | ||||
|     options?: IDetectionOptions | ||||
|   ): IDetectionResult | null { | ||||
|     const connectionId = this.createConnectionId(context); | ||||
|      | ||||
|     // Get or create buffer accumulator for this connection | ||||
|     let accumulator = TlsDetector.fragmentedBuffers.get(connectionId); | ||||
|     if (!accumulator) { | ||||
|       accumulator = new BufferAccumulator(); | ||||
|       TlsDetector.fragmentedBuffers.set(connectionId, accumulator); | ||||
|     } | ||||
|      | ||||
|     // Add new data | ||||
|     accumulator.append(buffer); | ||||
|      | ||||
|     // Try detection on accumulated data | ||||
|     const result = this.detect(accumulator.getBuffer(), options); | ||||
|      | ||||
|     // If detection is complete or we have too much data, clean up | ||||
|     if (result?.isComplete || accumulator.length() > 65536) { | ||||
|       TlsDetector.fragmentedBuffers.delete(connectionId); | ||||
|     } | ||||
|      | ||||
|     return result; | ||||
|     // This method is deprecated - TLS detection should use the fragment manager | ||||
|     // from the parent detector system, not maintain its own fragments | ||||
|     return this.detect(buffer, options); | ||||
|   } | ||||
| } | ||||
| @@ -120,10 +120,28 @@ export class ProtocolDetector { | ||||
|       }; | ||||
|     } | ||||
|      | ||||
|     const connectionId = DetectionFragmentManager.createConnectionId(context); | ||||
|      | ||||
|     // First peek to determine protocol type | ||||
|     if (this.tlsDetector.canHandle(buffer)) { | ||||
|       const result = this.tlsDetector.detectWithContext(buffer, context, options); | ||||
|       // Handle TLS with fragment accumulation | ||||
|       const handler = this.fragmentManager.getHandler('tls'); | ||||
|       const fragmentResult = handler.addFragment(connectionId, buffer); | ||||
|        | ||||
|       if (fragmentResult.error) { | ||||
|         handler.complete(connectionId); | ||||
|         return { | ||||
|           protocol: 'unknown', | ||||
|           connectionInfo: { protocol: 'unknown' }, | ||||
|           isComplete: true | ||||
|         }; | ||||
|       } | ||||
|        | ||||
|       const result = this.tlsDetector.detect(fragmentResult.buffer!, options); | ||||
|       if (result) { | ||||
|         if (result.isComplete) { | ||||
|           handler.complete(connectionId); | ||||
|         } | ||||
|         return result; | ||||
|       } | ||||
|     } | ||||
| @@ -173,13 +191,25 @@ export class ProtocolDetector { | ||||
|   /** | ||||
|    * Clean up old connection tracking entries | ||||
|    *  | ||||
|    * @param maxAge Maximum age in milliseconds (default: 30 seconds) | ||||
|    * @param _maxAge Maximum age in milliseconds (default: 30 seconds) | ||||
|    */ | ||||
|   static cleanupConnections(maxAge: number = 30000): void { | ||||
|   static cleanupConnections(_maxAge: number = 30000): void { | ||||
|     // Cleanup is now handled internally by the fragment manager | ||||
|     this.getInstance().fragmentManager.cleanup(); | ||||
|   } | ||||
|    | ||||
|   /** | ||||
|    * Clean up fragments for a specific connection | ||||
|    */ | ||||
|   static cleanupConnection(context: IConnectionContext): void { | ||||
|     const instance = this.getInstance(); | ||||
|     const connectionId = DetectionFragmentManager.createConnectionId(context); | ||||
|      | ||||
|     // Clean up both TLS and HTTP fragments for this connection | ||||
|     instance.fragmentManager.getHandler('tls').complete(connectionId); | ||||
|     instance.fragmentManager.getHandler('http').complete(connectionId); | ||||
|   } | ||||
|    | ||||
|   /** | ||||
|    * Extract domain from connection info | ||||
|    */ | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import { connectionLogDeduplicator } from '../../core/utils/log-deduplicator.js' | ||||
| import { LifecycleComponent } from '../../core/utils/lifecycle-component.js'; | ||||
| import { cleanupSocket } from '../../core/utils/socket-utils.js'; | ||||
| import { WrappedSocket } from '../../core/models/wrapped-socket.js'; | ||||
| import { ProtocolDetector } from '../../detection/index.js'; | ||||
| import type { SmartProxy } from './smart-proxy.js'; | ||||
|  | ||||
| /** | ||||
| @@ -323,6 +324,18 @@ export class ConnectionManager extends LifecycleComponent { | ||||
|         this.smartProxy.metricsCollector.removeConnection(record.id); | ||||
|       } | ||||
|  | ||||
|       // Clean up protocol detection fragments | ||||
|       const context = ProtocolDetector.createConnectionContext({ | ||||
|         sourceIp: record.remoteIP, | ||||
|         sourcePort: record.incoming?.remotePort || 0, | ||||
|         destIp: record.incoming?.localAddress || '', | ||||
|         destPort: record.localPort, | ||||
|         socketId: record.id | ||||
|       }); | ||||
|        | ||||
|       // Clean up any pending detection fragments for this connection | ||||
|       ProtocolDetector.cleanupConnection(context); | ||||
|  | ||||
|       if (record.cleanupTimer) { | ||||
|         clearTimeout(record.cleanupTimer); | ||||
|         record.cleanupTimer = undefined; | ||||
|   | ||||
| @@ -303,18 +303,18 @@ export class RouteConnectionHandler { | ||||
|  | ||||
|     // Handler for processing initial data (after potential PROXY protocol) | ||||
|     const processInitialData = async (chunk: Buffer) => { | ||||
|       // Use ProtocolDetector to identify protocol | ||||
|       const connectionId = ProtocolDetector.createConnectionId({ | ||||
|       // Create connection context for protocol detection | ||||
|       const context = ProtocolDetector.createConnectionContext({ | ||||
|         sourceIp: record.remoteIP, | ||||
|         sourcePort: socket.remotePort, | ||||
|         destIp: socket.localAddress, | ||||
|         destPort: socket.localPort, | ||||
|         sourcePort: socket.remotePort || 0, | ||||
|         destIp: socket.localAddress || '', | ||||
|         destPort: socket.localPort || 0, | ||||
|         socketId: record.id | ||||
|       }); | ||||
|        | ||||
|       const detectionResult = await ProtocolDetector.detectWithConnectionTracking( | ||||
|       const detectionResult = await ProtocolDetector.detectWithContext( | ||||
|         chunk, | ||||
|         connectionId, | ||||
|         context, | ||||
|         { extractFullHeaders: false } // Only extract essential info for routing | ||||
|       ); | ||||
|        | ||||
|   | ||||
		Reference in New Issue
	
	Block a user