diff --git "a/\004" "b/\004" new file mode 100644 index 0000000..674dd40 Binary files /dev/null and "b/\004" differ diff --git a/docs/THESIS_HTTP_Traffic_Detection.md b/docs/THESIS_HTTP_Traffic_Detection.md index 585705c..e30a7b9 100644 --- a/docs/THESIS_HTTP_Traffic_Detection.md +++ b/docs/THESIS_HTTP_Traffic_Detection.md @@ -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 85 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 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. **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 @@ -121,7 +121,7 @@ Ce document décrit une architecture opérationnelle positionnée à la frontiè 7. **8 features de thèse** : déviation de Benford sur les intervalles inter-requêtes, entropie de transition de chemins, autocorrélation lag-1, délai root-to-first-asset, diversité de hosts, uniformité de couverture cross-host 8. **Graphes bipartis NetworkX** pour la détection de flottes (Part B) -La suite de ce document est organisée comme suit : la Section 2 passe en revue l'état de l'art des techniques de détection. La Section 3 décrit l'architecture complète du pipeline. La Section 4 présente la taxonomie exhaustive des 85 features en 8 familles. Les Sections 5–8 (Part B) couvrent les techniques originales, les résultats expérimentaux et les perspectives. +La suite de ce document est organisée comme suit : la Section 2 passe en revue l'état de l'art des techniques de détection. La Section 3 décrit l'architecture complète du pipeline. La Section 4 présente la taxonomie exhaustive des 96 features en 8 familles. Les Sections 5–8 (Part B) couvrent les techniques originales, les résultats expérimentaux et les perspectives. --- @@ -415,7 +415,7 @@ XGBoost ([Chen & Guestrin, 2016](https://arxiv.org/abs/1603.02754)) est un algor **Limites des approches supervisées** : - **Concept drift** : un modèle entraîné sur des bots de 2024 peut être aveugle aux nouvelles techniques de 2025 - **Rareté des étiquettes** : annoter manuellement des millions de sessions HTTP est coûteux et sujet à erreur -- **Biais de jeu de données** : les modèles entraînés sur des données de laboratoire (CICIDS2017, NSL-KDD) généralisent mal au trafic en production, comme le souligne le [benchmark MAWIFlow 2025 (Schraven et al.)](https://arxiv.org/abs/2501.12345) +- **Biais de jeu de données** : les modèles entraînés sur des données de laboratoire (CICIDS2017, NSL-KDD) généralisent mal au trafic en production, comme le souligne le benchmark MAWIFlow 2025 (Schraven et al. [Référence à vérifier / Identifier le vrai papier]) - **Attaque par évasion adversariale** : un attaquant ayant accès ou connaissance du modèle peut crafting des sessions qui maximisent le score de légitimité #### 2.4.2 Approches semi-supervisées @@ -461,8 +461,8 @@ Résultat : les coupes ne sont plus liées aux axes, éliminant les artéfacts g Deux modèles EIF s'exécutent en parallèle à chaque cycle de 300 secondes : -- **Modèle Complet** (≈ 45 features, L3→L7) : appliqué sur les sessions corrélées (correlated=1) pour lesquelles ja4ebpf a pu corréler les métadonnées TCP/TLS avec la requête HTTP. Inclut toutes les features des familles F1–F7. -- **Modèle Applicatif** (≈ 35 features, L7 uniquement) : appliqué sur les sessions non corrélées (correlated=0) — trafic passant par un CDN ou proxy qui ne permet pas la corrélation TCP/TLS. Zeroed les features TCP/TLS pour ce modèle éviterait d'introduire un biais systématique de zéro-imputation. +- **Modèle Complet** (≈ 45 features, L3→L7) : appliqué sur les sessions pour lesquelles ja4ebpf a pu corréler les métadonnées TCP/TLS avec la requête HTTP (données L3/L4 disponibles). Inclut toutes les features des familles F1–F7. +- **Modèle Applicatif** (≈ 35 features, L7 uniquement) : appliqué sur les sessions dont les données TCP/TLS sont absentes — trafic passant par un CDN ou proxy qui ne permet pas la corrélation TCP/TLS. Utiliser les features TCP/TLS imputées à zéro pour ce modèle introduirait un biais systématique. La bifurcation est justifiée par le fait que les features TCP/TLS ne sont disponibles que lorsque ja4ebpf a corrélé la connexion réseau avec la requête HTTP. Imputer ces features à zéro pour le trafic non corrélé créerait un signal artificiel (zéro n'est pas neutre pour un EIF — il est interprété comme une valeur réelle). @@ -505,7 +505,7 @@ Pour un VAE, la régularisation KL(q(z|x) || p(z)) pénalise l'encodeur si sa di **Complémentarité AE + IF** -Comme le démontrent [Jamshidi et al. (arXiv, novembre 2025)](https://arxiv.org/abs/2511.12345) et [Basbous et al. (arXiv, mars 2026)](https://arxiv.org/abs/2603.12345) : +Comme le démontrent Jamshidi et al. (arXiv, novembre 2025) [Référence à vérifier / Identifier le vrai papier] et Basbous et al. (arXiv, mars 2026) [Référence à vérifier / Identifier le vrai papier] : | Critère | Isolation Forest (EIF) | Autoencoder (AE) | |---------|------------------------|------------------| @@ -572,12 +572,12 @@ Le MetaLearner est une régression logistique activée lorsqu'au moins 1 000 ét Régression logistique : modèle linéaire probabiliste qui apprend des poids w pour chaque signal intermédiaire en minimisant l'entropie croisée binaire sur les étiquettes accumulées : ``` -P(bot) = σ(w1×eif + w2×ae + w3×xgb + w4×volume + w5×correlated + bias) +P(bot) = σ(w1×eif + w2×ae + w3×xgb + w4×volume + bias) ``` où σ est la fonction sigmoïde : σ(z) = 1 / (1 + e^{-z}) -Les poids w1–w5 sont appris, permettant au système de calibrer automatiquement l'importance relative de chaque voix en fonction du type de trafic en production. En dessous de 1 000 étiquettes, le système revient aux poids fixes : `(eif: 0.50, ae: 0.30, xgb: 0.20)`. +Les poids w1–w4 sont appris, permettant au système de calibrer automatiquement l'importance relative de chaque voix en fonction du type de trafic en production. En dessous de 1 000 étiquettes, le système revient aux poids fixes : `(eif: 0.50, ae: 0.30, xgb: 0.20)`. **Calendrier de retraining** : - XGBoost : hebdomadaire sur les étiquettes accumulées @@ -622,7 +622,7 @@ où F1 et F2 sont les ECDFs de la distribution courante et de la distribution de #### 2.4.4 Régime d'attaque probabiliste (PARD-SSM) -[Hiremath et al. (arXiv, avril 2026)](https://arxiv.org/abs/2604.12345) proposent des Variational Switching State-Space Models (PARD-SSM) pour la modélisation des phases d'attaque : Reconnaissance → Mouvement latéral → Intrusion → Exfiltration. Cette approche modélise les transitions de phase comme un processus de Markov caché où l'état latent (phase d'attaque) est inféré depuis les observations (features de trafic). L'enrichissement du clustering HDBSCAN avec ce signal de phase permettrait de distinguer des campagnes en phase de reconnaissance de campagnes en phase d'exploitation active. +Hiremath et al. (arXiv, avril 2026) [Référence à vérifier / Identifier le vrai papier] proposent des Variational Switching State-Space Models (PARD-SSM) pour la modélisation des phases d'attaque : Reconnaissance → Mouvement latéral → Intrusion → Exfiltration. Cette approche modélise les transitions de phase comme un processus de Markov caché où l'état latent (phase d'attaque) est inféré depuis les observations (features de trafic). L'enrichissement du clustering HDBSCAN avec ce signal de phase permettrait de distinguer des campagnes en phase de reconnaissance de campagnes en phase d'exploitation active. #### 2.4.5 Explicabilité par SHAP et ExIFFI @@ -640,7 +640,7 @@ où F est l'ensemble de toutes les features, S est un sous-ensemble, et f(S) est **ExIFFI (Extended Isolation Forest Feature Importance)** -[ExIFFI (Frizzo et al., 2024)](https://arxiv.org/abs/2406.12345) est une méthode native d'importance des features pour EIF, basée sur la profondeur moyenne d'isolation par feature. Principe : une feature ayant une profondeur d'isolation moyenne faible (isole rapidement les anomalies) est plus importante pour la détection. Activé comme fallback lorsque SHAP n'est pas disponible. Comparé aux top-5 SHAP dans l'interface SOC. +ExIFFI (Frizzo et al., 2024) [Référence à vérifier / Identifier le vrai papier] est une méthode native d'importance des features pour EIF, basée sur la profondeur moyenne d'isolation par feature. Principe : une feature ayant une profondeur d'isolation moyenne faible (isole rapidement les anomalies) est plus importante pour la détection. Activé comme fallback lorsque SHAP n'est pas disponible. Comparé aux top-5 SHAP dans l'interface SOC. **Erreur de reconstruction AE par dimension** : `(xi - x̂i)²` par dimension d'entrée identifie quelles features contribuent à l'anomalie AE. Cela fournit une explicabilité locale pour chaque session anormale : les features dont la reconstruction est la plus dégradée sont les plus discriminantes. @@ -780,7 +780,7 @@ httpcloak est un outil d'évasion qui tente d'imiter l'empreinte TLS de Chrome. | Listes IP/ASN | Botnets résidentiels échappent aux blacklists | ASN = feature parmi d'autres, pas bloquant seul | | JA3 | Instabilité GREASE, collisions inter-versions | JA4 (GREASE filtré, trié), ratio JA3/JA4 comme feature | | JS challenges | Contournés par BotBrowser/CloakBrowser | Architecture 100 % passive, HTTP/2 fingerprinting | -| UA matching | Trivial à usurper | UA est une parmi 85 features, cohérence cross-layer | +| UA matching | Trivial à usurper | UA est une parmi 96 features, cohérence cross-layer | | ML supervisé seul | Concept drift, label scarcity | Semi-supervisé EIF + AE + retraining adaptatif | | Isolation Forest std | Ghost clusters en haute dimension | Extended Isolation Forest (hyperplans aléatoires) | | AE seul | Ne détecte pas les anomalies ponctuelles | Ensemble EIF + AE complémentaires | @@ -826,7 +826,7 @@ httpcloak est un outil d'évasion qui tente d'imiter l'empreinte TLS de Chrome. │ request tracking │ │ Timeout orphelin │ │ 500ms │ - │ correlated ∈{0,1}│ + │ L3/L4 ou L7 seul │ └─────────┬─────────┘ │ ┌─────────▼─────────────────────────────┐ @@ -879,9 +879,7 @@ httpcloak est un outil d'évasion qui tente d'imiter l'empreinte TLS de Chrome. **Composants clés** : -**libpcap** : bibliothèque C portative sous licence BSD pour la capture de paquets réseau. Opère au niveau des sockets bruts (raw sockets), capturant les paquets depuis l'interface réseau avant qu'ils atteignent la pile réseau du noyau OS. Utilisée par Wireshark, Zeek, Suricata, tcpdump. API : `pcap_open_live()`, `pcap_loop()`, `pcap_compile()` (filtres BPF). - -**CAP_NET_RAW** : capacité Linux permettant à un processus de capturer des paquets bruts (équivalent fonctionnel de `root` pour la capture réseau) sans accorder les privilèges root complets. Fait partie du framework Linux Capabilities ([man capabilities(7)](https://man7.org/linux/man-pages/man7/capabilities.7.html)), qui découpe les privilèges root en unités indépendantes pouvant être accordées séparément. +**uprobe eBPF** : mécanisme du noyau Linux permettant d'attacher dynamiquement une sonde eBPF à n'importe quelle fonction en espace utilisateur (par exemple `SSL_read` d'OpenSSL/BoringSSL), en utilisant l'infrastructure de breakpoints du noyau. L'uprobe intercepte l'appel à l'entrée ou à la sortie de la fonction cible, copie ses arguments ou sa valeur de retour dans un ring buffer eBPF, et rend le contrôle immédiatement — sans modifier le code source du processus cible, sans le mettre en pause, et sans nécessiter de recompilation. Dans **ja4ebpf**, l'uprobe sur `SSL_read` capture le buffer de données déchiffrées avant qu'il soit consommé par le serveur web (Apache, Nginx, Varnish, HAProxy), rendant l'interception totalement transparente côté applicatif. **AggregatingMergeTree (ClickHouse)** : moteur de table ClickHouse spécialisé pour l'agrégation incrémentale. Contrairement à un merge ordinaire (qui fusionne des lignes brutes), il fusionne des états d'agrégation partiels (`AggregateFunction` columns) — permettant à `SUM`, `AVG`, `uniqCombined`, etc. d'être calculés correctement même si les données arrivent dans le désordre. Cela permet des vues matérialisées en temps réel à faible latence : chaque cycle d'insertion met à jour l'état partiel, et la vue finale est calculée à la demande en fusionnant tous les états partiels. @@ -936,7 +934,9 @@ La couche L7 constitue la couche la plus riche en features comportementales. L'a Données capturées par ja4ebpf : `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, ja4ebpf identifie le protocole via le Go Magic Bytes dispatcher qui reconnaît le preface `PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n` dans le flux SSL_read déchiffré. Le parser HTTP/2 extrait ensuite les frames depuis ce flux déchiffré sans aucune instrumentation côté serveur web : +**Fingerprinting HTTP/2 passif intégré** : pour les connexions HTTP/2, l'uprobe sur `SSL_read` retourne un flux d'octets bruts déchiffrés qui **ne respecte pas les frontières des trames HTTP/2**. En raison de la fragmentation TCP et du buffering TLS, un seul appel `SSL_read` peut contenir un fragment partiel de trame, plusieurs trames complètes, ou une combinaison des deux. Le **Go Magic Bytes dispatcher** maintient donc un **buffer circulaire de réassemblage** par connexion (identifiée par `src_ip:src_port`) : il accumule les données de plusieurs appels `SSL_read` successifs jusqu'à ce que la logique de parsing HTTP/2 confirme qu'une trame complète est disponible (9 octets d'en-tête + longueur payload déclarée). L'identification du protocole HTTP/2 se fait en cherchant la connection preface `PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n` dans le buffer accumulé. Tout le parsing lourd — décodage des trames, HPACK pour les pseudo-headers — s'effectue dans l'agent Go en **espace utilisateur**, et non dans la VM eBPF (dont la complexité est limitée par le vérificateur noyau). Ce découplage est essentiel : la VM eBPF collecte les octets bruts le plus rapidement possible, et le parsing est réalisé de manière asynchrone côté Go sans jamais interrompre le flux applicatif du serveur web. + +Une fois les trames complètes reconstituées, le parser Go en extrait les éléments suivants du preface client : - Les 7 paramètres SETTINGS individuels (IDs 1–6 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 @@ -972,9 +972,9 @@ Toutes les features des familles F1–F6 et F8 proviennent de cette couche, agr **Gestion du HTTP Keep-Alive** : une connexion TCP peut transporter plusieurs requêtes HTTP successives. ja4ebpf maintient un gestionnaire de corrélation in-memory organisé en 256 shards (partitionnement par hash de src_ip pour éviter la contention). Chaque requête HTTP capturée via l'uprobe SSL_read est associée à l'enregistrement TCP/TLS ouvert correspondant, et `max_keepalives` est incrémenté. Un GC toutes les 100 ms libère les sessions expirées. -**Timeout orphelin** : si aucun enregistrement réseau ne correspond à une requête HTTP dans les 500 ms, la requête est enregistrée comme orpheline (`correlated=0`). Cela se produit quand le trafic arrive via un CDN ou un proxy inverse qui établit une nouvelle connexion TCP entre le proxy et le serveur, rendant l'adresse source TCP celle du proxy plutôt que celle du client original. +**Timeout orphelin** : si aucun enregistrement réseau (L3/L4) ne peut être associé à une requête HTTP dans les 500 ms — ce qui se produit quand le trafic arrive via un CDN ou un proxy inverse établissant une nouvelle connexion TCP entre le proxy et le serveur — la session est exportée avec uniquement les données HTTP disponibles. Les champs TCP/TLS restent absents dans l'enregistrement ClickHouse, et les features correspondantes sont imputées à zéro dans le pipeline ML. -**Conséquences pour le pipeline ML** : les sessions `correlated=0` alimentent le Modèle Applicatif EIF (≈ 35 features L7 uniquement) et le XGBoost non-corrélé, évitant le biais d'imputation à zéro des features TCP/TLS. +**Conséquences pour le pipeline ML** : pour les sessions dont les données TCP/TLS sont absentes (proxy CDN, load balancer avec terminaison TLS), le Modèle Applicatif EIF (≈ 35 features L7 uniquement) est utilisé à la place du Modèle Complet (≈ 45 features L3→L7), évitant le biais d'imputation à zéro des features réseau. **Impact sur HTTP/2** : quand `has_xff=1` (en-tête X-Forwarded-For présent, indiquant un proxy CDN), les dimensions H2 du browser_matcher sont neutralisées à 0.5 (score neutre). Le CDN réouvre sa propre connexion HTTP/2 vers le serveur d'origine ; les SETTINGS HTTP/2 capturés sont ceux du CDN (Cloudflare, Akamai), pas du client original. @@ -1043,10 +1043,10 @@ La valeur `percentile_5` du historique des scores négatifs (anomalies confirmé | Modèle | Features | Trafic applicable | Indicateur | |--------|----------|-------------------|------------| -| EIF Complet | ≈ 45 features L3→L7 | correlated=1 | eif_score_full | -| EIF Applicatif | ≈ 35 features L7 | correlated=0 | eif_score_app | +| EIF Complet | ≈ 45 features L3→L7 | Données L3/L4 disponibles | eif_score_full | +| EIF Applicatif | ≈ 35 features L7 | L3/L4 absentes (CDN/proxy) | eif_score_app | | AE | Même dimensionnalité que EIF actif | Toutes sessions | ae_reconstruction_error | -| XGBoost | Ensemble complet 85 features | Toutes sessions | xgb_probability | +| XGBoost | Ensemble complet 96 features | Toutes sessions | xgb_probability | #### Niveaux de sévérité @@ -1099,7 +1099,7 @@ 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 le serveur web, le flux HTTP/2 est déchiffré et disponible en clair dans le contexte d'OpenSSL/BoringSSL. Le fingerprinting passif est réalisé par **ja4ebpf** via un uprobe sur `SSL_read`. Lorsque le Go Magic Bytes dispatcher détecte le magic HTTP/2 (`PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n`) dans le flux déchiffré, le parser H2 extrait les frames SETTINGS, WINDOW_UPDATE et HEADERS du preface client, sans modifier ni interrompre le flux. Cette approche est agnostique au serveur web (Apache, Nginx, Varnish, HAProxy) et ne nécessite aucun module natif installé côté serveur. +Après terminaison TLS par le serveur web, le flux HTTP/2 est déchiffré et disponible en clair dans le contexte d'OpenSSL/BoringSSL. Le fingerprinting passif est réalisé par **ja4ebpf** via un uprobe sur `SSL_read`. Cependant, `SSL_read` retourne des octets bruts déchiffrés sans respecter les frontières des trames HTTP/2 — la fragmentation TCP et le buffering TLS signifient qu'un seul appel peut correspondre à un fragment de trame ou à plusieurs trames complètes. Le **Go Magic Bytes dispatcher** maintient un **buffer circulaire de réassemblage** par connexion, accumulant les données de plusieurs appels `SSL_read` jusqu'à ce que la logique de parsing HTTP/2 confirme qu'une trame complète est disponible (9 octets d'en-tête de trame + longueur payload). L'identification du preface `PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n` se fait dans ce buffer accumulé. Tout le parsing des trames SETTINGS, WINDOW_UPDATE et HEADERS (y compris le décodage HPACK partiel pour extraire l'ordre des pseudo-headers) s'effectue dans l'agent Go en espace utilisateur, et non dans la VM eBPF. Cette approche est agnostique au serveur web (Apache, Nginx, Varnish, HAProxy) et ne nécessite aucun module natif installé côté serveur. #### Frame SETTINGS @@ -1451,7 +1451,7 @@ WHERE browser_match_max < 0.45 ## 4. Taxonomie des features de détection -Les 85 features sont organisées en 8 familles couvrant les couches L3→L7. Chaque feature est définie par sa formule de calcul, son signal discriminant, ses plages de valeurs typiques (humain vs. bot), et son statut d'implémentation. +Les 96 features sont organisées en 8 familles couvrant les couches L3→L7. Chaque feature est définie par sa formule de calcul, son signal discriminant, ses plages de valeurs typiques (humain vs. bot), et son statut d'implémentation. **Légende des statuts** : - `[impl.]` Implémenté et validé en production @@ -1585,11 +1585,7 @@ La famille 2 capture la diversité des patterns d'accès, distinguant les compor #### ja4_drift_ratio `[impl.]` (§5.5) -**Calcul** : `COUNT(transitions du JA4 dominant entre segments temporels) / (nb_segments - 1)` - -La session est divisée en segments de N requêtes. Le JA4 dominant de chaque segment est calculé (mode). `ja4_drift_ratio` compte les transitions entre JA4 dominants consécutifs, normalisé par le nombre de transitions possibles. - -**Signal** : un humain avec un seul navigateur a un ratio de 0. Un bot qui change de configuration TLS entre différentes phases d'activité produit un ratio proche de 1. +*Voir définition complète dans la Famille 8 (Features de thèse). Comptabilisée ici pour des raisons historiques d'agrégation.* --- @@ -1863,7 +1859,7 @@ La famille 6 capture le comportement de navigation macroscopique sur la fenêtre #### orphan_ratio `[impl.]` -**Calcul** : `COUNT(requêtes HTTP avec correlated=0) / hits` +**Calcul** : `COUNT(requêtes HTTP sans données L3/L4 associées) / hits` **Signal** : ratio élevé = trafic majoritairement via proxy/CDN cassant la corrélation L4↔L7. Peut masquer des signaux TLS/TCP. Feature informative pour le MetaLearner. @@ -2101,7 +2097,13 @@ où f_observed(d) est la fréquence observée du premier chiffre d dans la séri #### ja4_drift_ratio `[impl.]` -Note : cette feature apparaît également dans la Famille 2 où elle est référencée. Elle est calculée dans `view_thesis_features_1h` et incluse dans F8 pour les fenêtres temporelles élargies. Voir §2.2.3 pour la définition complète. +**Calcul** : `COUNT(transitions du JA4 dominant entre segments temporels) / (nb_segments - 1)` + +La session est divisée en segments de N requêtes. Le JA4 dominant de chaque segment est calculé (mode). `ja4_drift_ratio` compte les transitions entre JA4 dominants consécutifs, normalisé par le nombre de transitions possibles. La feature est calculée dans `view_thesis_features_1h` (fenêtres temporelles étendues d'une heure). + +**Signal** : un humain avec un seul navigateur a un ratio de 0. Un bot qui change de configuration TLS entre différentes phases d'activité (reconnaissance → exploitation) produit un ratio proche de 1. Voir §5.5 pour la description complète et le contexte de détection des bots APT multi-phases. + +**Plages typiques** : humain = 0 ; bot multi-phase = 0,5–1,0 ; bot TLS aléatoire = proche de 1,0. #### host_diversity `[impl.]` @@ -2888,7 +2890,7 @@ Le fingerprinting réseau opère sans déchiffrement TLS (les métadonnées TLS | Composant | Temps d'exécution | Conditions | |-----------|------------------|------------| -| EIF training | < 2 secondes | ~34 000 sessions, 85 features | +| 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 | @@ -2913,6 +2915,8 @@ La durée du cycle (300 s = 5 minutes) est contrainte principalement par la **fe **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 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), où 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 : @@ -2965,10 +2969,10 @@ Un seul utilisateur réel alterne quelques connexions (2–6 ports source actifs 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). **PARD-SSM (Hiremath et al., 2026)** : -Modèle d'état-espace pour la modélisation des phases d'attaque ([arxiv:2604.12345](https://arxiv.org/abs/2604.12345)) — 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). +Modèle d'état-espace pour la modélisation des phases d'attaque [Référence à vérifier / Identifier le vrai papier] — 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** ([Dunning & Ertl, 2019](https://arxiv.org/abs/1902.04023)), 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). +Remplacement de l'approximation à 5 quantiles actuellement utilisée pour la détection de drift ([quantile_drift_score]) par la structure **t-digest** (Dunning & Ertl, 2019 [Référence à vérifier / Identifier le vrai papier]), 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. @@ -2992,9 +2996,9 @@ La reprise de session **0-RTT** ([RFC 8446 §2.3](https://www.rfc-editor.org/rfc Cette thèse présente une architecture de détection de bots HTTP opérationnelle, validée en production sur des serveurs Apache exposés à un trafic réel. Les contributions principales sont les suivantes. -#### Contribution 1 : Architecture multi-couches L3–L7 avec 85 features +#### Contribution 1 : Architecture multi-couches L3–L7 avec 96 features -Un système de détection à couverture complète couvrant cinq couches réseau (L3 réseau : TTL, IP flags ; L4 transport : TCP window, seq patterns ; L5 session TLS : JA4 fingerprint, GREASE, ALPN ; L6 application HTTP : en-têtes, méthodes, User-Agent ; L7 comportemental : navigation, timing, séquences) avec 85 features réparties en 8 familles. Ce système est prouvé à l'échelle (3 M+ logs analysés, ~34 000 sessions/cycle, 5-minute cycle time). +Un système de détection à couverture complète couvrant cinq couches réseau (L3 réseau : TTL, IP flags ; L4 transport : TCP window, seq patterns ; L5 session TLS : JA4 fingerprint, GREASE, ALPN ; L6 application HTTP : en-têtes, méthodes, User-Agent ; L7 comportemental : navigation, timing, séquences) avec 96 features réparties en 8 familles. Ce système est prouvé à l'échelle (3 M+ logs analysés, ~34 000 sessions/cycle, 5-minute cycle time). **La bifurcation Modèle Complet / Modèle Applicatif** est une contribution architecturale spécifique : les sessions sans corrélation entre JA4 et comportement (trafic à travers CDN ou reverse proxy) sont traitées par un modèle séparé évitant les biais d'imputation de features manquantes. @@ -3008,7 +3012,7 @@ Un pipeline ML combinant : Le pipeline intègre un mécanisme de **détection de dérive conceptuelle** (basé sur le percentile 5 des scores négatifs) distinguant la dérive organique (évolution naturelle du trafic) de la dérive adversariale (manipulation intentionnelle de la distribution). -L'**explainabilité** est assurée par ExIFFI ([Frizzo et al., 2024](https://arxiv.org/abs/2406.12345) ; [Arcudi et al., 2023](https://arxiv.org/abs/2310.05422)) pour l'EIF et SHAP ([Lundberg & Lee, 2017](https://shap.readthedocs.io/)) pour XGBoost, permettant l'audit des décisions de blocage par l'équipe SOC. +L'**explainabilité** est assurée par ExIFFI (Frizzo et al., 2024 [Référence à vérifier / Identifier le vrai papier] ; Arcudi et al., 2023 [Référence à vérifier / Identifier le vrai papier]) pour l'EIF et SHAP ([Lundberg & Lee, 2017](https://shap.readthedocs.io/)) pour XGBoost, permettant l'audit des décisions de blocage par l'équipe SOC. #### Contribution 3 : Fingerprinting HTTP/2 passif structuré (browser_matcher) @@ -3039,30 +3043,27 @@ Architecture de données fondée sur ClickHouse avec **AggregatingMergeTree view ### État final d'implémentation -**Tableau récapitulatif des 85 features par famille** : +**Tableau récapitulatif des 96 features par famille** (taxonomie sémantique Section 4) : -| Famille | Features | `[impl.]` Impl. | `[partiel]` Partiel | `[todo]` Non impl. | -|---------|----------|----------|------------|-------------| -| F1 — Réseau/Transport (L3-L4) | ttl_value, tcp_window_size, src_port_diversity, … (10 features) | 10 | 0 | 0 | -| F2 — TLS/Fingerprint (L5) | ja4_fingerprint, grease_present, alpn_h2, tls_version, cipher_count, ext_count, … (12 features) | 12 | 0 | 0 | -| F3 — HTTP Headers (L6-base) | user_agent_present, accept_encoding_present, sec_fetch_present, header_order_hash, … (15 features) | 15 | 0 | 0 | -| F4 — Corrélations TLS×HTTP | tls_h2_family_mismatch, ja4_asn_concentration, ja4_country_diversity, … (8 features) | 8 | 0 | 0 | -| 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) | 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** | **70** | **5** | **2** + meta | +| Famille | Description | Features (exemples) | `[impl.]` | `[partiel]` | `[todo]` | +|---------|-------------|---------------------|-----------|-------------|---------| +| Famille 1 — Volumétrie et vitesse | Signaux de volume et cadence bruts | hits, hit_velocity, max_keepalives, count_login_post (4 features) | 4 | 0 | 0 | +| Famille 2 — Diversité et exploration | Diversité des ressources et des signatures réseau | fuzzing_index, path_diversity_ratio, url_depth_variance, distinct_ja4_count, distinct_header_orders, is_ua_rotating, ja4_drift_ratio (7 features) | 7 | 0 | 0 | +| Famille 3 — Authenticité protocolaire | Conformité aux standards des navigateurs modernes | modern_browser_score, ua_ch_mismatch, has_accept_language, has_cookie, has_referer, sec_fetch_absence_rate, et 6 autres (12 features) | 12 | 0 | 0 | +| 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 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** | -**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 ja4ebpf via le parser HTTP/2 du flux SSL_read. +**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. ### 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. -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. +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. --- @@ -3157,23 +3158,19 @@ Documentation officielle SHAP : [https://shap.readthedocs.io/](https://shap.read [20] **Frizzo, L., Giudici, P., & Zeni, G. (2024)** "ExIFFI: Interpretable Anomaly Detection with Extended Isolation Forest Feature Importance." -arXiv preprint arXiv:2406.12345. -[https://arxiv.org/abs/2406.12345](https://arxiv.org/abs/2406.12345) +[Référence à vérifier / Identifier le vrai papier] [21] **Arcudi, A., Rozzoli, M., & Zantedeschi, V. (2023)** "Extended Isolation Forest Feature Importance via Shapley Values." -arXiv preprint arXiv:2310.05422. -[https://arxiv.org/abs/2310.05422](https://arxiv.org/abs/2310.05422) +[Référence à vérifier / Identifier le vrai papier] [22] **Hiremath, S., Saxena, A., & Garg, P. (2026)** "PARD-SSM: Phase-Aware Recurrent Detection with State-Space Models for Network Intrusion." -arXiv preprint arXiv:2604.12345. -[https://arxiv.org/abs/2604.12345](https://arxiv.org/abs/2604.12345) +[Référence à vérifier / Identifier le vrai papier] [23] **Dunning, T., & Ertl, O. (2019)** "Computing Extremely Accurate Quantiles Using t-Digests." -arXiv preprint arXiv:1902.04023. -[https://arxiv.org/abs/1902.04023](https://arxiv.org/abs/1902.04023) +[Référence à vérifier / Identifier le vrai papier] [24] **Higgins, I., Matthey, L., Pal, A., Burgess, C., Glorot, X., Botvinick, M., Mohamed, S., & Lerchner, A. (2017)** "β-VAE: Learning Basic Visual Concepts with a Constrained Variational Framework." diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 0000000..e4b6a05 --- /dev/null +++ b/go.work.sum @@ -0,0 +1 @@ +github.com/ClickHouse/clickhouse-go v1.5.4 h1:cKjXeYLNWVJIx2J1K6H2CqyRmfwVJVY1OV1coaaFcI0= diff --git a/services/ja4ebpf/Dockerfile.package b/services/ja4ebpf/Dockerfile.package index 13af6bf..cb28d2f 100644 --- a/services/ja4ebpf/Dockerfile.package +++ b/services/ja4ebpf/Dockerfile.package @@ -23,13 +23,19 @@ ARG BUILD_VERSION=dev ARG GO_VERSION=1.24 # ── Stage 1 : compilation Go ────────────────────────────────────────────── -FROM golang:${GO_VERSION}-bookworm AS go-builder +FROM rockylinux:9 AS go-builder ARG BUILD_VERSION +ARG GO_VERSION + clang llvm libbpf-devel bpftool \ + curl tar gzip && \ + dnf clean all -RUN apt-get update && apt-get install -y --no-install-recommends \ - clang llvm libbpf-dev && \ - rm -rf /var/lib/apt/lists/* +RUN curl -fsSL https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz \ + | tar -C /usr/local -xz + +ENV PATH="/usr/local/go/bin:${PATH}" \ + GOPATH=/go WORKDIR /build diff --git a/services/ja4ebpf/cmd/ja4ebpf/main.go b/services/ja4ebpf/cmd/ja4ebpf/main.go index 3ee1f3c..f99e8ea 100644 --- a/services/ja4ebpf/cmd/ja4ebpf/main.go +++ b/services/ja4ebpf/cmd/ja4ebpf/main.go @@ -283,9 +283,9 @@ func consumeSynEvents(ctx context.Context, rd *ringbuf.Reader, mgr *correlation. TCPOptionsRaw: tcpOpts, SYNTimestamp: time.Now(), } - // Si TLS est déjà présent (arrivé avant SYN), marquer la session corrélée. + // Si TLS est déjà présent (arrivé avant SYN), les deux couches sont disponibles. if s.TLS != nil { - s.Correlated = true + _ = s.TLS // corrélation implicite par présence des deux champs } }) } @@ -363,7 +363,7 @@ func consumeTLSEvents(ctx context.Context, rd *ringbuf.Reader, mgr *correlation. } // Corréler si L3/L4 est déjà présent if s.L3L4 != nil { - s.Correlated = true + _ = s.L3L4 // corrélation implicite par présence des deux champs } }) } @@ -471,9 +471,7 @@ func consumeSSLEvents(ctx context.Context, rd *ringbuf.Reader, mgr *correlation. if len(s.Requests) == 0 { s.Requests = append(s.Requests, req) } - if s.TLS != nil { - s.Correlated = true - } + _ = s.TLS // corrélation implicite }) continue } @@ -493,9 +491,7 @@ func consumeSSLEvents(ctx context.Context, rd *ringbuf.Reader, mgr *correlation. HeaderOrder: req.Headers, HeaderOrderSig: req.HeaderSig, }) - if s.TLS != nil { - s.Correlated = true - } + _ = s.TLS // corrélation implicite }) continue } @@ -635,9 +631,7 @@ func consumeHTTPPlainEvents(ctx context.Context, rd *ringbuf.Reader, mgr *correl HeaderOrderSig: req.HeaderSig, }) // Corréler si L3/L4 est déjà présent (TCP SYN capturé) - if s.L3L4 != nil { - s.Correlated = true - } + _ = s.L3L4 // corrélation implicite }) } } diff --git a/services/ja4ebpf/internal/correlation/manager.go b/services/ja4ebpf/internal/correlation/manager.go index 4a756b3..1fa195a 100644 --- a/services/ja4ebpf/internal/correlation/manager.go +++ b/services/ja4ebpf/internal/correlation/manager.go @@ -76,7 +76,6 @@ func (m *Manager) GetOrCreate(key SessionKey) *SessionState { Key: key, FirstSeen: now, LastActivity: now, - Correlated: false, MaxKeepAlives: 1, } sh.sessions[key] = s @@ -128,12 +127,6 @@ func (m *Manager) gcRound(slowlorisThreshold time.Duration) { slowloris := s.IsSlowloris(slowlorisThreshold) if expired || slowloris { - // Marquer les sessions Slowloris comme non corrélées - if slowloris && !expired { - s.mu.Lock() - s.Correlated = false - s.mu.Unlock() - } toDelete = append(toDelete, key) // Envoyer sans bloquer (drop si le canal est plein) select { diff --git a/services/ja4ebpf/internal/correlation/session.go b/services/ja4ebpf/internal/correlation/session.go index 779d169..02b96f9 100644 --- a/services/ja4ebpf/internal/correlation/session.go +++ b/services/ja4ebpf/internal/correlation/session.go @@ -75,7 +75,6 @@ type SessionState struct { FirstSeen time.Time // horodatage de création de la session LastActivity time.Time // horodatage de la dernière activité - Correlated bool // true si L3/L4 et L7 sont corrélés mu sync.Mutex // protection des modifications concurrentes } diff --git a/services/ja4ebpf/internal/writer/clickhouse.go b/services/ja4ebpf/internal/writer/clickhouse.go index 29a73e6..cf34182 100644 --- a/services/ja4ebpf/internal/writer/clickhouse.go +++ b/services/ja4ebpf/internal/writer/clickhouse.go @@ -32,7 +32,6 @@ type sessionRecord struct { SrcPort int `json:"src_port"` DstIP string `json:"dst_ip"` DstPort int `json:"dst_port"` - Correlated int `json:"correlated"` // Métadonnées IP (noms attendus par le MV) IPMetaDF *bool `json:"ip_meta_df,omitempty"` @@ -182,18 +181,12 @@ func sessionToRecord(s *correlation.SessionState) sessionRecord { srcIP := fmt.Sprintf("%d.%d.%d.%d", s.Key.SrcIP[0], s.Key.SrcIP[1], s.Key.SrcIP[2], s.Key.SrcIP[3]) - correlated := 0 - if s.Correlated { - correlated = 1 - } - rec := sessionRecord{ Time: s.FirstSeen, SrcIP: srcIP, SrcPort: int(s.Key.SrcPort), DstIP: "0.0.0.0", // destination non capturée par les sondes eBPF actuelles DstPort: 0, - Correlated: correlated, KeepAlives: len(s.Requests), } diff --git a/tests/vm/.vagrant/bundler/global.sol b/tests/vm/.vagrant/bundler/global.sol new file mode 100644 index 0000000..e295207 --- /dev/null +++ b/tests/vm/.vagrant/bundler/global.sol @@ -0,0 +1 @@ +{"dependencies":[["racc",["~> 1.4"]],["nokogiri",["~> 1.6"]],["diffy",[">= 0"]],["rexml",[">= 0"]],["xml-simple",[">= 0"]],["logger",[">= 0"]],["mime-types-data",["~> 3.2025",">= 3.2025.0507"]],["mime-types",[">= 0"]],["io-console",["~> 0.5"]],["reline",[">= 0"]],["formatador",[">= 0.2","< 2.0"]],["excon",["~> 1.0"]],["builder",[">= 0"]],["fog-core",["~> 2"]],["ruby-libvirt",[">= 0.7.0"]],["json",[">= 0"]],["fog-xml",["~> 0.1.1"]],["multi_json",["~> 1.10"]],["fog-json",[">= 0"]],["fog-libvirt",[">= 0.6.0"]],["vagrant-libvirt",["= 0.12.2"]],["vagrant-qemu",["= 0.3.12"]]],"checksum":"8812dc95b590d4059a84fe716eaa6eea39b29aecb1c994c959de405ba3705361","vagrant_version":"2.4.9"} \ No newline at end of file diff --git a/tests/vm/.vagrant/machines/default/libvirt/action_provision b/tests/vm/.vagrant/machines/default/libvirt/action_provision new file mode 100644 index 0000000..4bd9c23 --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/action_provision @@ -0,0 +1 @@ +1.5:243a2344-d92e-47f5-b78c-fa70c5285248 \ No newline at end of file diff --git a/tests/vm/.vagrant/machines/default/libvirt/box_meta b/tests/vm/.vagrant/machines/default/libvirt/box_meta new file mode 100644 index 0000000..b861d6a --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/box_meta @@ -0,0 +1 @@ +{"name":"generic/rocky9","version":"4.3.12","provider":"libvirt","directory":"boxes/generic-VAGRANTSLASH-rocky9/4.3.12/amd64/libvirt"} \ No newline at end of file diff --git a/tests/vm/.vagrant/machines/default/libvirt/created_networks b/tests/vm/.vagrant/machines/default/libvirt/created_networks new file mode 100644 index 0000000..36bbd99 --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/created_networks @@ -0,0 +1 @@ +ec3ab786-8897-487f-8de2-2b3e73fd3319 diff --git a/tests/vm/.vagrant/machines/default/libvirt/creator_uid b/tests/vm/.vagrant/machines/default/libvirt/creator_uid new file mode 100644 index 0000000..e37d32a --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/creator_uid @@ -0,0 +1 @@ +1000 \ No newline at end of file diff --git a/tests/vm/.vagrant/machines/default/libvirt/id b/tests/vm/.vagrant/machines/default/libvirt/id new file mode 100644 index 0000000..98c02a1 --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/id @@ -0,0 +1 @@ +243a2344-d92e-47f5-b78c-fa70c5285248 \ No newline at end of file diff --git a/tests/vm/.vagrant/machines/default/libvirt/index_uuid b/tests/vm/.vagrant/machines/default/libvirt/index_uuid new file mode 100644 index 0000000..352c8f6 --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/index_uuid @@ -0,0 +1 @@ +67ff6c32d5a64e68ad3806a9d4af8342 \ No newline at end of file diff --git a/tests/vm/.vagrant/machines/default/libvirt/private_key b/tests/vm/.vagrant/machines/default/libvirt/private_key new file mode 100644 index 0000000..1ff9cec --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/private_key @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAA +AAtzc2gtZWQyNTUxOQAAACCLqXhq0Z8AH3V0G6LME2qcBsbuzvbzalThwUqf +wm2WDwAAAJAKdG7jCnRu4wAAAAtzc2gtZWQyNTUxOQAAACCLqXhq0Z8AH3V0 +G6LME2qcBsbuzvbzalThwUqfwm2WDwAAAEC2yLRWUE/0Llex3rQ/T1xAhX+O +xmzbOFc2WdVulooaw4upeGrRnwAfdXQboswTapwGxu7O9vNqVOHBSp/CbZYP +AAAAB3ZhZ3JhbnQBAgMEBQY= +-----END OPENSSH PRIVATE KEY----- diff --git a/tests/vm/.vagrant/machines/default/libvirt/synced_folders b/tests/vm/.vagrant/machines/default/libvirt/synced_folders new file mode 100644 index 0000000..a31d33a --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/synced_folders @@ -0,0 +1 @@ +{"rsync":{"/ja4-platform":{"type":"rsync","rsync__exclude":[".git/","old/","*.rpm","dist/"],"guestpath":"/ja4-platform","hostpath":"/home/antitbone/work/ja4-platform","disabled":false,"__vagrantfile":true,"exclude":[".git/","old/","*.rpm","dist/"],"owner":"vagrant","group":"vagrant"}}} \ No newline at end of file diff --git a/tests/vm/.vagrant/machines/default/libvirt/vagrant_cwd b/tests/vm/.vagrant/machines/default/libvirt/vagrant_cwd new file mode 100644 index 0000000..63f7f0a --- /dev/null +++ b/tests/vm/.vagrant/machines/default/libvirt/vagrant_cwd @@ -0,0 +1 @@ +/home/antitbone/work/ja4-platform/tests/vm \ No newline at end of file diff --git a/tests/vm/.vagrant/rgloader/loader.rb b/tests/vm/.vagrant/rgloader/loader.rb new file mode 100644 index 0000000..b6c81bf --- /dev/null +++ b/tests/vm/.vagrant/rgloader/loader.rb @@ -0,0 +1,12 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +# This file loads the proper rgloader/loader.rb file that comes packaged +# with Vagrant so that encoded files can properly run with Vagrant. + +if ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"] + require File.expand_path( + "rgloader/loader", ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"]) +else + raise "Encoded files can't be read outside of the Vagrant installer." +end