Files
ja4-platform/docs/thesis/07_discussion_limites.md
Jacquin Antoine c6cb12981c feat(ml): replace NetworkX/Louvain with PyTorch Geometric GraphSAGE for fleet detection
Rewrite fleet.py to use a GNN-based approach: nodes are src_ip with ML feature
vectors, edges connect IPs sharing (JA4, ASN) pairs, GraphSAGE (2 SAGEConv
layers, in→64→32) produces 32D embeddings clustered by HDBSCAN. PyG NeighborLoader
activates for >50k nodes. Update thesis docs (§5.2, §6.4, §2, §8) to reflect
GraphSAGE architecture and PyG scalability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 15:45:34 +02:00

227 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[<< Sommaire](README.md) | [Suivant >>](08_conclusion_references.md)
---
## 6. Discussion et limites
### 6.1 Course aux armements (Arms Race)
#### Dynamique attaquant/défenseur
La détection de bots s'inscrit dans une dynamique de course aux armements où chaque technique de détection génère une contre-mesure correspondante. Cette dynamique est bien documentée dans la littérature sur la sécurité réseau ([Fifield et al., 2012](https://arxiv.org/abs/1210.0921)) : l'avantage attaquant décroît quand le nombre de signaux de détection augmente, car le coût d'imitation de plusieurs signaux simultanément croît de manière super-linéaire.
**Tableau des contre-mesures connues** :
| Technique de détection | Contre-mesure connue | Évaluation de la contre-mesure |
|-----------------------|---------------------|-------------------------------|
| JA4 TLS fingerprinting | BotBrowser, curl_cffi, httpcloak | Efficace sur la couche TLS, mais laisse des traces sur H2 |
| Analyse des en-têtes HTTP | Frameworks reproduisant l'ordre exact des en-têtes Chrome | Efficace mais ne reproduit pas les en-têtes conditionnel (Sec-Fetch-*, If-None-Match) |
| Analyse temporelle (hit_velocity) | Jitter artificiel randomisé | Augmente CV mais laisse une signature d'autocorrélation (§5.3) |
| asset_ratio | Playwright/Puppeteer chargeant toutes ressources | Détectable via resource dependency tree (§5.4) |
| IP reputation | Proxies résidentiels (Bright Data, Oxylabs) | Contournement partiel mais coût élevé par requête |
| Comportement navigation | Scripts imitant les patterns de clic humain | Détectable via cadence fingerprint et entropy de séquence |
#### Architecture multi-couches comme contre-mesure structurelle
La mitigation fondamentale est l'**architecture multi-couches** : imiter simultanément 85+ features réparties sur 8 familles et 5 couches réseau (L3 à L7) implique un coût de mise en œuvre croissant de manière exponentielle avec le nombre de signaux. Un attaquant qui maîtrise la couche TLS (L5) peut encore être trahi par le timing TCP (L4) ou les patterns de navigation (L7).
#### Analyse des outils d'évasion spécifiques
**BotBrowser** : modifie le code source de Chromium pour supprimer les artefacts d'automatisation. Passe tous les tests de détection JS-based. Détectable via :
- Signatures temporelles (le patching de Chromium introduit des artefacts comportementaux subtils dans les timings de rendu)
- Frames PRIORITY H2 : BotBrowser utilise l'architecture Chrome → pas de PRIORITY frames (cohérent), mais ne corrige pas les subtilités de `INITIAL_WINDOW_SIZE` sur certaines versions
- JA4 TLS identique au vrai Chrome → non discriminant seul
**curl_cffi** : bibliothèque Python qui utilise libcurl avec un stack TLS patché pour imiter les JA4 Chrome/Firefox. Détectable via :
- Ordre pseudo-headers : `curl_cffi` conserve l'ordre curl (`mpsa`), pas Chrome (`masp`)
- WINDOW_UPDATE absent (= 0) — non reproduit par curl_cffi
- Comportement navigation : absence de cookies de session, absence de `Referer`, absence de `Sec-Fetch-*`
**httpcloak** : similaire à `curl_cffi`. Reproduit correctement les SETTINGS H2 de Chrome et la valeur WINDOW_UPDATE, mais échoue sur l'ordre pseudo-headers (conserve `mpsa`). Score browser_matcher résultant ≈ 0,60 → zone grise → atténuation active.
**Playwright/Puppeteer headless** : charge toutes les ressources, reproduit les en-têtes Chrome. Détectable via :
- `root_to_first_asset_delay` < 10 ms 5.4)
- `asset_load_stddev` quasi-nul 5.4)
- Absence de variabilité naturelle dans les timings inter-requêtes 5.3, CV faible)
### 6.2 Faux positifs et contamination de baseline
#### Hypothèse semi-supervisée et sa fragilité
Le modèle EIF repose sur l'hypothèse que le trafic avec `asn_label = 'human'` est effectivement humain, constituant la distribution de référence. Cette hypothèse est fragilisée par deux phénomènes :
**Proxies résidentiels** (Bright Data, Oxylabs, IPRoyal) : ces services opèrent depuis des ASN étiquetés "résidentiel/human" par les bases de données géo-IP, mais transportent du trafic automatisé pour leurs clients. Leur trafic contaminerait la baseline si inclus.
**Botnets IoT** : appareils compromis dans des réseaux résidentiels, générant du trafic automatisé depuis des ASN labellisés humains.
#### Quantification statistique de la contamination
Avec `contamination = 0.001` (paramètre EIF), au maximum 0,1 % des sessions d'entraînement sont supposées anormales. Sur ~34 000 sessions par cycle, cela représente au maximum **34 sessions contaminées** insuffisant pour déplacer matériellement la frontière d'isolation EIF.
Cependant, des proxies résidentiels persistants apparaissant dans **chaque cycle** pourraient accumuler un impact. Soit C_cycle sessions contaminées par cycle, et N cycles d'entraînement accumulés. Si C_cycle 50 et N = 10, 500 sessions contaminées sur 340 000 (0,15 %) encore marginal mais non négligeable.
**Seuil critique** : au-delà de 1 % de contamination de la baseline, la sensibilité EIF chute de manière non linéaire les sessions contaminées sont suffisamment nombreuses pour constituer leur propre "cluster normal" dans l'espace d'isolation.
#### Système de mitigation multi-niveau
| Niveau | Mécanisme | Efficacité estimée |
|--------|-----------|-------------------|
| 1 | `contamination = 0.001` + déduplication Anubis | Supprime les bots connus avant entraînement |
| 2 | Signaux orthogonaux 5.2, §5.3) résistants à contamination | Détecte bots résistants à l'EIF par des axes indépendants |
| 3 | Validation : `anomaly_rate > 20%` rejet du modèle | Détecte les cycles d'entraînement pathologiques |
| 4 | Feedback SOC : FP reclassification "human" ; TP exclusion baseline | Correction manuelle des erreurs systématiques |
| 5 | Triple ensemble : XGBoost corrige les erreurs systématiques EIF | Supervisé corrige les biais de l'non-supervisé |
#### Impact du feedback SOC
Le mécanisme de feedback (niveau 4) est particulièrement important : chaque faux positif identifié par l'équipe SOC reclassifie l'IP en "human" dans la baseline, empêchant sa réinfluence future sur l'EIF. Chaque vrai positif confirmé exclut l'IP de la baseline, purifiant le jeu d'entraînement de manière progressive.
### 6.3 Vie privée et conformité RGPD
#### Caractérisation du traitement
Le fingerprinting réseau opère sans déchiffrement TLS (les métadonnées TLS sont accessibles avant déchiffrement du payload) et sans exécution de code côté client (pas d'injection de JavaScript de tracking, contrairement à FingerprintJS [BotD](https://fingerprint.com/blog/botd/)). Cette caractéristique architecturale a des implications directes sur la conformité RGPD.
**Analyse de conformité** :
| Dimension RGPD | Analyse |
|----------------|---------|
| **Base légale** (Art. 6(1)(f)) | Intérêt légitime : protection de l'infrastructure contre les attaques automatisées nécessité établie, proportionnalité maintenue par les mécanismes de minimisation |
| **Données traitées** | Adresse IP source (nécessaire techniquement pour la communication réseau), fingerprints JA4 (agrégats cryptographiques sans identifiant personnel direct), métriques comportementales agrégées |
| **JA4H_d** | Explicitement conçu pour le non-SPII tracking : les suites de chiffrement sont expurgées des informations personnellement identifiantes |
| **Minimisation** (Art. 5(1)(e)) | TTL 2h pour les données brutes, 7j pour les agrégats volume constant, données individuelles non conservées longtemps |
| **Tracking inter-sites** | Absent : l'analyse est limitée au trafic propre du serveur, sans corrélation avec d'autres sites |
**Comparaison avec les alternatives** : les solutions de détection de bots côté client (JavaScript fingerprinting, CAPTCHA) impliquent l'exécution de code sur l'appareil de l'utilisateur et la collecte de données de dispositif (canvas fingerprint, WebGL, résolution d'écran) données personnelles au sens du RGPD selon plusieurs avis de la CNIL et du WP29. L'approche passive réseau est structurellement plus favorable à la protection de la vie privée.
### 6.4 Scalabilité et performances
#### Performances ClickHouse
[ClickHouse](https://clickhouse.com/docs/en/intro) avec moteur **AggregatingMergeTree** permet :
- Ingestion en temps réel : ~100 000 requêtes/seconde sur matériel standard (serveur 16 cœurs, 64 Go RAM)
- TTL 2h brut / 7j agrégé : volume de données constant, pas de croissance non bornée
- Opérations ARRAY (`arrayIntersect`, `arrayUnion`, `groupArray`, `arrayMap`) : nativement optimisées dans ClickHouse via SIMD et vectorisation
#### Performances du pipeline ML
| Composant | Temps d'exécution | Conditions |
|-----------|------------------|------------|
| 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 (anomalies) | ~100 ms | ~34 000 sessions, espace latent AE |
| HDBSCAN (profiling) | ~25 s | Quotidien, ~200k sessions H2 dédupliquées, min_cluster=1000 |
| Dynamic matcher scoring | < 1 ms | Par session, lookup en mémoire contre ~510 profils |
| GraphSAGE (fleet.py) | ~80 ms | Graphe d'IPs, 2 couches SAGEConv, GPU/CPU |
| Fusion LR LR | < 10 ms | Régression logistique, négligeable |
| **Cycle complet** | **~300 secondes** | EIF + AE + XGBoost + HDBSCAN + GraphSAGE |
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.
#### Limites de scalabilité
**fleet.py — graphe d'IPs avec PyTorch Geometric** :
- Le module utilise **PyTorch Geometric** (PyG) pour la construction et l'inférence du graphe, éliminant toute dépendance à NetworkX
- En full-batch (≤ 50 000 nœuds) : les tensors (`x`, `edge_index`) résident en mémoire GPU/CPU de manière compacte (COO sparse), complexité O(V + E)
- Au-delà de 50 000 nœuds, le **Neighbor Sampling** (`NeighborLoader`) échantillonne le voisinage de chaque mini-batch (num_neighbors=[25, 10], batch_size=4096), réduisant la complexité mémoire à O(batch × k²) par batch indépendant de la taille du graphe
- **Scalabilité théorique** : des graphes de millions de nœuds (infrastructure CDN, trafic massif) restent traitables sur GPU standard, PyG exploitant les opérations scatter/gather vectorisées CUDA
**HDBSCAN sur l'espace latent AE** :
- Complexité temporelle : O(n log n) pour n sessions
- À 34 000 sessions/cycle : ~100 ms acceptable
- À 500 000 sessions/cycle (scaling ×15) : ~2 s encore tolérable
**Fusion LR logistic regression** : O(n × d) entraînement, d = 3 features d'entrée (scores EIF, AE, XGBoost). Temps négligeable quelle que soit la taille.
**Limite architecturale principale** : le modèle XGBoost hebdomadaire nécessite un jeu de labels accumulés via le feedback SOC. À faible volume de labels (< 500 sessions étiquetées par semaine), XGBoost ne converge pas correctement. Ce problème est partiellement atténué par le filtrage Cleanlab qui élimine les labels douteux (détail §3.8), mais reste identifié comme axe d'amélioration futur 6.6 online learning).
**Overhead de l'uprobe SSL_read** : un uprobe attaché à `SSL_read` se déclenche à *chaque* appel de lecture TLS, y compris pour les gros transferts de fichiers (images, vidéos, scripts JS volumineux), une seule requête peut générer des dizaines d'appels `SSL_read` successifs transportant des frames HTTP/2 DATA sans intérêt pour le fingerprinting. Sous forte charge (> 10 000 connexions TLS actives simultanées), cet overhead peut dégrader les performances du serveur web de manière mesurable. Les mitigations recommandées sont : (1) filtrer côté eBPF les invocations dont le buffer ne contient pas les magic bytes HTTP/2 ou HTTP/1.x (`GET `, `POST `, etc.) avant de soumettre au ring buffer ; (2) ignorer les frames HTTP/2 de type DATA de grande taille (longueur payload > 16 384 octets) qui ne contiennent pas d'en-têtes de requête ; (3) appliquer du sampling probabiliste (ex. 1 appel sur 10) pour les connexions déjà identifiées par leur JA4 comme des navigateurs légitimes connus.
### 6.5 Limites des techniques proposées
Analyse systématique des limites de chaque technique proposée, avec quantification et mesures d'atténuation :
| Technique | Limite principale | Condition de déclenchement | Mesure d'atténuation |
|-----------|-------------------|---------------------------|---------------------|
| **5.1** Session Transformer Embedding | Nécessite ≥ 2 requêtes pour un embedding non-nul ; qualité dépendante du pré-entraînement | Sessions single-request, modèle non entraîné | Fallback vers vecteur nul (32 zéros) pour sessions ≤ 1 requête |
| **5.2** Bipartite Fleet Graph | Contrainte mémoire O(V+E) à l'échelle | > 100k JA4/ASN distincts par cycle | Représentation sparse, seuil `min_ips`, réinitialisation par cycle |
| **5.3** Cadence Fingerprint | Insuffisant pour les sessions single-request | Bots qui font exactement 1 requête par cycle | Agrégation des sessions multi-cycles par IP sur 24h |
| **5.4** Resource Dependency Tree | Requiert une classification correcte Content-Type/extension | Chemins sans extension, Content-Type ambigu (`*/*`) | Double-source : en-tête Accept + regex extension chemin |
| **5.5** JA4 Drift | Nécessite ≥ 3 segments de 10 min (session ≥ 30 min) | Sessions courtes, reconnaissance rapide | Flag `ja4_drift_insufficient_data` + NULL imputation |
| **5.6** DNS Shadow Analysis (`[todo]`) | DoH rend l'observation DNS impossible pour ~20 % des clients modernes | Clients Chrome avec DoH activé par défaut, Firefox DNS-over-HTTPS | Cross-référence IPs de fournisseurs DoH connus (1.1.1.1, 8.8.8.8) |
| **5.7** Compression Ratio Invariant (`[todo]`) | Interférence avec la compression CDN | Sessions `has_xff = 1` (CDN recompresse) | Désactivation pour sessions CDN ; instrumentation avant CDN si architecture le permet |
| **5.8** Cross-Domain Session Linking | Scénarios NAT / IP partagée (multiples utilisateurs derrière la même IP) | Réseaux d'entreprise, CGNAT opérateurs mobiles | Feature `src_port_diversity` comme discriminant (NAT montre haute diversité de ports source) |
#### Scénario NAT détaillé (§5.8)
Dans un réseau d'entreprise sous NAT, 200 utilisateurs partagent une seule IP publique. Leurs navigations sur des intranet/extranet hébergés sur le même serveur Apache produiraient une `host_diversity` artificielle de 515 hôtes — fausse alarme. La feature discriminante est `src_port_diversity` :
```sql
src_port_diversity = uniqExact(src_port) OVER (PARTITION BY src_ip, time_window)
```
Un seul utilisateur réel alterne quelques connexions (26 ports source actifs). 200 utilisateurs NAT partagent l'IP mais utilisent des milliers de ports source différents (src_port_diversity élevée). Cette feature est présente dans la famille F1 (réseau/transport) et constitue le discriminant naturel contre les faux positifs NAT de §5.8.
### 6.6 Absence d'évaluation quantitative
Ce document présente un système opérationnel déployé en production, mais souffre d'une lacune majeure : **il ne fournit pas de métriques d'évaluation standardisées** permettant de mesurer objectivement la performance de détection.
**Métriques absentes** :
- F1-score, Precision, Recall, ROC-AUC, PR-AUC
- Matrice de confusion sur un jeu de test labellisé
- Taux de faux positifs et faux négatifs par seuil de décision
- Comparaison avec des baselines publiques (datasets CICIDS2017, CTU-13, ou benchmarks récents)
**Le chiffre de "777 anomalies par cycle (≈ 2,3 %)"** est un compteur opérationnel brut : il mesure le nombre de sessions dépassant le seuil d'anomalie configuré, mais ne distingue pas les vrais positifs des faux positifs. En l'absence de ground truth systématique, ce chiffre ne constitue pas un indicateur de performance de détection.
**Conséquence** : les choix architecturaux (EIF bifurqué, ensemble triple-voix, poids de la fusion LR) sont motivés par des arguments qualitatifs et l'expérience opérationnelle, mais ne sont pas validés par une évaluation quantitative contrôlée. La priorité immédiate pour les travaux futurs est l'établissement d'un protocole d'évaluation sur un dataset labellisé, avec comparaison contre des baselines (Isolation Forest seul, XGBoost seul, LOF, One-Class SVM).
### 6.7 Travaux futurs et roadmap
#### Priorité 1 — Extension du vecteur de features
**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`)
- Profiling dynamique : `[impl.]` — moteur HDBSCAN hors-ligne (`profile_builder.py`, 614 lignes) + scorer temps réel (`browser_matcher_dynamic.py`, 387 lignes). Les profils auto-appris dans `auto_browser_profiles` s'adaptent automatiquement aux nouvelles versions de navigateurs, éliminant la maintenance manuelle du dictionnaire statique.
- Travail restant : monitoring de la convergence des clusters dynamiques, validation croisée entre scores statique et dynamique
**DNS Shadow Analysis (§5.6)** :
- État actuel : `[todo]` non implémenté
- Travail requis : extension de `ja4ebpf` pour capture UDP/53 + TCP/53, table ClickHouse `dns_resolutions`, corrélation avec table `sessions`
- Contraintes techniques : nécessite accès privilégié au trafic réseau niveau interface (pcap ou eBPF)
- Estimation : 68 semaines de développement + tests de charge
**Compression Ratio Invariant (§5.7)** :
- État actuel : `[todo]` non implémenté
- Travail requis : module Apache custom pour logging des tailles pré/post-compression, table ClickHouse dédiée
- Estimation : 23 semaines de développement
#### Priorité 2 — Améliorations des modèles ML
**β-VAE en remplacement de l'AE standard** :
Un Variational Autoencoder bêta ([β-VAE, Higgins et al., 2017](https://openreview.net/forum?id=Sy2fchgwl)) structure l'espace latent en imposant une contrainte KL-divergence pondérée par β sur la distribution latente. Cette structure améliore la qualité du score d'anomalie via la divergence KL par rapport à N(0,1), permettant une détection plus fine des anomalies "lentes" (bots qui imitent le comportement humain mais dérivent progressivement).
**Modélisation des phases d'attaque** :
Des modèles d'état-espace pour la modélisation des phases d'attaque — permet de détecter explicitement les transitions de phase (reconnaissance → exploitation) au lieu de seulement scorer chaque session isolément. Complémentaire au signal JA4 Drift (§5.5).
**t-digest pour la dérive conceptuelle** :
Remplacement de l'approximation à 5 quantiles actuellement utilisée pour la détection de drift ([quantile_drift_score]) par la structure **t-digest** , qui supporte les distributions bimodales et les queues longues avec précision adaptative. Critique pour les features à distribution bimodale comme `hit_velocity` (distribution séparée bots/humains).
**XGBoost → online learning** :
Remplacement du ré-entraînement hebdomadaire XGBoost par un apprentissage incrémental (gradient boosting online, par exemple [XGBoost Federated](https://xgboost.readthedocs.io/en/stable/tutorials/federated_learning.html) ou RIVER framework) permettant des mises à jour par cycle au lieu d'attendre l'accumulation d'une semaine de labels.
#### Priorité 3 — Infrastructure et protocoles émergents
**HTTP/3 (QUIC)** :
HTTP/3 ([RFC 9114](https://www.rfc-editor.org/rfc/rfc9114)) transporte HTTP sur **QUIC** plutôt que TCP. QUIC est un protocole de transport multiplexé et chiffré (UDP-based, TLS 1.3 intégré). Le fingerprinting passif HTTP/3 nécessite une capture différente (UDP au lieu de TCP) et un décodage QUIC. Actuellement hors périmètre — à intégrer lorsque la part de trafic HTTP/3 dépasse 20 % de la baseline.
**Fingerprinting IPv6** :
Les champs spécifiques à IPv6 (extension headers, Hop Limit ≠ TTL IPv4, adresses link-local) constituent des signatures passives supplémentaires. L'analyse du Hop Limit IPv6 est analogue à l'analyse TTL IPv4 mais avec des valeurs initiales différentes.
**TLS 1.3 0-RTT** :
La reprise de session **0-RTT** ([RFC 8446 §2.3](https://www.rfc-editor.org/rfc/rfc8446)) permet d'envoyer des données applicatives dans le premier paquet TLS, avant la completion du handshake. Ces sessions ne contiennent pas de ClientHello complet → fingerprinting JA4 impossible. Traitement spécial requis dans l'EIF (feature `is_0rtt_session` = 1, dimensions TLS neutralisées).