- 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>
Tests VM — eBPF sur kernel réel (Rocky Linux 9)
Pourquoi une VM ?
Les tests Docker ne peuvent capturer que L3/L4 et TLS (via le hook TC). Les données L7 HTTP (method, path, status_code, header_order_signature) nécessitent :
| Fonctionnalité eBPF | Docker | VM |
|---|---|---|
| Hook TC (XDP) — L3/L4 + TLS | ✅ | ✅ |
| Uprobe SSL_read — L7 HTTP | ✅ attache | ✅ attache |
| Tracepoint accept4 — corrélation IP | ❌ pas de tracefs | ✅ |
| Kprobe accept4 — corrélation IP | ❌ pas de perf PMU | ✅ |
Dans une VM, le kernel complet est disponible → accept4 fonctionne → la corrélation IP est parfaite → les données L7 arrivent dans ClickHouse.
Prérequis (installation unique)
# 1. Installer Vagrant + libvirt + KVM
sudo apt-get install -y vagrant libvirt-daemon-system libvirt-clients \
qemu-kvm ruby-libvirt bridge-utils
# 2. Plugin vagrant-libvirt
vagrant plugin install vagrant-libvirt
# 3. Ajouter ton user aux groupes (nécessite une reconnexion)
sudo usermod -aG libvirt,kvm $USER
# → Se déconnecter et se reconnecter
# 4. Vérifier que KVM fonctionne
virsh list --all
Utilisation
# Depuis la racine du projet :
# Créer la VM (première fois, ~5-10 min — télécharge Rocky Linux 9)
make vm-up
# Lancer le test nginx complet (L3/L4 + TLS + L7 HTTP)
make test-vm-nginx
# Après modification des sources Go/C
make vm-rebuild-ja4ebpf # synchronise + recompile dans la VM
make test-vm-nginx # relancer les tests
# Connexion SSH interactive
make vm-ssh
# Détruire la VM (libère l'espace disque)
make vm-down
Ce que teste test-vm-nginx
- Build — recompile ja4ebpf (BPF CO-RE + Go) depuis les sources
- ClickHouse — démarre dans Docker (dans la VM)
- nginx — démarre avec TLS + HTTP/2
- ja4ebpf — démarre avec uprobes + accept4 tracepoints
- Trafic — HTTP/1.0, HTTP/1.1, HTTPS/1.1, HTTPS/2.0
- Vérification DB :
ip_meta_ttl,tcp_meta_mss,tcp_meta_window_size✅ja4,tls_sni✅method,path,status_code✅ (uniquement en VM)header_order_signature✅ (uniquement en VM)
Différence avec les tests Docker
| Check | Docker | VM |
|---|---|---|
| L3/L4 (TTL, MSS, window) | ✅ | ✅ |
| TLS fingerprint (JA4, SNI) | ✅ | ✅ |
| L7 méthode HTTP | ❌ | ✅ |
| L7 path HTTP | ❌ | ✅ |
| status_code | ❌ | ✅ |
| header_order_signature | ❌ | ✅ |
Architecture de la VM
VM Rocky Linux 9 (KVM)
├── nginx + libssl.so.3 ← serveur web cible
├── ja4ebpf ← agent eBPF (natif, pas Docker)
│ ├── TC hook (eth0) ← capture L3/L4 + TLS ClientHello
│ ├── Uprobe SSL_read ← capture HTTP déchiffré
│ └── Tracepoint accept4 ← corrélation fd→IP (disponible !)
└── ClickHouse (Docker) ← base de données
Dépannage
vagrant up échoue : "Call to virConnectOpen failed"
sudo systemctl start libvirtd
sudo usermod -aG libvirt $USER # puis se reconnecter
Erreur "default pool not found"
sudo virsh pool-define-as default dir --target /var/lib/libvirt/images
sudo virsh pool-build default
sudo virsh pool-start default
sudo virsh pool-autostart default
ja4ebpf : "uprobe SSL_read" ne s'attache pas
# Vérifier le chemin libssl dans la VM
vagrant ssh -- 'ls -la /usr/lib64/libssl*'
# Si différent de /usr/lib64/libssl.so.3, modifier /tmp/ja4ebpf.yml