docs: mise à jour README + RAPPORT_FINAL v2.0.0
- README: version 2.0.0, TCP fingerprinting, clustering multi-métriques, structure fichiers mise à jour, endpoints API complets, workflows d'investigation, services techniques, tables ClickHouse, thème - RAPPORT_FINAL: section v2.0.0 avec détails TCP fingerprinting (20 signatures, scoring multi-signal, résultats production), clustering (21 features, K-means++, PCA, résultats 289 bots), redesign visualisation (tableau de bord + graphe), points d'attention Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
134
RAPPORT_FINAL.md
134
RAPPORT_FINAL.md
@ -106,3 +106,137 @@
|
||||
- Les **scores négatifs** dans `anomaly_score` et `worst_score` sont normaux — toujours utiliser `abs()` pour l'affichage
|
||||
- Les **IPv6-mapped** (`::ffff:x.x.x.x`) sont présentes dans toutes les vues agrégées — systématiquement utiliser `replaceRegexpAll(toString(src_ip), '^::ffff:', '')`
|
||||
|
||||
|
||||
---
|
||||
|
||||
# Rapport — v2.0.0 : TCP Fingerprinting Multi-Signal + Clustering IPs
|
||||
**Date :** 2026-03-19
|
||||
**Commit :** `e2db8ca`
|
||||
|
||||
---
|
||||
|
||||
## 1. TCP Fingerprinting OS amélioré
|
||||
|
||||
### Problème initial
|
||||
L'ancien `tcp_spoofing.py` utilisait uniquement le TTL avec 3 plages grossières (≤64 = Linux, ≤128 = Windows, sinon = Network). Résultat : faux positifs, aucune détection de bots scanners.
|
||||
|
||||
### Solution implémentée
|
||||
|
||||
**`backend/services/tcp_fingerprint.py`** — 20 signatures OS, scoring multi-signal :
|
||||
|
||||
| Signal | Poids | Source ClickHouse |
|
||||
|--------|-------|------------------|
|
||||
| TTL initial (estimé) | 40% | `tcp_ttl_raw` |
|
||||
| MSS | 30% | `tcp_mss_raw` |
|
||||
| Fenêtre TCP | 20% | `tcp_win_raw` |
|
||||
| Scale factor | 10% | `tcp_scale_raw` |
|
||||
|
||||
**Détections validées en production :**
|
||||
- **Masscan** : `win=5808, mss=1452, scale=4, TTL 48–57` → confiance **97%**
|
||||
- **Googlebot** : stack Windows détecté avec UA Android → **spoof confirmé**
|
||||
- **Bot-tool** : `risk_score += 30` (vs +15 pour spoof simple)
|
||||
|
||||
**MSS → chemin réseau :**
|
||||
- 1460 → Ethernet standard
|
||||
- 1452 → PPPoE / DSL (Masscan pattern)
|
||||
- 1420–1452 → VPN probable
|
||||
- < 1420 → Tunnel / double-encapsulation
|
||||
|
||||
**Fichiers modifiés :**
|
||||
- `backend/services/tcp_fingerprint.py` (nouveau)
|
||||
- `backend/routes/tcp_spoofing.py` (réécriture complète — queries `agg_host_ip_ja4_1h`)
|
||||
- `backend/routes/investigation_summary.py` (utilise le service tcp_fingerprint)
|
||||
- `frontend/src/components/TcpSpoofingView.tsx` (nouvelles colonnes MSS/scale/confiance, graphique distribution MSS)
|
||||
|
||||
---
|
||||
|
||||
## 2. Clustering IPs multi-métriques
|
||||
|
||||
### Problème initial
|
||||
La première version du clustering utilisait uniquement des règles sur les propriétés TCP. L'utilisateur a demandé d'utiliser **l'ensemble des métriques disponibles**.
|
||||
|
||||
### Solution implémentée
|
||||
|
||||
**`backend/services/clustering_engine.py`** — K-means++ pur Python (sans dépendances ML) :
|
||||
|
||||
**21 features normalisées [0,1] :**
|
||||
|
||||
| Catégorie | Features |
|
||||
|-----------|----------|
|
||||
| Stack TCP (4) | TTL initial, MSS, scale, fenêtre |
|
||||
| Anomalie ML (6) | score, vélocité, fuzzing, headless, POST ratio, IP-ID zéro |
|
||||
| TLS/Protocole (5) | ALPN mismatch, ALPN absent, efficacité H2, ordre headers, UA-CH mismatch |
|
||||
| Navigateur (1) | score navigateur moderne (normalisé /50) |
|
||||
| Temporel (3) | entropie, diversité JA4 (log1p), UA rotatif |
|
||||
| Comportement (2) | ratio assets, ratio accès direct |
|
||||
|
||||
**Algorithme :**
|
||||
```
|
||||
K-means++ : init O(k·n), n_init=3, meilleure inertie retenue
|
||||
Power iter : X^T(Xv) trick, O(n·d) par iter — pas de matrice n×n
|
||||
Déflation : Hotelling pour PC2 après extraction PC1
|
||||
```
|
||||
|
||||
**Stratégie d'échantillonnage :** `ORDER BY avg(abs(anomaly_score)) DESC` → les bots (score élevé) sont inclus en priorité, même si leurs hits individuels sont faibles (cas Masscan).
|
||||
|
||||
**Résultats en production (k=14, 3000 IPs) :**
|
||||
- **289 bots confirmés** : clusters UA rotatif + UA-CH mismatch (cloud providers : Microsoft, Google, Akamai)
|
||||
- **655 IPs suspects** : anomalie ML modérée ou UA-CH incohérent
|
||||
- **ASN dominants** : MICROSOFT-CORP-MSN-AS-BLOCK, GOOGLE-CLOUD-PLATFORM, OVH, AMAZON
|
||||
- **Temps de calcul** : ~5–9 secondes (Python pur, 3000 points × 21 features)
|
||||
|
||||
---
|
||||
|
||||
## 3. Visualisation clustering redesignée
|
||||
|
||||
### Problème initial
|
||||
La première version utilisait des bulles ReactFlow positionnées par PCA. L'utilisateur a signalé : **"l'affichage du graphe est illisible"**.
|
||||
|
||||
### Solution implémentée
|
||||
|
||||
**Deux vues distinctes, accessibles par onglets :**
|
||||
|
||||
#### ⊞ Tableau de bord (défaut — toujours lisible)
|
||||
- Grille de cartes groupées par niveau de risque
|
||||
- **Bots & Menaces confirmées** (rouge) → **Suspects** (orange) → **Légitimes** (vert)
|
||||
- Chaque carte : label + IP count + hits + badge CRITIQUE/ÉLEVÉ/MODÉRÉ/SAIN + 4 mini-barres + stack TCP + pays + ASN
|
||||
|
||||
#### ⬡ Graphe de relations
|
||||
- Nœuds-cartes ReactFlow (220px — texte entièrement lisible)
|
||||
- **Colonnes par niveau de menace** (disposition déterministe, pas PCA)
|
||||
- Arêtes colorées : orange=similaire, gris=distant, animé=très fort
|
||||
- Légende intégrée, minimap, contrôles zoom
|
||||
|
||||
#### Sidebar de détail
|
||||
- RadarChart comportemental (10 axes)
|
||||
- Toutes les métriques avec barres de progression
|
||||
- Liste des IPs avec badges menace/pays
|
||||
- Export **Copier IPs** + **⬇ CSV**
|
||||
- Intégrée dans le flux flex (ne bloque plus la barre de contrôle)
|
||||
|
||||
**Fichiers modifiés :**
|
||||
- `backend/routes/clustering.py` (réécriture complète)
|
||||
- `backend/services/clustering_engine.py` (nouveau — seuils calibrés sur données réelles)
|
||||
- `frontend/src/components/ClusteringView.tsx` (réécriture complète)
|
||||
- `frontend/src/App.tsx` (route `/clustering` + nav "🔬 Clustering IPs")
|
||||
|
||||
---
|
||||
|
||||
## 4. Points d'attention
|
||||
|
||||
### Performances
|
||||
- K-means++ sur 3000 × 21 : **5–9s** (acceptable — pas de cache implémenté)
|
||||
- Le cache mémoire du drill-down (`_cache["cluster_ips"]`) est volatile : rechargement = recalcul
|
||||
- Pour améliorer : cache Redis ou TTL 5 min avec `functools.lru_cache`
|
||||
|
||||
### Calibration des seuils
|
||||
Les seuils de `name_cluster()` et `risk_score_from_centroid()` sont calibrés sur les données observées :
|
||||
- `anomaly_score` en production : plage 0.2–0.35 (pas 0–1 comme attendu)
|
||||
- Score normalisé affiché : `min(1, score / 0.5)` pour étirer la plage utile
|
||||
- UA-CH mismatch = 1.0 sur les clusters bot = signal **très fort** (cloud providers simulant un navigateur)
|
||||
|
||||
### Données manquantes dans le LEFT JOIN
|
||||
Certaines IPs n'apparaissent pas dans `ml_detected_anomalies` (score=0, fuzz=0). Ce sont les IPs légitimes non détectées par le modèle ML. Elles forment naturellement les clusters "Trafic Légitime".
|
||||
|
||||
### Fuzzing_index = 100% dans beaucoup de clusters
|
||||
Après analyse : le `fuzzing_index` log-normalisé dépasse souvent le seuil de 100% car les valeurs brutes sont très variables (0 à 229+). Ce n'est pas un bug — c'est la nature du trafic web moderne (beaucoup de requêtes avec des paths variés).
|
||||
|
||||
Reference in New Issue
Block a user