docs: synchronize thesis with codebase — browser_matcher, fleet detection, module counts

Update THESIS_HTTP_Traffic_Detection.md to reflect actual implementation state:
- Module count: 12 → 14 modules, 2 912 → 3 700 lines
- browser_matcher: [partiel] → [impl.] (all 7 scoring dimensions, Chrome/Firefox/Safari signatures)
- Fleet detection §5.2: HDBSCAN → Louvain with connected components fallback
- §3.9.1 H2 tables: update Firefox/Safari pseudo-header order to real captured values
- §7 conclusion: 96/0/0 features (all implemented, zero partial)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jacquin Antoine
2026-04-13 01:38:57 +02:00
parent 842b98d13a
commit 64dada980f

View File

@ -7,7 +7,7 @@
## Résumé
Ce document présente une architecture complète de détection et classification du trafic HTTP malveillant, positionnée à la frontière des générations 3 et 4 de défenses applicatives. Le système exploite 96 features organisées en 8 familles couvrant les couches réseau L3 à L7, corrélant des signaux TCP, TLS et HTTP en un vecteur unifié par session. La détection repose sur un ensemble triple-voix combinant un Extended Isolation Forest (EIF), un autoencodeur (AE) et XGBoost, fusionnés par un MetaLearner à régression logistique activé à partir de 1 000 étiquettes accumulées. L'explicabilité est assurée par ExIFFI (nativement pour EIF) et SHAP TreeExplainer (pour XGBoost). Le clustering de campagnes est réalisé par HDBSCAN dans l'espace latent 16 dimensions de l'autoencodeur, et la détection de flottes coordonnées par graphes bipartis via NetworkX. Le fingerprinting HTTP/2 passif — extraction des trames SETTINGS, WINDOW_UPDATE et de l'ordre des pseudo-headers côté serveur — constitue un signal inédit difficile à contourner sans implémenter une pile HTTP/2 complète fidèle à un navigateur cible. L'infrastructure repose sur 12 modules Python (2 912 lignes), une base ClickHouse à double schéma (ja4_logs bruts TTL 2 h, ja4_processing agrégés TTL 7 j), des cycles d'analyse de 300 secondes, et traite en production plus de 3 millions de logs, environ 34 000 sessions par cycle, avec approximativement 777 anomalies détectées par cycle (≈ 2,3 %). Les mots-clés couvrent : fingerprinting réseau, JA4+, HTTP/2 fingerprinting passif, détection de bots, Extended Isolation Forest, ExIFFI, autoencodeurs, méta-learner, ensemble hybride, corrélation TCP/TLS/HTTP, WAF, classification de trafic, apprentissage semi-supervisé, clustering HDBSCAN.
Ce document présente une architecture complète de détection et classification du trafic HTTP malveillant, positionnée à la frontière des générations 3 et 4 de défenses applicatives. Le système exploite 96 features organisées en 8 familles couvrant les couches réseau L3 à L7, corrélant des signaux TCP, TLS et HTTP en un vecteur unifié par session. La détection repose sur un ensemble triple-voix combinant un Extended Isolation Forest (EIF), un autoencodeur (AE) et XGBoost, fusionnés par un MetaLearner à régression logistique activé à partir de 1 000 étiquettes accumulées. L'explicabilité est assurée par ExIFFI (nativement pour EIF) et SHAP TreeExplainer (pour XGBoost). Le clustering de campagnes est réalisé par HDBSCAN dans l'espace latent 16 dimensions de l'autoencodeur, et la détection de flottes coordonnées par graphes bipartis via NetworkX. Le fingerprinting HTTP/2 passif — extraction des trames SETTINGS, WINDOW_UPDATE et de l'ordre des pseudo-headers côté serveur — constitue un signal inédit difficile à contourner sans implémenter une pile HTTP/2 complète fidèle à un navigateur cible. L'infrastructure repose sur 14 modules Python (3 700 lignes), une base ClickHouse à double schéma (ja4_logs bruts TTL 2 h, ja4_processing agrégés TTL 7 j), des cycles d'analyse de 300 secondes, et traite en production plus de 3 millions de logs, environ 34 000 sessions par cycle, avec approximativement 777 anomalies détectées par cycle (≈ 2,3 %). Les mots-clés couvrent : fingerprinting réseau, JA4+, HTTP/2 fingerprinting passif, détection de bots, Extended Isolation Forest, ExIFFI, autoencodeurs, méta-learner, ensemble hybride, corrélation TCP/TLS/HTTP, WAF, classification de trafic, apprentissage semi-supervisé, clustering HDBSCAN.
**Mots-clés** : fingerprinting réseau, JA4+, HTTP/2 fingerprinting, détection de bots, Extended Isolation Forest, ExIFFI, autoencoders, méta-learner, ensemble hybride, corrélation TCP/TLS/HTTP, WAF, classification de trafic, apprentissage semi-supervisé, clustering HDBSCAN
@ -847,8 +847,8 @@ httpcloak est un outil d'évasion qui tente d'imiter l'empreinte TLS de Chrome.
┌─────────▼─────────────────────────────┐
│ bot_detector │
│ (12 modules Python, │
2912 lignes) │
│ (14 modules Python, │
3 700 lignes) │
│ │
│ Cycle 300s: │
│ ┌──────────────────────────────────┐ │
@ -1084,9 +1084,9 @@ La valeur `percentile_5` du historique des scores négatifs (anomalies confirmé
## 3.9 Browser Signature Detection (browser_matcher)
`[partiel]` **Statut global : capture H2 implémentée, module de scoring à compléter**
`[impl.]` **Statut global : capture H2 et scoring entièrement implémentés**
Le système `browser_confidence` à 6 axes 3.8) fournit un score agrégé utile comme feature ML, mais sa logique de bypass (seuil 0,55) manque de précision face aux outils d'évasion modernes notamment `httpcloak`, `curl_cffi` et `python-requests` patchés qui reproduisent les couches TLS et HTTP/1.1 sans reproduire les subtilités HTTP/2. `browser_matcher` adresse cette lacune en implémentant une correspondance structurée par famille de navigateur, fondée sur l'empreinte passive du protocole HTTP/2.
Le système `browser_confidence` à 6 axes 3.8) fournit un score agrégé utile comme feature ML, mais sa logique de bypass (seuil 0,55) manque de précision face aux outils d'évasion modernes notamment `httpcloak`, `curl_cffi` et `python-requests` patchés qui reproduisent les couches TLS et HTTP/1.1 sans reproduire les subtilités HTTP/2. `browser_matcher` adresse cette lacune en implémentant une correspondance structurée par famille de navigateur, fondée sur l'empreinte passive du protocole HTTP/2. Le module de scoring à 7 dimensions pondérées (`browser_matcher.py`, 497 lignes) et la base de signatures Chrome/Firefox/Safari (`browser_signatures.py`, 165 lignes) sont entièrement opérationnels.
### 3.9.1 Principes du fingerprinting HTTP/2 passif
@ -1155,13 +1155,15 @@ Les pseudo-headers **doivent** apparaître avant les en-têtes réguliers dans l
| Client | Ordre observé | Notation abrégée |
|-----------------|---------------|------------------|
| Chrome 119+ | method, authority, scheme, path | `masp` |
| Firefox 90+ | method, path, authority, scheme | `mpas` |
| Safari 15+ | method, scheme, path, authority | `mspa` |
| Firefox 90+ | method, path, scheme, authority | `mpsa` |
| Safari 15+ | method, authority, scheme, path | `masp` |
| curl 8.x | method, path, scheme, authority | `mpsa` |
Source : [Bartlett, Cloudflare 2023](https://blog.cloudflare.com/cloudflare-bot-management-machine-learning-and-more/).
**Cas httpcloak** : httpcloak reproduit correctement le SETTINGS H2 de Chrome et la valeur WINDOW_UPDATE de Chrome, mais conserve l'ordre pseudo-header de curl (`mpsa`) au lieu de Chrome (`masp`). Résultat : score browser_matcher Chrome 0,60 zone grise. La pénalité de zone grise (voir §3.9.3) réduit le score final ML sans le neutraliser totalement.
**Note sur les valeurs observées vs. références Cloudflare** : les captures réelles effectuées par `ja4ebpf` montrent des écarts avec les données de référence Cloudflare pour certaines implémentations. Firefox présente un ordre `mpsa` (method, path, scheme, authority) dans nos captures, et non `mpas` (method, path, authority, scheme) comme rapporté par Cloudflare. Safari présente un ordre `masp` identique à Chrome dans nos captures, et non `mspa`. Safari envoie `INITIAL_WINDOW_SIZE=65535` et `WINDOW_UPDATE=10485760` dans nos observations, contre respectivement 2 097 152 et 10 420 225 dans les données Cloudflare. Ces écarts peuvent résulter de différences de version (nos captures Safari correspondent à WebKit 613.1.x sur macOS/iOS), de variantes de build, ou de l'évolution des piles HTTP/2 entre les mesures. Les signatures dans `browser_signatures.py` reflètent nos valeurs capturées réelles, garantissant la cohérence du scoring en production.
**Cas httpcloak** : httpcloak reproduit correctement le SETTINGS H2 de Chrome et la valeur WINDOW_UPDATE de Chrome, mais conserve l'ordre pseudo-header de curl (`mpsa`) au lieu de Chrome (`masp`). Résultat : score browser_matcher Chrome 0,60 zone grise. La pénalité de zone grise (voir §3.9.3) réduit le score final ML sans le neutraliser totalement. Note : `mpsa` est l'ordre réel capturé pour Firefox dans notre infrastructure httpcloak peut donc tromper partiellement la dimension pseudo-header, mais les dimensions SETTINGS et WINDOW_UPDATE révèlent l'incohérence.
#### Frames PRIORITY
@ -1208,6 +1210,26 @@ BROWSER_SIGNATURES["Chrome"] = {
"headers_ch_ua_required": True,
"accept_language_required": True,
}
# Signature Firefox (valeurs capturées réelles)
BROWSER_SIGNATURES["Firefox"] = {
"h2_settings_exact": {1: 65536, 4: 131072, 5: 16384},
"h2_settings_forbidden_keys": [2, 3, 6],
"h2_window_update": 12517377,
"pseudo_header_order": "m,p,s,a", # ordre réel capturé (pas m,p,a,s)
"tls": {"ja4_families": ["Firefox"], "grease_expected": False},
"headers_ch_ua_required": False, # Firefox ne supporte pas les Client Hints
}
# Signature Safari (valeurs capturées réelles)
BROWSER_SIGNATURES["Safari"] = {
"h2_settings_exact": {1: 4096, 3: 100, 4: 65535},
"h2_settings_forbidden_keys": [2, 5, 6],
"h2_window_update": 10485760,
"pseudo_header_order": "m,a,s,p", # identique à Chrome (WU=10485760 distingue)
"tls": {"ja4_families": ["Safari"], "grease_expected": False},
"headers_sec_fetch_forbidden": True, # Présence = incohérence
}
```
Le champ `h2_settings_exact` est désormais consommé directement par `_d1_h2_settings()` via les colonnes individuelles de `view_ai_features_1h` (`h2_header_table_size`, `h2_enable_push`, `h2_initial_window_size`, `h2_max_header_list_size`, etc.). La comparaison colonne par colonne permet de scorer partiellement un fingerprint inconnu du dictionnaire mais structurellement proche (ex. variante de navigateur non encore répertoriée).
@ -1385,17 +1407,17 @@ Le module `browser_matcher` génère les features suivantes dans le vecteur feat
| Feature | Type | Description | Statut |
|---------|------|-------------|--------|
| `browser_match_chrome` | Float32 | Score de correspondance Chrome (01) | `[partiel]` |
| `browser_match_firefox` | Float32 | Score de correspondance Firefox (01) | `[partiel]` |
| `browser_match_safari` | Float32 | Score de correspondance Safari (01) | `[partiel]` |
| `browser_match_max` | Float32 | max(chrome, firefox, safari) | `[partiel]` |
| `browser_family_detected` | String | Famille détectée ou chaîne vide | `[partiel]` |
| `browser_match_chrome` | Float32 | Score de correspondance Chrome (01) | `[impl.]` |
| `browser_match_firefox` | Float32 | Score de correspondance Firefox (01) | `[impl.]` |
| `browser_match_safari` | Float32 | Score de correspondance Safari (01) | `[impl.]` |
| `browser_match_max` | Float32 | max(chrome, firefox, safari) | `[impl.]` |
| `browser_family_detected` | String | Famille détectée ou chaîne vide | `[impl.]` |
| `h2_window_update_value` | UInt32 | Valeur WINDOW_UPDATE observée | `[impl.]` (colonne `h2_window_update` dans `http_logs`) |
| `h2_has_priority_frames` | UInt8 | 1 si frames PRIORITY présentes | `[impl.]` (colonne `h2_has_priority` dans `http_logs`) |
| `h2_pseudo_order` | String | Ordre observé (ex. `m,a,s,p`) | `[impl.]` (colonne `h2_pseudo_order` dans `http_logs`) |
| `tls_h2_family_mismatch` | UInt8 | 1 si JA4 dit Chrome mais H2 SETTINGS dit Firefox/outil | `[impl.]` (feature F4) |
Les features `h2_window_update_value`, `h2_has_priority_frames` et `h2_pseudo_order` sont désormais capturées par ja4ebpf via le parser HTTP/2 du flux SSL_read déchiffré et stockées dans des colonnes individuelles de `ja4_logs.http_logs`. De plus, chaque paramètre SETTINGS HTTP/2 dispose de sa propre colonne (`h2_header_table_size`, `h2_enable_push`, `h2_max_concurrent_streams`, `h2_initial_window_size`, `h2_max_frame_size`, `h2_max_header_list_size`, `h2_enable_connect_protocol`) avec la valeur -1 pour les paramètres absents du preface client. La feature `tls_h2_family_mismatch` est implémentée dans le vecteur feature global (famille F4 TLS features) et se calcule à partir des données JA4 existantes et des colonnes H2 individuelles disponibles dans `ja4_logs.http_logs`. Les features `browser_match_*` requièrent l'exécution complète du module `browser_matcher.py`.
Les features `h2_window_update_value`, `h2_has_priority_frames` et `h2_pseudo_order` sont désormais capturées par ja4ebpf via le parser HTTP/2 du flux SSL_read déchiffré et stockées dans des colonnes individuelles de `ja4_logs.http_logs`. De plus, chaque paramètre SETTINGS HTTP/2 dispose de sa propre colonne (`h2_header_table_size`, `h2_enable_push`, `h2_max_concurrent_streams`, `h2_initial_window_size`, `h2_max_frame_size`, `h2_max_header_list_size`, `h2_enable_connect_protocol`) avec la valeur -1 pour les paramètres absents du preface client. La feature `tls_h2_family_mismatch` est implémentée dans le vecteur feature global (famille F4 TLS features) et se calcule à partir des données JA4 existantes et des colonnes H2 individuelles disponibles dans `ja4_logs.http_logs`. Les features `browser_match_*` sont calculées par le module `browser_matcher.py` (497 lignes) à chaque cycle d'analyse, avec les signatures statiques de `browser_signatures.py` (165 lignes) et un rechargement dynamique optionnel depuis ClickHouse toutes les 24 heures.
### 3.9.5 Maintenance des signatures
@ -1953,7 +1975,7 @@ La famille 7 combine la connaissance des bases de référence (JA4 connu, ASN, p
**Calcul** : score de confiance global du browser_matcher (voir §3.8).
#### browser_family `[partiel]`
#### browser_family `[impl.]`
**Calcul** : famille détectée : `chrome | firefox | safari | curl | python | go | unknown`
@ -1993,19 +2015,19 @@ La famille 7 combine la connaissance des bases de référence (JA4 connu, ASN, p
**Calcul** : dimension cohérence HTTP/2 — composite de `h2_settings_known`, `h2_pseudo_order_match`, `h2_ja4_coherence`.
#### browser_match_chrome `[partiel]`
#### browser_match_chrome `[impl.]`
**Calcul** : score de correspondance spécifique au profil Chrome (SETTINGS H2 + WINDOW_UPDATE + pseudo-order masp + JA4 Chrome).
#### browser_match_firefox `[partiel]`
#### browser_match_firefox `[impl.]`
**Calcul** : score de correspondance spécifique au profil Firefox.
#### browser_match_safari `[partiel]`
#### browser_match_safari `[impl.]`
**Calcul** : score de correspondance spécifique au profil Safari.
#### browser_match_max `[partiel]`
#### browser_match_max `[impl.]`
**Calcul** : `MAX(browser_match_chrome, browser_match_firefox, browser_match_safari)`
@ -2259,12 +2281,12 @@ Un **graphe bipartite** G = (U V, E) est un graphe dont les sommets se répa
**Détection de communautés** : une communauté est un sous-ensemble de sommets plus densément connectés entre eux qu'avec le reste du graphe. Dans le graphe projeté G_JA4, une communauté dense de JA4 indique un botnet utilisant plusieurs empreintes JA4 mais se coordonnant via une infrastructure ASN partagée.
Plutôt que d'utiliser les algorithmes classiques de détection de communautés (Louvain, Girvan-Newman), qui nécessitent des graphes non orientés et souffrent de limites de résolution, l'implémentation utilise **HDBSCAN** ([Campello et al., 2013](https://link.springer.com/chapter/10.1007/978-3-642-37456-2_14)) sur les vecteurs de co-occurrence : chaque JA4 est représenté par le vecteur binaire des ASNs dans lesquels il apparaît, puis HDBSCAN regroupe les JA4 présentant des profils de co-occurrence ASN similaires.
L'implémentation utilise **Louvain** ([Blondel et al., 2008](https://arxiv.org/abs/0803.0476)) via la bibliothèque `python-louvain` pour la détection de communautés sur le graphe projeté pondéré. L'algorithme de Louvain optimise la modularité du graphe par agrégation hiérarchique itérative, identifiant les regroupements de JA4 partageant un profil de co-occurrence ASN similaire. En l'absence de `python-louvain`, un fallback vers les **composantes connexes** de NetworkX est utilisé.
**Formule du score de flotte** :
```
fleet_score = community_size × edge_density / log(nb_ASN)
fleet_score = community_size × edge_density / log2(n_asn + 2)
```
où :
@ -2280,22 +2302,38 @@ Une valeur de `fleet_score` élevée (> seuil empirique déterminé en productio
```python
import networkx as nx
from hdbscan import HDBSCAN
import numpy as np
from networkx.algorithms import bipartite
def build_bipartite_graph(sessions: pd.DataFrame, min_ips: int = 3) -> nx.Graph:
def build_fleet_graph(df: pd.DataFrame, min_ips: int = 3):
"""Construit le graphe bipartite JA4 × ASN."""
G = nx.Graph()
pairs = sessions.groupby(['ja4_fingerprint', 'asn'])['src_ip'].nunique()
for (ja4, asn), n_ips in pairs.items():
if n_ips >= min_ips:
G.add_edge(f"ja4:{ja4}", f"asn:{asn}", weight=n_ips)
return G
edge_weights = (
df.groupby(['ja4', 'asn_number'])['src_ip'].nunique()
.reset_index(name='n_ips')
)
edge_weights = edge_weights[edge_weights['n_ips'] >= min_ips]
for _, row in edge_weights.iterrows():
G.add_edge(f"ja4:{row['ja4']}", f"asn:{row['asn_number']}",
weight=int(row['n_ips']))
return G, ja4_nodes, asn_nodes
def project_ja4(G: nx.Graph) -> np.ndarray:
"""Projette le graphe bipartite sur l'espace JA4 (vecteurs de co-occurrence ASN)."""
ja4_nodes = [n for n in G.nodes if n.startswith("ja4:")]
asn_nodes = [n for n in G.nodes if n.startswith("asn:")]
def detect_fleet_communities(df: pd.DataFrame) -> dict:
"""Analyse le graphe et retourne {src_ip: fleet_score}."""
G, ja4_nodes, asn_nodes = build_fleet_graph(df)
# Projection bipartite : graphe des JA4 partageant des ASN
G_ja4 = bipartite.weighted_projected_graph(G, ja4_nodes)
# Détection de communautés (Louvain ou composantes connexes en fallback)
try:
from community import best_partition as louvain_partition
partition = louvain_partition(G_ja4, weight='weight', random_state=42)
except ImportError:
communities = {i: set(c) for i, c in enumerate(nx.connected_components(G_ja4))}
# fleet_score = taille × densité / log2(n_asn + 2)
for cid, members in communities.items():
score = len(members) * density / max(np.log2(n_asn + 2), 0.1)
for ja4_node in members:
fleet_scores[ja4_node.replace('ja4:', '')] = score
return ip_scores
matrix = np.zeros((len(ja4_nodes), len(asn_nodes)))
for i, ja4 in enumerate(ja4_nodes):
for j, asn in enumerate(asn_nodes):
@ -2313,8 +2351,9 @@ def detect_fleets(sessions: pd.DataFrame) -> pd.DataFrame:
# Calcul fleet_score par cluster...
```
**Table de résultats** : `ja4_processing.fleet_detections`
- Colonnes : `(cycle_timestamp, community_id, ja4_list, asn_list, community_size, edge_density, nb_asn, fleet_score)`
**Sortie** : les résultats de la détection de flotte sont intégrés directement dans le DataFrame du cycle courant via deux colonnes additionnelles :
- `fleet_score` : score de la communauté à laquelle appartient l'IP (0 si aucune flotte détectée)
- `fleet_campaign_flag` : 1 si `fleet_score ≥ FLEET_SCORE_THRESHOLD` (défaut : 2.0)
Les IPs appartenant à des communautés avec `fleet_score` élevé reçoivent un **malus de score d'anomalie** dans le pipeline final (ajout d'une constante au score brut EIF avant application du MetaLearner).
@ -2893,9 +2932,10 @@ Le fingerprinting réseau opère sans déchiffrement TLS (les métadonnées TLS
| EIF training | < 2 secondes | ~34 000 sessions, 96 features |
| AE inference | ~50 ms | Batch de 34 000 sessions |
| XGBoost inference | ~30 ms | Batch de 34 000 sessions |
| HDBSCAN (fleet.py) | ~100 ms | ~34 000 sessions, espace latent AE |
| HDBSCAN (anomalies) | ~100 ms | ~34 000 sessions, espace latent AE |
| Louvain (fleet.py) | ~50 ms | Graphe JA4×ASN, communautés |
| MetaLearner LR | < 10 ms | Régression logistique, négligeable |
| **Cycle complet** | **~300 secondes** | EIF + AE + XGBoost + HDBSCAN + fleet |
| **Cycle complet** | **~300 secondes** | EIF + AE + XGBoost + HDBSCAN + Louvain |
La durée du cycle (300 s = 5 minutes) est contrainte principalement par la **fenêtre d'agrégation ClickHouse** (1 heure glissante avec recalcul toutes les 5 minutes), non par les temps d'exécution ML.
@ -2944,13 +2984,12 @@ Un seul utilisateur réel alterne quelques connexions (26 ports source actifs
### 6.6 Travaux futurs et roadmap
#### Priorité 1 — Complétude du vecteur de features (implémentation requise)
#### Priorité 1 — Extension du vecteur de features
**browser_matcher complet (§3.9)** :
- État actuel : modules `[partiel]` (logique de score partielle, base de signatures incomplète)
**browser_matcher maintenance (§3.9)** :
- État actuel : `[impl.]` logique de score complète à 7 dimensions, base de signatures Chrome/Firefox/Safari complète
- Données H2 brutes : `[impl.]` — capture des 7 paramètres SETTINGS individuels, WINDOW_UPDATE, flag PRIORITY et ordre pseudo-headers par ja4ebpf via le parser HTTP/2 du flux SSL_read déchiffré. Colonnes individuelles dans `ja4_logs.http_logs` (`h2_header_table_size`, `h2_enable_push`, `h2_max_concurrent_streams`, `h2_initial_window_size`, `h2_max_frame_size`, `h2_max_header_list_size`, `h2_enable_connect_protocol`, `h2_window_update`, `h2_has_priority`, `h2_pseudo_order`)
- Travail restant : compléter `browser_signatures.py` avec signatures Firefox et Safari complètes, implémenter le rechargement ClickHouse toutes les 24h, intégrer les 5 features `browser_match_*` dérivées dans le vecteur feature global
- Dépendances : ~~capture des frames H2 SETTINGS~~ (réalisé) ; reste le module `browser_matcher.py`
- Travail restant : maintenance des signatures lors des nouvelles versions de navigateurs, enrichissement de la base via la file d'examen `unknown_h2_fingerprints`
**DNS Shadow Analysis (§5.6)** :
- État actuel : `[todo]` non implémenté
@ -3020,7 +3059,7 @@ Extension du système `browser_confidence` à 6 axes vers une correspondance str
La capture passive est réalisée par ja4ebpf via un uprobe sur `SSL_read` (OpenSSL/BoringSSL). Le Go Magic Bytes dispatcher identifie le preface HTTP/2 dans le flux déchiffré, et le parser H2 extrait les frames SETTINGS, WINDOW_UPDATE et HEADERS sans instrumentation serveur. Chaque paramètre SETTINGS est stocké dans une colonne ClickHouse individuelle (`h2_header_table_size`, `h2_enable_push`, `h2_max_concurrent_streams`, `h2_initial_window_size`, `h2_max_frame_size`, `h2_max_header_list_size`, `h2_enable_connect_protocol`) avec -1 pour les paramètres absents, complétés par `h2_window_update`, `h2_has_priority` et `h2_pseudo_order`.
Cette technique permet de détecter des outils d'évasion qui reproduisent correctement la couche TLS (curl_cffi, httpcloak) mais échouent à reproduire les subtilités H2 — notamment l'ordre des pseudo-headers et la valeur WINDOW_UPDATE.
Cette technique permet de détecter des outils d'évasion qui reproduisent correctement la couche TLS (curl_cffi, httpcloak) mais échouent à reproduire les subtilités H2 — notamment l'ordre des pseudo-headers et la valeur WINDOW_UPDATE. Le module de scoring est entièrement implémenté (`browser_matcher.py`, 497 lignes) avec les signatures des trois familles majeures (Chrome, Firefox, Safari) et trois signatures non-navigateur (curl, python-httpx, Go net/http) dans `browser_signatures.py` (165 lignes).
La stabilité des empreintes H2 de Chrome sur 2+ ans (novembre 2023 2026) contraste favorablement avec JA4 TLS (instable à chaque mise à jour de ciphersuites), justifiant l'investissement dans cette dimension additionnelle.
@ -3029,7 +3068,7 @@ La stabilité des empreintes H2 de Chrome sur 2+ ans (novembre 2023 2026) co
Six techniques entièrement implémentées adressant des angles morts spécifiques :
1. **Path Sequence Entropy (§5.1)** : entropie de la matrice de transition Markov des séquences de chemins — résistant à la randomisation de diversité par les bots
2. **Bipartite Bot Fleet Detection (§5.2)** : détection de flottes distribuées via graphe bipartite JA4×ASN et HDBSCAN sur l'espace de co-occurrence — détecte les botnets dont aucune paire (JA4, ASN) individuelle n'est anormale
2. **Bipartite Bot Fleet Detection (§5.2)** : détection de flottes distribuées via graphe bipartite JA4×ASN et Louvain sur le graphe projeté pondéré — détecte les botnets dont aucune paire (JA4, ASN) individuelle n'est anormale
3. **Request Cadence Fingerprint (§5.3)** : quatre signaux statistiques (CV, autocorrélation lag-1, ratio rafale/pause, déviation Benford) sur les intervalles inter-requêtes
4. **Resource Dependency Tree (§5.4)** : analyse du waterfall de chargement de ressources — détecte Playwright/Puppeteer par le délai anormalement court entre HTML et premier asset
5. **Intra-Session JA4 Drift (§5.5)** : ratio de transitions de JA4 dominant par fenêtre de 10 minutes — détecte les bots APT multi-phases
@ -3053,15 +3092,15 @@ Architecture de données fondée sur ClickHouse avec **AggregatingMergeTree view
| Famille 4 — Cohérence cross-layer | Cohérence entre les couches TCP, TLS et HTTP | alpn_http_mismatch, is_alpn_missing, sni_host_mismatch, tls_h2_family_mismatch, tls12_ratio, http10_ratio, et 8 autres (14 features) | 14 | 0 | 0 |
| Famille 5 — Empreinte réseau | Caractéristiques de la pile réseau du client | ip_id_zero_ratio, avg_ttl, ttl_std, no_window_scale_ratio, ip_asn, ip_country, ja4_asn_rarity, et 6 autres (13 features) | 13 | 0 | 0 |
| Famille 6 — Comportement de navigation | Patterns de navigation et structure des requêtes | asset_ratio, direct_access_ratio, orphan_ratio, temporal_entropy, post_ratio, head_ratio, http_scheme_ratio, et 3 autres (10 features) | 10 | 0 | 0 |
| Famille 7 — Intelligence contextuelle | Enrichissements contextuels et browser scoring | ja4_asn_concentration, browser_confidence, browser_match_chrome, browser_match_firefox, browser_match_safari, browser_match_max, browser_family_detected, et 16 autres (23 features) | 18 | 5 | 0 |
| Famille 7 — Intelligence contextuelle | Enrichissements contextuels et browser scoring | ja4_asn_concentration, browser_confidence, browser_match_chrome, browser_match_firefox, browser_match_safari, browser_match_max, browser_family_detected, et 16 autres (23 features) | 23 | 0 | 0 |
| Famille 8 — Features de thèse | Features originales de recherche (§5.1§5.8) | path_transition_entropy, cadence_cv, lag1_autocorrelation, burst_ratio, benford_deviation, root_to_first_asset_delay, ja4_drift_ratio, host_diversity, et 5 autres (13 features) | 13 | 0 | 0 |
| **Total** | | | **91** | **5** | **0** |
| **Total** | | | **96** | **0** | **0** |
**Résumé quantitatif** : sur 96 features documentées dans la Section 4, ~95 % sont entièrement implémentées (`[impl.]`) et ~5 % sont partiellement implémentées (`[partiel]` : les 5 features `browser_match_*` du module `browser_matcher`). Les features précédemment marquées `[todo]` (§5.6 DNS Shadow Analysis, §5.7 Compression Ratio Invariant) sont exclues du décompte des 96 features actives car classées comme travaux futurs dans la Section 5. Les features H2 brutes (`h2_window_update_value`, `h2_has_priority_frames`, `h2_pseudo_order`) sont entièrement implémentées depuis l'intégration du parser HTTP/2 avec buffer de réassemblage dans ja4ebpf.
**Résumé quantitatif** : les 96 features documentées dans la Section 4 sont **toutes entièrement implémentées** (`[impl.]`), incluant les 5 features `browser_match_*` du module `browser_matcher` (scoring à 7 dimensions complet, signatures Chrome/Firefox/Safari opérationnelles). Les features des techniques §5.6 (DNS Shadow Analysis) et §5.7 (Compression Ratio Invariant), classées `[todo]`, sont exclues du décompte des 96 features actives car identifiées comme travaux futurs dans la Section 5. Les features H2 brutes (`h2_window_update_value`, `h2_has_priority_frames`, `h2_pseudo_order`) sont entièrement implémentées depuis l'intégration du parser HTTP/2 avec buffer de réassemblage dans ja4ebpf.
### Perspective
Le système atteint ses objectifs opérationnels actuels. La capture HTTP/2 passive est désormais intégrée avec 12 colonnes individuelles dans `ja4_logs.http_logs`. Les axes d'amélioration prioritaires sont l'achèvement du module de scoring `browser_matcher` (`[partiel]``[impl.]` pour les 5 features `browser_match_*`), l'extension DNS Shadow Analysis pour la couverture DNS (`[todo]``[partiel]`), et le passage à l'apprentissage en ligne pour XGBoost. À plus long terme, le support HTTP/3 (QUIC) deviendra nécessaire à mesure que la proportion de trafic HTTP/3 augmente dans la baseline.
Le système atteint ses objectifs opérationnels actuels. La capture HTTP/2 passive est intégrée avec 12 colonnes individuelles dans `ja4_logs.http_logs`, et le module `browser_matcher` est opérationnel avec ses 7 dimensions de scoring. Les axes d'amélioration prioritaires sont l'enrichissement continu des signatures navigateur via la file d'examen `unknown_h2_fingerprints`, l'extension DNS Shadow Analysis pour la couverture DNS (`[todo]``[partiel]`), et le passage à l'apprentissage en ligne pour XGBoost. À plus long terme, le support HTTP/3 (QUIC) deviendra nécessaire à mesure que la proportion de trafic HTTP/3 augmente dans la baseline.
La technique la plus prometteuse parmi les travaux futurs est le **PARD-SSM** (Hiremath et al., 2026 [Référence à vérifier / Identifier le vrai papier]), qui permettrait de modéliser explicitement les phases d'attaque séquentielles — comblant la lacune actuelle entre la détection de sessions individuelles et la détection de campagnes d'attaque coordonnées multi-phases.