docs: mise à jour thèse — capture HTTP/2 passive et colonnes individuelles

Sections mises à jour :
- Architecture §3.1 : H2 capture déplacé de ja4sentinel vers mod_reqin_log
- §3.5 Couche L7 : description du hook process_connection (APR_HOOK_FIRST,
  AP_MODE_SPECULATIVE), parsing preface, notes c1/c2, colonnes individuelles
- Tableau des 12 colonnes H2 dans ja4_logs.http_logs avec types et conventions
- §3.9 Browser Matcher : statut mis à jour (capture [impl.], scoring [partiel])
- §3.9.1 : mécanisme de capture via process_connection au lieu de filtre connexion
- §3.9.4 : h2_window_update_value, h2_has_priority, h2_pseudo_order → [impl.]
- §6.6 Roadmap : dépendance capture H2 résolue, travail restant = browser_match_*
- Contribution 3 : description de l implémentation technique ajoutée
- Tableau récapitulatif : F8 passe de 0/8/0 à 3/5/0 (70 impl. / 5 partiel)
- Résumé quantitatif : 82% impl. (était 79%), 6% partiel (était 9%)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
toto
2026-04-11 02:40:41 +02:00
parent 85d3b95b7b
commit 95e87149aa

View File

@ -803,15 +803,17 @@ httpcloak est un outil d'évasion qui tente d'imiter l'empreinte TLS de Chrome.
│ (Source B) │ (Source A) │
│ │ │
│ libpcap, CAP_NET_RAW │ Module Apache personnalisé │
│ Couches L3/L4/L5 │ Couche L7 HTTP
│ Couches L3/L4/L5 │ Couches L7 HTTP + L5 HTTP/2
│ - IP header (TTL, DF) │ - src_ip, src_port │
│ - TCP SYN (MSS, Window, │ - timestamp_ns (nanoseconde) │
│ Options, Scale) │ - méthode, chemin, query │
│ - TLS ClientHello │ - version HTTP │
│ (JA4, JA4T, ALPN, SNI) │ - en-têtes (bruts + ordre) │
- HTTP/2 frames │ - statut, taille, durée_ms │
(SETTINGS, WU, │
PRIORITY, pseudo-hdr) │
│ - statut, taille, durée_ms │
- HTTP/2 preface passif :
SETTINGS (7 params individuels),
│ │ WINDOW_UPDATE, PRIORITY flag, │
│ │ ordre pseudo-headers │
└───────────────────────────┴──────────────────────────────────────┘
│ │
└─────────────┬─────────────┘
@ -934,6 +936,34 @@ La couche L7 constitue la couche la plus riche en features comportementales. Le
Données capturées par mod_reqin_log : `src_ip`, `src_port`, `timestamp_ns` (nanoseconde absolu), `method`, `path`, `query_string`, `http_version`, `headers_raw` (en-têtes bruts dans leur ordre d'émission), `header_order_signature` (hash de l'ordre), `status_code`, `response_size`, `duration_ms`. L'horodatage nanoseconde est critique pour le calcul des features temporelles F8 (cadence_cv, lag1_autocorrelation, benford_deviation, root_to_first_asset_delay).
**Fingerprinting HTTP/2 passif intégré** : pour les connexions HTTP/2, mod_reqin_log capture passivement le preface client via un hook `ap_hook_process_connection` enregistré en priorité `APR_HOOK_FIRST`, exécuté avant `mod_http2`. Ce hook effectue une lecture spéculative (`AP_MODE_SPECULATIVE`) de 512 octets sur les filtres d'entrée de la connexion, qui déclenche transparentement le handshake TLS (`mod_ssl`) et retourne les données déchiffrées sans les consommer. Le preface H2 est ensuite parsé pour en extraire :
- Les 7 paramètres SETTINGS individuels (IDs 16 et 8), chacun stocké dans une colonne ClickHouse dédiée (`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
- L'incrément `h2_window_update` de la frame WINDOW_UPDATE sur la connexion (stream ID 0)
- Le flag `h2_has_priority` indiquant la présence d'un champ PRIORITY dans la frame HEADERS
- L'ordre des pseudo-headers `h2_pseudo_order` (ex. `m,a,s,p`) extrait par décodage HPACK partiel de la première frame HEADERS
- Le fingerprint composite `h2_fingerprint` au format Akamai et la chaîne brute `h2_settings_fp`
Les données H2 sont stockées dans les notes de la connexion primaire (`c->notes`). Pour les connexions HTTP/2, `mod_http2` crée des connexions secondaires (c2) par stream ; le hook `log_request` accède aux notes H2 via `r->connection->master` (connexion primaire c1). Le hook retourne `DECLINED` après stockage, laissant `mod_http2` gérer la suite normalement.
**Colonnes HTTP/2 dans `ja4_logs.http_logs`** :
| Colonne ClickHouse | Type | Défaut | Description |
|---------------------|------|--------|-------------|
| `h2_fingerprint` | String | `''` | Fingerprint composite au format Akamai (ex. `1:65536,2:0,4:6291456,6:262144\|15663105\|0\|m,a,s,p`) |
| `h2_settings_fp` | String | `''` | Chaîne brute des entrées SETTINGS (ex. `3:100,4:65536,2:0`) |
| `h2_header_table_size` | Int32 | `-1` | SETTINGS ID 1 — HEADER_TABLE_SIZE (octets). -1 = absent du preface |
| `h2_enable_push` | Int32 | `-1` | SETTINGS ID 2 — ENABLE_PUSH (0/1). -1 = absent |
| `h2_max_concurrent_streams` | Int32 | `-1` | SETTINGS ID 3 — MAX_CONCURRENT_STREAMS. -1 = absent |
| `h2_initial_window_size` | Int64 | `-1` | SETTINGS ID 4 — INITIAL_WINDOW_SIZE (octets). -1 = absent |
| `h2_max_frame_size` | Int32 | `-1` | SETTINGS ID 5 — MAX_FRAME_SIZE (octets). -1 = absent |
| `h2_max_header_list_size` | Int32 | `-1` | SETTINGS ID 6 — MAX_HEADER_LIST_SIZE (octets). -1 = absent |
| `h2_enable_connect_protocol` | Int32 | `-1` | SETTINGS ID 8 — ENABLE_CONNECT_PROTOCOL (RFC 8441). -1 = absent |
| `h2_window_update` | UInt32 | `0` | Incrément WINDOW_UPDATE connexion (stream ID 0). 0 = absent |
| `h2_has_priority` | UInt8 | `0` | 1 si le flag PRIORITY est présent dans la frame HEADERS |
| `h2_pseudo_order` | String | `''` | Ordre des pseudo-headers (ex. `m,a,s,p` pour Chrome) |
La convention `-1` pour les paramètres SETTINGS absents est essentielle : elle distingue un paramètre non envoyé par le client (valeur par défaut RFC implicite) d'un paramètre explicitement fixé à 0 (ex. `ENABLE_PUSH = 0` signifie « Server Push désactivé » vs `-1` signifie « non envoyé, le serveur utilise la valeur par défaut RFC de 1 »).
Toutes les features des familles F1F6 et F8 proviennent de cette couche, agrégées sur des fenêtres temporelles de 300 secondes (5 minutes) par session (src_ip).
### 3.6 Corrélation inter-couches (logcorrelator)
@ -1054,7 +1084,7 @@ La valeur `percentile_5` du historique des scores négatifs (anomalies confirmé
## 3.9 Browser Signature Detection (browser_matcher)
`[partiel]` **Statut global : à implémenter**
`[partiel]` **Statut global : capture H2 implémentée, module de scoring à compléter**
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.
@ -1069,7 +1099,9 @@ Le système `browser_confidence` à 6 axes (§3.8) fournit un score agrégé uti
- **Compression d'en-têtes HPACK** : [RFC 7541](https://www.rfc-editor.org/rfc/rfc7541) définit HPACK, une compression d'en-têtes HTTP par table d'indexation. L'ordre des entrées dans la table statique HPACK est normalisé, mais l'ordre de sérialisation des pseudo-headers est laissé à l'implémentation.
- **Contrôle de flux** : mécanisme de fenêtres (`WINDOW_UPDATE`) limitant le débit pour éviter la saturation du récepteur.
Après terminaison TLS par Apache (`mod_ssl`), le flux HTTP/2 est déchiffré et disponible pour `mod_http2` en clair. Ceci permet le **fingerprinting passif** des paramètres de connexion HTTP/2 sans aucune injection de code côté client.
Après terminaison TLS par Apache (`mod_ssl`), le flux HTTP/2 est déchiffré et disponible en clair. Le fingerprinting passif est réalisé directement par **mod_reqin_log** via un hook `process_connection` enregistré en priorité `APR_HOOK_FIRST`. Ce hook s'exécute **avant** `mod_http2` et effectue une lecture spéculative (`AP_MODE_SPECULATIVE`, 512 octets) sur `c->input_filters`, déclenchant transparentement le handshake TLS. Si les données commencent par le magic HTTP/2 (`PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n`), le parser binaire extrait les frames SETTINGS, WINDOW_UPDATE et HEADERS du preface client, stocke les résultats dans `c->notes`, puis retourne `DECLINED` pour laisser `mod_http2` gérer la connexion. Cette approche ne consomme pas les données et n'interfère pas avec le traitement HTTP/2 normal.
**Note architecturale** : l'approche par filtre de connexion (`AP_FTYPE_CONNECTION`) a été abandonnée car `mod_http2` prend le contrôle complet de la connexion via son propre hook `process_connection` les filtres d'entrée de connexion ne sont jamais invoqués pour les connexions HTTP/2. Le hook `process_connection` à priorité haute est la seule technique fiable pour intercepter le preface H2 avant `mod_http2`.
#### Frame SETTINGS
@ -1352,12 +1384,12 @@ Le module `browser_matcher` génère les features suivantes dans le vecteur feat
| `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]` |
| `h2_window_update_value` | UInt32 | Valeur WINDOW_UPDATE observée | `[partiel]` |
| `h2_has_priority_frames` | UInt8 | 1 si frames PRIORITY présentes | `[partiel]` |
| `h2_pseudo_order` | String | Ordre observé (ex. `m,a,s,p`) | `[partiel]` |
| `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) |
La feature `tls_h2_family_mismatch` est déjà implémentée dans le vecteur feature global (famille F4 TLS features) car elle se calcule à partir des données JA4 existantes et du champ h2_settings_id4 disponible dans `ja4_processing.sessions`. 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 mod_reqin_log 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`.
### 3.9.5 Maintenance des signatures
@ -2906,9 +2938,9 @@ Un seul utilisateur réel alterne quelques connexions (26 ports source actifs
**browser_matcher complet (§3.9)** :
- État actuel : modules `[partiel]` (logique de score partielle, base de signatures incomplète)
- Travail requis : compléter `browser_signatures.py` avec signatures Firefox et Safari complètes, implémenter le rechargement ClickHouse toutes les 24h, intégrer les 8 features dérivées dans le vecteur feature global
- Dépendances : capture des frames H2 SETTINGS via `mod_h2` Apache (requires `mod_http2` avec hook de logging personnalisé)
- Estimation : 34 semaines de développement
- Données H2 brutes : `[impl.]` — capture des 7 paramètres SETTINGS individuels, WINDOW_UPDATE, flag PRIORITY et ordre pseudo-headers par mod_reqin_log via hook `process_connection` (APR_HOOK_FIRST, AP_MODE_SPECULATIVE). 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`
**DNS Shadow Analysis (§5.6)** :
- État actuel : `[todo]` non implémenté
@ -2976,7 +3008,9 @@ L'**explainabilité** est assurée par ExIFFI ([Frizzo et al., 2024](https://arx
Extension du système `browser_confidence` à 6 axes vers une correspondance structurée par famille de navigateur, fondée sur l'analyse passive de 7 dimensions H2 : frame SETTINGS (7 paramètres), WINDOW_UPDATE, ordre des pseudo-headers, frames PRIORITY, cohérence des en-têtes HTTP, structure TLS, et lookup JA4 par dictionnaire.
Cette technique détecte 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.
La capture passive est réalisée par mod_reqin_log via un hook `ap_hook_process_connection` (APR_HOOK_FIRST) qui intercepte le preface HTTP/2 avant `mod_http2` par lecture spéculative. 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.
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.
@ -3010,17 +3044,17 @@ Architecture de données fondée sur ClickHouse avec **AggregatingMergeTree view
| F5 — Comportement temporel | hit_velocity, temporal_entropy, cadence_cv, lag1_autocorrelation, burst_ratio, benford_deviation, ja4_drift_ratio (7 features) | 7 | 0 | 0 |
| F6 — Navigation L7 | path_diversity_ratio, path_transition_entropy, asset_ratio, root_to_first_asset_delay, asset_load_stddev, post_ratio, error_4xx_ratio (7 features) | 7 | 0 | 0 |
| F7 — Browser Confidence | browser_confidence (6-axis agrégé) | 1 | 0 | 0 |
| F8 — Browser Matcher | browser_match_chrome, browser_match_firefox, browser_match_safari, browser_match_max, browser_family_detected, h2_window_update_value, h2_has_priority_frames, h2_pseudo_order (8 features) | 0 | 8 | 0 |
| F8 — Browser Matcher | browser_match_chrome, browser_match_firefox, browser_match_safari, browser_match_max, browser_family_detected, h2_window_update_value, h2_has_priority_frames, h2_pseudo_order (8 features) | 3 | 5 | 0 |
| F9 — Fleet / Graphe | fleet_score, community_size, edge_density (3 features) | 3 | 0 | 0 |
| F10 — Multi-domaine | host_diversity, host_sweep_speed, host_coverage_uniformity, cross_domain_path_similarity (4 features) | 4 | 0 | 0 |
| F11 — Futures (non impl.) | dns_shadow_ratio, compression_ratio_invariant (2 features) | 0 | 0 | 2 |
| **Total** | **85** | **67** | **8** | **2** + meta |
| **Total** | **85** | **70** | **5** | **2** + meta |
**Résumé quantitatif** : ~79 % des features entièrement implémentées (`[impl.]`), ~9 % partiellement implémentées (`[partiel]`, toutes dans browser_matcher), ~2 % non implémentées (`[todo]`, §5.6 et §5.7).
**Résumé quantitatif** : ~82 % des features entièrement implémentées (`[impl.]`), ~6 % partiellement implémentées (`[partiel]`, les 5 features `browser_match_*` de browser_matcher), ~2 % non implémentées (`[todo]`, §5.6 et §5.7). Les 3 features H2 brutes (`h2_window_update_value`, `h2_has_priority_frames`, `h2_pseudo_order`) sont passées de `[partiel]` à `[impl.]` suite à l'intégration de la capture HTTP/2 passive dans mod_reqin_log.
### Perspective
Le système atteint ses objectifs opérationnels actuels. Les axes d'amélioration prioritaires sont l'achèvement de `browser_matcher` (`[partiel]``[impl.]`), 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 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.
La technique la plus prometteuse parmi les travaux futurs est le **PARD-SSM** ([Hiremath et al., 2026](https://arxiv.org/abs/2604.12345)), 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.