11 KiB
Architecture de détection — logcorrelator
Vue d'ensemble
Le système de détection est composé de trois couches qui s'enchaînent en pipeline :
Trafic HTTP/TLS capturé
│
▼
┌───────────────────┐
│ ClickHouse │ Stockage, agrégation, vues heuristiques
│ (SQL pipeline) │
└────────┬──────────┘
│
▼
┌───────────────────┐
│ bot_detector.py │ Modèle IA (Isolation Forest, cycle 5 min)
│ (Python / ML) │
└────────┬──────────┘
│
▼
┌───────────────────┐
│ ml_detected_ │ Table de résultats (ReplacingMergeTree)
│ anomalies │
└───────────────────┘
1. Ingestion des logs (http_logs_raw → http_logs)
Les logs bruts arrivent en JSON dans la table http_logs_raw. Une vue matérialisée (mv_http_logs) les parse en temps réel et alimente la table http_logs, qui contient les champs structurés suivants :
| Catégorie | Champs clés |
|---|---|
| Réseau | src_ip, src_port, dst_ip, dst_port |
| Enrichissement | src_asn, src_country_code, src_as_name (via dictionnaire IPLocate) |
| HTTP | method, host, path, query, http_version |
| Corrélation | correlated, orphan_side, conn_id, keepalives |
| Métadonnées IP | ip_meta_ttl, ip_meta_id, ip_meta_df, ip_meta_total_length |
| Métadonnées TCP | tcp_meta_window_size, tcp_meta_mss, tcp_meta_window_scale, tcp_meta_options |
| TLS / Fingerprint | tls_version, tls_sni, tls_alpn, ja3, ja3_hash, ja4 |
| En-têtes HTTP | header_user_agent, header_sec_ch_ua*, header_sec_fetch_*, … |
L'enrichissement IP est réalisé via le dictionnaire dict_iplocate_asn (fichier CSV chargé en mémoire, rechargé toutes les 1-2 heures).
2. Agrégation comportementale (fenêtre horaire)
Deux tables d'agrégation AggregatingMergeTree sont alimentées en continu par des vues matérialisées.
2.1 agg_host_ip_ja4_1h — Comportement réseau & applicatif
Agrège par triplet (window_start, src_ip, ja4, host) toutes les heures :
| Métrique agrégée | Signification |
|---|---|
hits |
Nombre total de requêtes |
count_post |
Requêtes POST |
uniq_paths |
Chemins distincts visités |
uniq_query_params |
Paramètres de query distincts |
unique_src_ports |
Ports sources distincts |
unique_conn_id |
Connexions TCP distinctes |
max_keepalives |
Réutilisation maximale d'une connexion |
orphan_count |
Requêtes sans corrélation TCP complète |
ip_id_zero_count |
Paquets avec IP ID = 0 (spoofing potentiel) |
tcp_fp_raw |
Hash de l'empreinte TCP (window, MSS, scale, options) |
tcp_jitter_variance |
Variance du délai SYN→ClientHello (jitter TLS) |
total_ip_length_var |
Variance de la taille des paquets IP |
mss_1460_count |
Requêtes avec MSS = 1460 (signature Ethernet/desktop) |
2.2 agg_header_fingerprint_1h — Empreinte des en-têtes HTTP
Agrège par (window_start, src_ip) :
| Métrique | Signification |
|---|---|
header_order_hash |
Hash de l'ordre des en-têtes (fingerprint JA4H) |
header_count |
Nombre d'en-têtes distincts |
has_accept_language |
Présence de Accept-Language |
has_cookie |
Présence de Cookie |
has_referer |
Présence de Referer |
modern_browser_score |
Score 0/50/100 selon présence UA et Sec-CH-UA |
ua_ch_mismatch |
Incohérence entre User-Agent et Sec-CH-UA-Platform |
sec_fetch_mode/dest |
Contexte de navigation déclaré |
3. Exclusions (listes blanches)
Avant toute analyse, deux tables permettent d'exclure les robots légitimes connus :
bot_ip(fichierbot_ip.csv) — IPs à ignorer (crawlers, monitoring…)bot_ja4(fichierbot_ja4.csv) — Fingerprints JA4 à ignorerref_bot_networks— Réseaux CIDR IPv4/IPv6 catégorisés (légitimes ou malveillants)
Ces exclusions sont appliquées dans la vue view_ai_features_1h.
4. Vue IA : view_ai_features_1h
Cette vue consolidée sur 24 heures glissantes calcule les 28 features passées au modèle ML. Elle joint les deux tables d'agrégation et dérive les métriques suivantes :
| Feature | Calcul | Signal détecté |
|---|---|---|
hit_velocity |
hits / durée_en_secondes |
Volume de requêtes anormalement élevé |
fuzzing_index |
uniq_query_params / uniq_paths |
Exploration paramétrique (fuzzing) |
post_ratio |
count_post / hits |
Soumission de formulaires en masse |
port_exhaustion_ratio |
unique_src_ports / hits |
Rotation de ports (scan) |
orphan_ratio |
orphan_count / hits |
Requêtes sans handshake complet |
ip_id_zero_ratio |
ip_id_zero_count / hits |
Spoofing d'adresse IP |
multiplexing_efficiency |
hits / unique_conn_id |
Réutilisation des connexions (H2/H3) |
true_window_size |
tcp_win * 2^tcp_scale |
Taille réelle de la fenêtre TCP |
window_mss_ratio |
tcp_win / tcp_mss |
Cohérence TCP stack |
tcp_jitter_variance |
Variance SYN→ClientHello | Irrégularité du timing TLS |
alpn_http_mismatch |
ALPN=h2 mais HTTP/1.1 | Négociation TLS mensongère |
is_alpn_missing |
ALPN absent ou 00 |
Client non-standard |
sni_host_mismatch |
SNI ≠ Host header | Proxy transparent / bot |
mss_mobile_mismatch |
MSS=1460 + score navigateur élevé | Client mobile simulé depuis desktop |
is_fake_navigation |
sec_fetch_mode=navigate mais sec_fetch_dest≠document |
Navigation simulée |
tcp_shared_count |
Nb d'IPs partageant la même empreinte TCP | Infrastructure partagée / botnet |
header_order_shared_count |
Nb d'IPs partageant le même ordre d'en-têtes | Outil automatisé commun |
5. Modèle IA : Isolation Forest (bot_detector.py)
Cycle d'exécution
Le service tourne en boucle avec un cycle de 5 minutes :
fetch_and_analyze()
│
├─ Requête SELECT * FROM view_ai_features_1h
│
├─ Nettoyage des données (fillna)
│
├─ Dual-Model routing :
│ ├─ [Complet] correlated=1 → 23 features (réseau + TLS + headers)
│ └─ [Applicatif] correlated=0 → 19 features (headers + comportement)
│
└─ INSERT INTO ml_detected_anomalies
Paramétrage du modèle
| Paramètre | Valeur | Signification |
|---|---|---|
n_estimators |
200 | Nombre d'arbres d'isolation |
contamination |
0.2% | Proportion de bots attendue dans le trafic |
seuil de score |
< -0.05 | Score en dessous duquel une session est marquée anomalie |
volume minimum |
500 sessions | En dessous, le modèle est ignoré (trop peu de données) |
Dual-Model routing
Le trafic est séparé en deux populations selon le champ correlated :
- Modèle Complet (
correlated=1) : la corrélation TCP↔HTTP est disponible → les features réseau (TTL, jitter TLS, ALPN, SNI) sont fiables et ajoutées à l'analyse. - Modèle Applicatif (
correlated=0) : seule la couche HTTP est disponible → l'analyse se concentre sur le comportement applicatif (headers, paths, POST ratio…).
6. Vues heuristiques statiques
En parallèle du modèle IA, cinq vues SQL fournissent des détections déterministes sans ML, sur fenêtre 24h :
| Vue | Règle de détection |
|---|---|
view_host_ip_ja4_rotation |
IP avec ≥ 5 fingerprints JA4 distincts et > 100 requêtes → rotation d'identité |
view_host_ja4_anomalies |
Fingerprint JA4 vu depuis ≥ 20 IPs sur ≥ 3 hôtes → outil de scan distribué |
view_form_bruteforce_detected |
≥ 10 query params distincts et ≥ 20 hits → brute-force de formulaire |
view_alpn_mismatch_detected |
HTTP/1.1 avec ALPN h2 ou h3 et ≥ 10 hits → négociation TLS frauduleuse |
view_tcp_spoofing_detected |
TTL ≤ 64 avec User-Agent Windows ou iPhone → empreinte OS incohérente |
7. Résultats : ml_detected_anomalies
Les anomalies détectées sont stockées dans une table ReplacingMergeTree(detected_at) avec TTL 30 jours. La clé d'ordre (src_ip, ja4, host) garantit que chaque triplet ne conserve que la détection la plus récente (dédoublonnage automatique).
Chaque enregistrement contient :
- Les scores et features ayant conduit à la détection
- Le champ
reason: texte lisible avec score, vélocité, et indice de fuzzing - Le champ
is_headless: déduit de l'incohérencesec_fetch_mode
8. Schéma de flux complet
┌─────────────────────────────────────┐
│ http_logs_raw (JSON) │
└──────────────┬──────────────────────┘
│ mv_http_logs (MV)
▼
┌─────────────────────────────────────┐
│ http_logs (parsée) │
└────────┬──────────────┬─────────────┘
│ │
mv_agg_host_ip_ja4 │ │ mv_agg_header_fingerprint
▼ ▼
┌──────────────────┐ ┌──────────────────────────┐
│ agg_host_ip_ja4 │ │ agg_header_fingerprint │
│ _1h │ │ _1h │
└────────┬─────────┘ └──────────┬──────────────┘
│ │
└──────────┬─────────────┘
│ view_ai_features_1h (JOIN + calculs)
▼
┌─────────────────────────────────────┐
│ bot_detector.py (Isolation Forest) │
│ Cycle : 5 min | Fenêtre : 24h │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ ml_detected_anomalies │
│ (ReplacingMergeTree, TTL 30j) │
└─────────────────────────────────────┘