fix(detection): fix SNI detection in TLS detector
Some checks failed
Default (tags) / security (push) Successful in 53s
Default (tags) / test (push) Failing after 43m34s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped

This commit is contained in:
Juergen Kunz
2025-07-22 00:19:59 +00:00
parent 36068a6d92
commit 8936f4ad46
13 changed files with 837 additions and 393 deletions

View File

@@ -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, readUInt24BE, BufferAccumulator } from '../utils/buffer-utils.js';
import { readUInt16BE, BufferAccumulator } from '../utils/buffer-utils.js';
import { tlsVersionToString } from '../utils/parser-utils.js';
// Import from protocols
@@ -29,6 +29,13 @@ export class TlsDetector implements IProtocolDetector {
*/
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
*/
@@ -201,11 +208,11 @@ export class TlsDetector implements IProtocolDetector {
/**
* Parse cipher suites
*/
private parseCipherSuites(data: Buffer): number[] {
private parseCipherSuites(cipherData: Buffer): number[] {
const suites: number[] = [];
for (let i = 0; i + 1 < data.length; i += 2) {
const suite = readUInt16BE(data, i);
for (let i = 0; i < cipherData.length - 1; i += 2) {
const suite = readUInt16BE(cipherData, i);
suites.push(suite);
}
@@ -213,45 +220,31 @@ export class TlsDetector implements IProtocolDetector {
}
/**
* Handle fragmented TLS detection with connection tracking
* Detect with context for fragmented data
*/
static detectWithFragments(
buffer: Buffer,
connectionId: string,
detectWithContext(
buffer: Buffer,
context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number },
options?: IDetectionOptions
): IDetectionResult | null {
const detector = new TlsDetector();
const connectionId = this.createConnectionId(context);
// Try direct detection first
const directResult = detector.detect(buffer, options);
if (directResult && directResult.isComplete) {
// Clean up any tracked fragments for this connection
this.fragmentedBuffers.delete(connectionId);
return directResult;
}
// Handle fragmentation
let accumulator = this.fragmentedBuffers.get(connectionId);
// Get or create buffer accumulator for this connection
let accumulator = TlsDetector.fragmentedBuffers.get(connectionId);
if (!accumulator) {
accumulator = new BufferAccumulator();
this.fragmentedBuffers.set(connectionId, accumulator);
TlsDetector.fragmentedBuffers.set(connectionId, accumulator);
}
// Add new data
accumulator.append(buffer);
const fullBuffer = accumulator.getBuffer();
// Try detection on accumulated buffer
const result = detector.detect(fullBuffer, options);
// Try detection on accumulated data
const result = this.detect(accumulator.getBuffer(), options);
if (result && result.isComplete) {
// Success - clean up
this.fragmentedBuffers.delete(connectionId);
return result;
}
// Check timeout
if (options?.timeout) {
// TODO: Implement timeout handling
// If detection is complete or we have too much data, clean up
if (result?.isComplete || accumulator.length() > 65536) {
TlsDetector.fragmentedBuffers.delete(connectionId);
}
return result;