fix(ja4ebpf): split bpf2go generate into Ja4Tc + Ja4Ssl, fix RPM systemd-rpm-macros

- Use two separate //go:generate directives (Ja4Tc for tc_capture.c, Ja4Ssl
  for uprobe_ssl.c) to avoid duplicate LICENSE symbol and multi-file clang issue
- Update loader.go to hold tcObjs/sslObjs separately with correct field names:
  UprobeSslSetFd, UprobeSslReadEntry, UretprobeSslReadExit,
  KprobeAccept4Entry, KretprobeAccept4Exit
- Add systemd-rpm-macros to all three RPM build stages (el8/el9/el10)
  so that %{_unitdir} macro resolves correctly
- RPMs now build successfully for el8, el9, el10

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
toto
2026-04-11 23:21:11 +02:00
parent a1e4c1dad5
commit 3b047b680a
155 changed files with 197011 additions and 599 deletions

View File

@ -5,30 +5,25 @@ ja4-platform est un pipeline de sécurité qui capture le trafic réseau en temp
## Architecture système
```
┌─────────────────────────────────────────────────────────────────────────────────────┐
Serveur Linux cible (Apache) │
┌─────────────────┐ HTTP req ┌───────────────────────┐ │
│ │ Client │────────────▶│ Apache HTTPD
(navigateur / + mod-reqin-log (C) │
│ │ bot) │ └───────────┬───────────┘
│ │ │ │ JSON / UNIX DGRAM
│ /var/run/logcorrelator/http.socket │
│ ▼ │
│ │ │ TLS CH ┌──────────────────────────────────────┐
│ │ │────────────▶│ sentinel (Go · libpcap) │
└─────────────────┘ (pcap) │ → JA4/JA3 fingerprints │ │
└───────────┬──────────────────────────┘ │
│ JSON / UNIX DGRAM
│ │ /var/run/logcorrelator/network.socket│
│ ▼
┌───────────────────────────────┐
│ │ correlator (Go · hex. arch) │ │
│ │ join src_ip:src_port + TTL │ │
│ └───────────┬───────────────────┘ │
│ │ │
└───────────────────────────────────────────────┼─────────────────────────────────────┘
│ INSERT (Native TCP :9000)
+---------------------------------------------------+
| Serveur Linux cible (Apache/Nginx/...) |
| |
| Client --HTTPS (443)--> [Serveur web] |
| Client --HTTP (80)---> [Serveur web] |
| |
| +-----------------+ |
| | ja4ebpf | (s'exécute sur le meme host)|
| | (eBPF CO-RE) | |
| | TC ingress |<-- L3/L4/L5 (SYN, TLS CH) |
| | uprobe SSL_read|<-- L7 HTTPS (déchiffré) |
| | kprobe tcp_recv|<-- L7 HTTP port 80/8080 |
| | 256-shard mgr | corrélation src_ip:src_port |
| +--------+--------+ |
| | |
+-----------|-----------------------------------+ |
| INSERT batch | |
v v
INSERT (Native TCP :9000)
┌───────────────────────────────────────────────────────┐
│ ClickHouse 24.8 │
@ -71,15 +66,17 @@ ja4-platform est un pipeline de sécurité qui capture le trafic réseau en temp
### Phase 1 — Capture
1. **mod-reqin-log** (module Apache C11) intercepte chaque requête HTTP dans le hook `post_read_request`. Il sérialise method, path, headers, client IP/port en JSON et envoie le datagramme vers `/var/run/logcorrelator/http.socket`.
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. **sentinel** (démon Go) capture les paquets TLS ClientHello via libpcap sur les ports configurés (défaut : 443, 8443). Il extrait les métadonnées IP/TCP, génère les empreintes JA4 et JA3, et envoie le résultat en JSON vers `/var/run/logcorrelator/network.socket`.
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.
### Phase 2 — Corrélation
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. **correlator** (démon Go, architecture hexagonale) écoute les deux sockets Unix. Il met en tampon les événements entrants et les corrèle par `src_ip:src_port` dans une fenêtre temporelle configurable (défaut : 10 s). Le mode `one_to_many` (Keep-Alive) permet de réutiliser un seul handshake TLS (source B) pour plusieurs requêtes HTTP (source A). Les événements corrélés fusionnent les champs HTTP + TLS en un objet `CorrelatedLog` JSON, inséré dans **`ja4_logs.http_logs_raw`**.
### Phase 2 — Corrélation en mémoire
### Phase 3 — Enrichissement (ClickHouse)
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.
### Phase 3 — Enrichissement### Phase 3 — Enrichissement (ClickHouse)
4. **mv_http_logs** (vue matérialisée) transforme le JSON de `http_logs_raw` en la table structurée `ja4_logs.http_logs`, enrichissant chaque ligne avec :
- Données ASN via `dict_iplocate_asn` (IP_TRIE)
@ -123,14 +120,12 @@ ja4-platform est un pipeline de sécurité qui capture le trafic réseau en temp
## Matrice d'interaction des composants
| De ↓ \ Vers → | mod-reqin-log | sentinel | correlator | ClickHouse | bot-detector | dashboard |
|----------------|:---:|:---:|:---:|:---:|:---:|:---:|
| **mod-reqin-log** | — | — | UNIX DGRAM (source A) | — | — | — |
| **sentinel** | — | — | UNIX DGRAM (source B) | — | — | — |
| **correlator** | — | — | — | Native TCP :9000 (INSERT) | — | — |
| **ClickHouse** | — | — | — | MVs internes | — | — |
| **bot-detector** | — | — | — | HTTP :8123 (SELECT/INSERT) | — | — |
| **dashboard** | — | — | — | HTTP :8123 (SELECT/INSERT) | — | — |
| De ↓ \ Vers → | ja4ebpf | ClickHouse | bot-detector | dashboard |
|----------------|:---:|:---:|:---:|:---:|
| **ja4ebpf** | — | Native TCP :9000 (INSERT batch) | — | — |
| **ClickHouse** | — | MVs internes | — | — |
| **bot-detector** | — | HTTP :8123 (SELECT/INSERT) | — | — |
| **dashboard** | — | HTTP :8123 (SELECT/INSERT) | — | — |
## Propriété des tables ClickHouse
@ -138,7 +133,7 @@ ja4-platform est un pipeline de sécurité qui capture le trafic réseau en temp
| Table / Vue | Écrit par | Lu par |
|-------------|-----------|--------|
| `http_logs_raw` | correlator | mv_http_logs (MV) |
| `http_logs_raw` | ja4ebpf | mv_http_logs (MV) |
| `http_logs` | mv_http_logs (MV) | mv_agg_* (6 MVs), dashboard |
| `mv_http_logs` | — (MV automatique) | — |
@ -187,17 +182,23 @@ ja4-platform est un pipeline de sécurité qui capture le trafic réseau en temp
## Algorithme de corrélation
Le correlator joint les événements HTTP (source A) avec les événements TLS/réseau (source B) via une corrélation à deux clés :
**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 :
1. **Clé** : `src_ip + src_port` — l'IP source et le port éphémère du client identifient une connexion TCP de manière unique.
2. **Fenêtre temporelle** : Les événements doivent arriver dans la fenêtre configurée (défaut 10 secondes).
3. **Mode de correspondance** :
- `one_to_one` : Chaque événement B correspond à un seul événement A (consommé après correspondance).
- `one_to_many` (défaut, Keep-Alive) : Un seul B (handshake TLS) peut correspondre à plusieurs A (requêtes HTTP) sur la même connexion. Le B possède un TTL configurable (défaut 120 s) réinitialisé à chaque correspondance.
4. **Gestion des orphelins** : Les événements A sans correspondance sont émis après un délai configurable (défaut 500 ms) avec `correlated=false` et `orphan_side=A`.
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.
3. **Gestion Keep-Alive** : Un seul état TLS/L4 est conservé par connexion TCP et partagé entre toutes les requêtes HTTP successives. Compteur `maxkeepalives` incrémenté à chaque requête.
4. **Magic Bytes dispatcher** : Les premiers octets du buffer L7 déterminent le protocole :
- `PRI * HTTP/2.0\r\n` → parser HTTP/2 (SETTINGS + WINDOW_UPDATE + pseudo-headers)
- `GET `, `POST `, `HEAD `, etc. → parser HTTP/1.1
- Autre → `ProtoUnknown` (bruit TLS ou protocole non supporté)
5. **Orphelins** : Événements L7 sans correspondance L3/L4 dans les 500 ms → `correlated=0`.
6. **Slowloris** : Connexion TCP sans requête HTTP complète après 10 s → export partiel.
7. **GC** : Goroutine dédiée, itération sur tous les shards toutes les 100 ms.
La sortie est insérée dans **`ja4_logs.http_logs_raw`** (base `ja4_logs`), pas dans `ja4_processing`.
## Pipeline ML
## Pipeline ML — bot-detector (détail)
```
@ -253,15 +254,15 @@ Format original de fingerprinting TLS :
Le `ja3_hash` est le hash MD5 de la chaîne JA3.
Les deux empreintes sont générées par sentinel à partir du payload TLS ClientHello.
Les deux empreintes sont générées par **ja4ebpf** (espace utilisateur Go) à partir du payload TLS ClientHello capturé par le TC ingress hook.
## Stack technologique
| Composant | Technologie |
|-----------|-------------|
| Capture de paquets | Go 1.24.6 + libpcap (gopacket) |
| Logging HTTP | Module Apache C11 (APR, `apxs`) |
| Corrélation d'événements | Go 1.24.6 (architecture hexagonale) |
| Capture réseau (L3/L4/L5) | Go 1.24.6 + eBPF CO-RE (TC ingress, cilium/ebpf) |
| Capture applicative (L7) | eBPF uprobe SSL_read + kprobe tcp_recvmsg |
| Corrélation en mémoire | Go 1.24.6 (256-shard manager, goroutines) |
| Détection ML — EIF | Python 3.11 + isotree |
| Détection ML — Autoencoder | Python 3.11 + PyTorch |
| Détection ML — Supervisé | Python 3.11 + XGBoost |
@ -272,7 +273,7 @@ Les deux empreintes sont générées par sentinel à partir du payload TLS Clien
| 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 | Sockets UNIX datagramme |
| IPC | RingBuffers eBPF (kernel → userspace Go) |
| Workspace Go | `go.work` (Go 1.24.6) |
## Fichiers de schéma SQL (13)