Files
ja4-platform/docs/architecture.md
Jacquin Antoine f0c8fe81c6 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>
2026-04-16 01:49:26 +02:00

19 KiB
Raw Blame History

Architecture

ja4-platform est un pipeline de sécurité qui capture le trafic réseau en temps réel, génère des empreintes TLS JA4/JA3, corrèle les handshakes TLS avec les requêtes HTTP, applique une détection d'anomalies par apprentissage automatique (ensemble triple voix), et présente les résultats dans un tableau de bord SOC. ClickHouse sert de magasin central reliant tous les services, organisé en deux bases de données distinctes.

Architecture système

+---------------------------------------------------+
|         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                    │
                    │                                                       │
                    │   ja4_logs                    ja4_processing           │
                    │  ┌────────────────┐          ┌────────────────────┐   │
                    │  │ http_logs_raw  │──(MV)──▶ │ agg_host_ip_ja4_1h│   │
                    │  │   ↓ mv_http_logs           │ agg_header_fp_1h │   │
                    │  │ http_logs      │──(MVs)──▶│ agg_path_seq_1h  │   │
                    │  └────────────────┘          │ agg_request_tm_1h│   │
                    │                               │ agg_ip_behavior_1h│  │
                    │                               │ agg_resource_cas_1h│ │
                    │                               │ ml_detected_anom. │  │
                    │                               │ ml_all_scores     │  │
                    │                               │ view_ai_features  │  │
                    │                               │ view_thesis_feat. │  │
                    │                               │ audit_logs, dicts │  │
                    │                               └────────────────────┘  │
                    └──────────┬──────────────────────────┬────────────────┘
                               │ SELECT                    │ SELECT / INSERT
                ┌──────────────┘                           └──────────────┐
                ▼                                                          ▼
     ┌───────────────────────┐                              ┌───────────────────────┐
     │  bot-detector          │                              │  dashboard             │
     │  Python 3.11           │                              │  FastAPI + Jinja2      │
     │                        │                              │  htmx + Chart.js       │
     │  Lit :                 │                              │  Tailwind CSS (CDN)    │
     │   view_ai_features_1h  │                              │                        │
     │   view_thesis_feat_1h  │                              │  53 routes (37 API     │
     │   view_ip_recurrence   │                              │   + 16 pages HTML)     │
     │  Écrit :               │                              │  16 templates Jinja2   │
     │   ml_detected_anomalies│                              │  16 pages SOC          │
     │   ml_all_scores        │                              │                        │
     │   fleet_detections     │                              │  Lit : ml_*, agg_*,    │
     │   ml_performance_metrics│                             │   http_logs, audit_logs│
     └───────────────────────┘                              └───────────────────────┘

Flux de données — 5 phases

Phase 1 — Capture

  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 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 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

  1. 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)

  1. 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)
    • Identification Anubis via dict_anubis_ip (IP_TRIE) et dict_anubis_asn (FLAT) — règles IP/CIDR + ASN uniquement, avec priorité COALESCE(IP, ASN)
  2. 6 vues matérialisées d'agrégation alimentent les tables ja4_processing.agg_* en fenêtres comportementales d'1 heure :

    • agg_host_ip_ja4_1h — Agrégations par (host, src_ip, ja4)
    • agg_header_fingerprint_1h — Empreintes d'en-têtes HTTP
    • agg_path_sequences_1h — Séquences de chemins (n-grams)
    • agg_request_timing_1h — Métriques de timing inter-requêtes
    • agg_ip_behavior_1h — Comportement réseau par IP
    • agg_resource_cascade_1h — Cascades de ressources
  3. view_ai_features_1h joint les tables d'agrégation et calcule ~63 features ML par tuple (src_ip, ja4, host).

Phase 4 — Détection

  1. bot-detector (Python 3.11, 16 modules) s'exécute en cycle de 5 minutes :
    • Pipeline bifurqué :
      • Complet (L3→L7, ~85 features, correlated=1) — trafic corrélé TCP+TLS+HTTP
      • Applicatif (L7 seulement, ~73 features, correlated=0) — trafic HTTP non corrélé
    • Ensemble triple voix :
      • Extended Isolation Forest (isotree) — scoreur non supervisé principal
      • NFEnsemble (PyTorch, Deep Ensemble M=5 TrafficNormalizingFlow/RealNVP) — NLL et incertitude épistémique
      • XGBoost — supervisé, entraîné sur les labels SOC (soc_feedback)
    • Score final : final = meta_learner.predict(eif_norm, ae_norm, xgb_prob, volume, correlated) avec fallback sur pondération linéaire fixe (1-β) × ((1-α) × eif_norm + α × ae_norm) + β × xgb_prob (α=0.30, β=0.20)
    • MetaLearner (MLP) entraîné automatiquement sur les labels accumulés (seuil: 1000 labels)
    • Seuil adaptatif par percentile, détection de dérive conceptuelle (ADWIN + KS + KL divergence)
    • Détection adversariale : incertitude inter-modèles NFEnsemble (nf_uncertainty > NF_UNCERTAINTY_THRESHOLD)
    • fleet_detector (PyTorch Geometric GraphSAGE) — graphe bipartite JA4×ASN, fleet_score, table fleet_detections
    • HDBSCAN — regroupement en campagnes d'attaque
    • Détection de navigateur — 6 axes multifactoriels (confiance ≥ 0.55 → LEGITIMATE_BROWSER)
    • ExIFFI — importance de features native à l'EIF (alternative à SHAP)
    • Explicabilité SHAP — contribution de chaque feature au score d'anomalie
    • Métriques de cycle (metrics.py) — table ml_performance_metrics, alertes calibration
    • Niveaux de menace : CRITICAL, HIGH, MEDIUM, LOW, NORMAL, LEGITIMATE_BROWSER, KNOWN_BOT, ANUBIS_DENY, ANUBIS_ALLOW

Phase 5 — Visualisation

  1. dashboard (FastAPI + Jinja2 + htmx + Chart.js + Tailwind CSS CDN) expose 53 routes (37 API JSON + 16 pages HTML) et 16 templates Jinja2 pour les analystes SOC :
    • Pages : overview, detections, scores, traffic, ip_detail, ja4_detail, cluster_detail, campaigns, features, models, classify, tactics, reflists, network, fleet, health

Matrice d'interaction des composants

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

Base ja4_logs

Table / Vue Écrit par Lu par
http_logs_raw ja4ebpf mv_http_logs (MV)
http_logs mv_http_logs (MV) mv_agg_* (6 MVs), dashboard
mv_http_logs — (MV automatique)

Base ja4_processing

Table / Vue Écrit par Lu par
agg_host_ip_ja4_1h mv_agg_host_ip_ja4_1h view_ai_features_1h, dashboard
agg_header_fingerprint_1h mv_agg_header_fingerprint_1h view_ai_features_1h, dashboard
agg_path_sequences_1h mv_agg_path_sequences_1h view_thesis_features_1h
agg_request_timing_1h mv_agg_request_timing_1h view_thesis_features_1h
agg_ip_behavior_1h mv_agg_ip_behavior_1h view_thesis_features_1h
agg_resource_cascade_1h mv_agg_resource_cascade_1h view_thesis_features_1h
ml_detected_anomalies bot-detector dashboard
ml_all_scores bot-detector dashboard
fleet_detections bot-detector (fleet.py) dashboard
ml_performance_metrics bot-detector (metrics.py) dashboard
soc_feedback dashboard (/api/classify) bot-detector
audit_logs dashboard dashboard
anubis_ip_rules fetch_rules.py dict_anubis_ip
anubis_asn_rules fetch_rules.py dict_anubis_asn
ref_bot_networks update-csv-data.sh dict_bot_ip
bot_ip update-csv-data.sh dict_bot_ip
bot_ja4 update-csv-data.sh dict_bot_ja4
view_ai_features_1h — (vue) bot-detector
view_ip_recurrence — (vue) bot-detector
view_thesis_features_1h — (vue) bot-detector
view_form_bruteforce_detected — (vue) dashboard
view_host_ip_ja4_rotation — (vue) dashboard
view_dashboard_user_agents — (vue) dashboard
view_dashboard_entities — (vue) dashboard
view_resource_cascade_1h — (vue) dashboard

Dictionnaires (8)

Dictionnaire Layout Source Utilisation
dict_iplocate_asn IP_TRIE Fichier CSV Géolocalisation IP → ASN
dict_bot_ip IP_TRIE Table bot_ip IPs de bots connues
dict_bot_ja4 COMPLEX_KEY_HASHED Table bot_ja4 Signatures JA4 de bots
dict_browser_ja4 COMPLEX_KEY_HASHED Table (CSV) Signatures JA4 de navigateurs
dict_browser_h2 COMPLEX_KEY_HASHED Table (CSV) Fingerprints HTTP/2 SETTINGS par navigateur
dict_asn_reputation HASHED Fichier CSV Réputation ASN (isp/datacenter/hosting/cdn)
dict_anubis_ip IP_TRIE Table anubis_ip_rules Règles Anubis IP/CIDR
dict_anubis_asn FLAT Table anubis_asn_rules Règles Anubis ASN

Algorithme de corrélation

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.
  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)

view_ai_features_1h ──┐                    ┌─── ml_detected_anomalies
view_thesis_feat_1h ──┤   ┌────────────┐   │
view_ip_recurrence ───┤   │ Pré-       │   │
                      ├──▶│ traitement │──▶│ Bifurcation :
                      │   │ + filtrage │   │  ├── Complet   (correlated=1, ~85 feat.)
                      │   └────────────┘   │  └── Applicatif(correlated=0, ~73 feat.)
                      │                    │
                      │   ┌────────────┐   │  Pour chaque branche :
                      │   │ Ensemble   │   │   ├── Extended Isolation Forest (EIF)
                      │   │ triple     │──▶│   ├── NFEnsemble (M=5 NF, PyTorch)
                      │   │ voix       │   │   └── XGBoost (supervisé)
                      │   └────────────┘   │
                      │                    │  Score = MetaLearner(eif, ae, xgb) ou
                      │                    │          (1-β)×((1-α)×EIF + α×AE) + β×XGB
                      │   ┌────────────┐   │
                      │   │ Post-      │   ├─── ml_all_scores
                      └──▶│ traitement │──▶│
                          │ HDBSCAN    │   │  Niveaux : CRITICAL / HIGH / MEDIUM /
                          │ fleet.py   │   │   LOW / NORMAL / LEGITIMATE_BROWSER /
                          │ Browser 6ax│   │   KNOWN_BOT / ANUBIS_DENY / ANUBIS_ALLOW
                          │ ExIFFI+SHAP│   │
                          │ metrics.py │   ├─── fleet_detections
                          └────────────┘   └─── ml_performance_metrics

Référence des empreintes JA4/JA3

JA4

Format moderne de fingerprinting TLS (successeur de JA3) :

t{TLS_VER}{SNI}{CIPHER_COUNT}{EXT_COUNT}_{CIPHER_HASH}_{EXT_HASH}

Exemple : t13d1516h2_8daaf6152771_b0da82dd1658

  • Préfixe t = TLS, suivi de la version (13 = TLS 1.3)
  • d = SNI présent, i = SNI absent
  • Nombre de cipher suites et nombre d'extensions
  • Hash SHA-256 tronqué des cipher suites et extensions triées

JA3

Format original de fingerprinting TLS :

{TLS_VER},{CIPHERS},{EXTENSIONS},{ELLIPTIC_CURVES},{EC_POINT_FORMATS}

Le ja3_hash est le hash MD5 de la chaîne JA3.

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 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 — NFEnsemble Python 3.11 + PyTorch
Détection ML — Supervisé Python 3.11 + XGBoost
Détection ML — Ensemble Python 3.11 + MetaLearner (MLP)
Clustering de campagnes HDBSCAN + NetworkX (fleet detection)
Explicabilité SHAP + ExIFFI
Backend dashboard FastAPI + Jinja2 (Python 3.11)
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 PerfEventArray eBPF (kernel → userspace Go)
Workspace Go go.work (Go 1.24.6)

Fichiers de schéma SQL (13)

shared/clickhouse/
├── 00_database.sql           # Création des bases ja4_logs + ja4_processing
├── 01_raw_tables.sql         # ja4_logs.http_logs_raw (TTL 2 heures)
├── 02_dictionaries.sql       # dict_iplocate_asn, ref_bot_networks, bot_ip, bot_ja4
├── 03_anubis_tables.sql      # anubis_ip_rules, anubis_asn_rules + 2 dictionnaires
├── 04_mv_http_logs.sql       # ja4_logs.http_logs + mv_http_logs (JSON → colonnes)
├── 05_aggregation_tables.sql # agg_host_ip_ja4_1h, agg_header_fingerprint_1h + MVs + 4 dicts
├── 06_ml_tables.sql          # ml_detected_anomalies, ml_all_scores, view_ip_recurrence
├── 07_ai_features_view.sql   # view_ai_features_1h (feature engineering ~63 features)
├── 08_users.sql              # Utilisateurs data_writer + analyst
├── 09_audit_table.sql        # audit_logs (trace SOC, TTL 90 jours)
├── 10_perf_indexes.sql       # Index et projections de performance
├── 11_views.sql              # Vues métier du dashboard (4 vues)
├── 12_thesis_features.sql    # agg_path_sequences, agg_request_timing, agg_ip_behavior,
│                             #   agg_resource_cascade + MVs + view_thesis_features_1h
│                             #   + view_resource_cascade_1h
└── deploy_schema.sh          # Script de déploiement automatisé (substitution env vars)