fix(ja4ebpf): fix TLS capture, SYN offsets, TCP option parsing
- Increase MAX_TLS_PAYLOAD from 512 to 2048 bytes to capture full TLS ClientHellos (modern browsers/curl send 1000-1543 byte ClientHellos) - Fix ParseClientHello to tolerate XDP-truncated payloads: clamp recordLength and chLen to available data instead of returning error - Fix cipher suites, compression, extensions truncation to use clamping - Fix consumeSynEvents struct field offsets: dst_ip (4 bytes at offset 4) was not accounted for, causing all L3/L4 metadata to be read from wrong positions (TTL was actually dst_ip[0], windowSize was dst_port, etc.) - Add parseTCPOptions() to extract MSS and Window Scale from raw TCP options (C code sets defaults of mss=0, window_scale=0xFF, expects Go to parse) - Fix consumeAcceptEvents: skip zero-IP events to avoid phantom sessions - Fix consumeSSLEvents: filter zero-IP/port events when proc fallback fails - Add missing consumeHTTPPlainEvents goroutine (was defined but never called) - Fix race condition: SYN consumer sets Correlated=true if TLS already present - Update tls_hello_event struct offsets in Go consumer (payload_len now at offset 2054, was 518, due to payload array growing from 512 to 2048 bytes) - Remove debug logging from consumers and GC E2E verified: HTTP plain (port 80) and HTTPS (port 443) both produce fully correlated sessions in ClickHouse with correct: - ip_meta_ttl=64, ip_meta_df=true, ip_meta_id - tcp_meta_window_size=64240, tcp_meta_window_scale=10, tcp_meta_mss=1460 - ja4=t13i3010_1d37bd780c83_95d2a80e6515 - tls_alpn=http/1.1 - method=GET, path=/, header_order_signature=Host;User-Agent;Accept - correlated=1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@ -47,8 +47,12 @@ func ParseClientHello(payload []byte) (*ClientHello, error) {
|
||||
recordVersion := binary.BigEndian.Uint16(payload[1:3])
|
||||
recordLength := int(binary.BigEndian.Uint16(payload[3:5]))
|
||||
|
||||
if len(payload) < 5+recordLength {
|
||||
return nil, fmt.Errorf("record TLS tronqué: attendu %d octets, reçu %d", 5+recordLength, len(payload))
|
||||
// Le XDP capture au maximum MAX_TLS_PAYLOAD (512) octets.
|
||||
// Si la taille du record TLS dépasse les données disponibles, on travaille
|
||||
// avec ce qu'on a (le ClientHello est toujours en début de record).
|
||||
available := len(payload) - 5
|
||||
if recordLength > available {
|
||||
recordLength = available
|
||||
}
|
||||
|
||||
// Parsing du message Handshake
|
||||
@ -64,8 +68,9 @@ func ParseClientHello(payload []byte) (*ClientHello, error) {
|
||||
|
||||
// Longueur du ClientHello (3 octets big-endian)
|
||||
chLen := int(uint32(hs[1])<<16 | uint32(hs[2])<<8 | uint32(hs[3]))
|
||||
if len(hs) < 4+chLen {
|
||||
return nil, fmt.Errorf("ClientHello tronqué: attendu %d octets", 4+chLen)
|
||||
// Tolérance à la troncature XDP : on travaille avec ce qu'on a
|
||||
if chLen > len(hs)-4 {
|
||||
chLen = len(hs) - 4
|
||||
}
|
||||
|
||||
ch := &ClientHello{RecordVersion: recordVersion}
|
||||
@ -98,9 +103,9 @@ func ParseClientHello(payload []byte) (*ClientHello, error) {
|
||||
csLen := int(binary.BigEndian.Uint16(data[offset : offset+2]))
|
||||
offset += 2
|
||||
if len(data) < offset+csLen {
|
||||
return nil, fmt.Errorf("ClientHello: cipher suites tronquées")
|
||||
csLen = len(data) - offset // troncature tolérée
|
||||
}
|
||||
for i := 0; i < csLen; i += 2 {
|
||||
for i := 0; i+2 <= csLen; i += 2 {
|
||||
cs := binary.BigEndian.Uint16(data[offset+i : offset+i+2])
|
||||
ch.CipherSuites = append(ch.CipherSuites, cs)
|
||||
}
|
||||
@ -108,12 +113,12 @@ func ParseClientHello(payload []byte) (*ClientHello, error) {
|
||||
|
||||
// Compression Methods (longueur 1 octet + données)
|
||||
if len(data) < offset+1 {
|
||||
return nil, fmt.Errorf("ClientHello: longueur compression manquante")
|
||||
return ch, nil // troncature : retourner ce qu'on a
|
||||
}
|
||||
compLen := int(data[offset])
|
||||
offset++
|
||||
if len(data) < offset+compLen {
|
||||
return nil, fmt.Errorf("ClientHello: méthodes de compression tronquées")
|
||||
compLen = len(data) - offset
|
||||
}
|
||||
ch.CompressionMethods = data[offset : offset+compLen]
|
||||
offset += compLen
|
||||
@ -125,7 +130,7 @@ func ParseClientHello(payload []byte) (*ClientHello, error) {
|
||||
extTotalLen := int(binary.BigEndian.Uint16(data[offset : offset+2]))
|
||||
offset += 2
|
||||
if len(data) < offset+extTotalLen {
|
||||
return nil, fmt.Errorf("ClientHello: extensions tronquées")
|
||||
extTotalLen = len(data) - offset // troncature tolérée
|
||||
}
|
||||
|
||||
// Parsing des extensions
|
||||
|
||||
Reference in New Issue
Block a user