feat(ja4ebpf): add multi-interface TC, LPM_TRIE ignore_src, unit tests, and fix bugs

- Add multi-interface TC attachment (default "any" = all UP interfaces)
- Add BPF LPM_TRIE map ignored_src for kernel-side CIDR filtering
- Add userspace ignore_src filtering for SSL/accept4 path via net.IPNet.Contains()
- Add AcceptCache for fd→SessionKey correlation with TTL and Close()
- Add 5 test files covering writer, procutil, dispatcher, accept_cache, and cmd
- Fix formatTCPOptions infinite loop on EOL (case 0 break→return)
- Fix pseudoOrderToShort panic on empty slice (negative cap)
- Fix AcceptCache goroutine leak (add done channel + Close())
- Update config.yml.example with interfaces, listen_ports, ignore_src
- Rewrite docs/services/ja4ebpf.md (was massively stale: XDP, RingBuffer, etc.)
- Fix stale XDP/RingBuffer references in docs/architecture.md, thesis, tls.go

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jacquin Antoine
2026-04-16 01:49:26 +02:00
parent fd84aebc44
commit f0c8fe81c6
20 changed files with 3053 additions and 1261 deletions

View File

@ -68,13 +68,13 @@ INSERT (Native TCP :9000)
1. **ja4ebpf TC ingress hook** capture les paquets réseau bruts. Pour chaque TCP SYN : `src_ip`, `src_port`, `ttl`, `window_size`, `mss`, `window_scale`, `df_bit`. Pour chaque TLS ClientHello : décodage du payload pour extraire `ciphers`, `extensions`, `elliptic_curves`, `alpn`, `sni` (calcul du hash JA4/JA3 en espace utilisateur Go).
2. **ja4ebpf uprobe SSL_read** accroche `SSL_read` dans la bibliothèque OpenSSL/BoringSSL du serveur web. Les données déchiffrées sont écrites dans un RingBuffer eBPF. Un kprobe sur `accept4` fournit la correspondance `fd → src_ip:src_port` pour annoter chaque buffer L7.
2. **ja4ebpf uprobes SSL_read/SSL_write** sattachent à `SSL_read` et `SSL_write` dans la bibliothèque OpenSSL/BoringSSL du serveur web. Les données déchiffrées sont écrites dans un PerfEventArray eBPF. Des tracepoints sur `accept4` fournissent la correspondance `fd → src_ip:src_port` pour annoter chaque buffer L7.
3. **ja4ebpf kprobe tcp_recvmsg** (HTTP port 80/8080) intercepte le payload TCP avant consommation par le serveur pour les connexions non chiffrées.
3. **ja4ebpf TC ingress HTTP plain** (port 80/8080) capture les payloads TCP en clair directement depuis le hook TC ingress pour les connexions non chiffrées.
### Phase 2 — Corrélation en mémoire
4. **ja4ebpf 256-shard manager** (espace utilisateur Go) consomme les trois RingBuffers eBPF via des goroutines dédiées. Les événements L3/L4/L5 et L7 sont corrélés par `src_ip:src_port` dans une table de sessions shardée (256 shards, mutex par shard). Timeout orphelin : 500 ms (émission avec `correlated=0`). Détection Slowloris : émission partielle après 10 s. GC des sessions fantômes : toutes les 100 ms. Le dispatcher magic bytes route vers le parser HTTP/1.1 ou HTTP/2. Pour HTTP/2, la première frame SETTINGS + WINDOW_UPDATE est décodée pour le fingerprinting passif. Lobjet corrélé est inséré dans **`ja4_logs.http_logs_raw`** par batch.
4. **ja4ebpf 256-shard manager** (espace utilisateur Go) consomme les cinq PerfEventArray eBPF via des goroutines dédiées. Les événements L3/L4/L5 et L7 sont corrélés par `src_ip:src_port` dans une table de sessions shardée (256 shards, mutex par shard). Timeout orphelin : 500 ms (émission avec `correlated=0`). Détection Slowloris : émission partielle après 10 s. GC des sessions fantômes : toutes les 100 ms. Le dispatcher magic bytes route vers le parser HTTP/1.1 ou HTTP/2. Pour HTTP/2, la première frame SETTINGS + WINDOW_UPDATE est décodée pour le fingerprinting passif. Lobjet corrélé est inséré dans **`ja4_logs.http_logs_raw`** par batch.
### Phase 3 — Enrichissement### Phase 3 — Enrichissement (ClickHouse)
@ -183,7 +183,7 @@ INSERT (Native TCP :9000)
## Algorithme de corrélation
**ja4ebpf** corrèle les événements L3/L4/L5 (RingBuffer TC ingress) avec les événements L7 (RingBuffer uprobe) via une table de sessions en mémoire :
**ja4ebpf** corrèle les événements L3/L4/L5 (PerfEventArray TC ingress) avec les événements L7 (PerfEventArray uprobe) via une table de sessions en mémoire :
1. **Clé** : `src_ip + src_port` — lIP source et le port éphémère identifient une connexion TCP de manière unique.
2. **Sharding** : 256 shards (`src_port % 256`), chacun protégé par un `sync.Mutex`. Réduit la contention sous fort trafic.
@ -274,7 +274,7 @@ Les deux empreintes sont générées par **ja4ebpf** (espace utilisateur Go) à
| Frontend dashboard | htmx + Chart.js + ECharts + Tailwind CSS (CDN) |
| Magasin de données | ClickHouse 24.8 (dual-database) |
| Déploiement | systemd, Docker, RPM (Rocky 8/9/10) |
| IPC | RingBuffers eBPF (kernel → userspace Go) |
| IPC | PerfEventArray eBPF (kernel → userspace Go) |
| Workspace Go | `go.work` (Go 1.24.6) |
## Fichiers de schéma SQL (13)