Files
ja4-platform/docs/services/bot-detector.md
toto c96c41fb45 docs: réécriture complète de la documentation des services en français
- bot-detector.md : architecture 11 modules, 77/65 features,
  ensemble triple voix (EIF+AE+XGBoost), browser 5 axes, HDBSCAN,
  toutes les variables d'environnement vérifiées depuis le code source
- dashboard.md : corrigé stack (Jinja2+htmx, pas React+Vite),
  14 pages + 35 API routes + health, dual-database, IPv4/IPv6
- python-ja4common.md : ajouté CLICKHOUSE_DB_PROCESSING/LOGS,
  schéma dual-database, note dashboard n'utilise pas ja4_common

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-09 22:04:58 +02:00

25 KiB
Raw Blame History

Bot Detector

Service Python de détection d'anomalies par apprentissage automatique semi-supervisé sur le trafic HTTP/TLS agrégé dans ClickHouse. Fonctionne en cycle continu (par défaut toutes les 5 minutes) avec un ensemble à triple voix (Extended Isolation Forest + Autoencoder + XGBoost), enrichi par l'explicabilité SHAP, le clustering HDBSCAN et la détection multifactorielle des navigateurs.


Architecture des modules

Le service est découpé en 11 modules organisés ainsi :

__main__.py          Point d'entrée (python -m bot_detector)
  └─ cycle.py        Boucle principale : requête ClickHouse → pipeline → insertion
       ├─ config.py          Variables d'environnement, flags de disponibilité
       ├─ log.py             Journalisation structurée JSON (structlog + RotatingFileHandler)
       ├─ infra.py           Client ClickHouse (via ja4_common), health check HTTP, arrêt propre
       ├─ preprocessing.py   Nettoyage du DataFrame, imputation, listes de features
       │    └─ browser.py    Identification multifactorielle des navigateurs (5 axes)
       ├─ pipeline.py        Orchestration : filtrage → entraînement → scoring → fusion
       │    ├─ models.py     EIF, TrafficAutoEncoder (PyTorch), XGBoost
       │    └─ scoring.py    Normalisation, seuil adaptatif, SHAP, HDBSCAN, dérive
       └─ (insère dans ml_all_scores + ml_detected_anomalies)
Module Lignes Rôle
config.py 154 Toute la configuration via os.getenv(), flags de disponibilité des librairies
log.py 65 log_info(), log_decision(), append_training_history() — JSONL rotatif
infra.py 89 Client ClickHouse (délègue à ja4_common), score_to_threat_level(), serveur de santé en thread daemon
browser.py 170 Détection multifactorielle des navigateurs sur 5 axes pondérés
scoring.py 279 Normalisation, seuil adaptatif, SHAP top-3, HDBSCAN, détection de dérive
models.py 478 TrafficAutoEncoder, entraînement/chargement EIF, XGBoost, élagage de features
preprocessing.py 117 preprocess_df() — nettoyage, typage, imputation, listes FEATURES / FEATURES_COMPLET
pipeline.py 378 run_semi_supervised_logic() — orchestration complète d'un modèle
cycle.py 371 fetch_and_analyze() — boucle principale, feedback SOC, multiwindow
__main__.py 41 Point d'entrée, bannière de démarrage, boucle while True
__init__.py 1 Docstring du package

Configuration

Toute la configuration est lue via os.getenv() dans config.py. Aucun fichier YAML ni pydantic-settings.

Connexion ClickHouse

Variable Type Défaut Description
CLICKHOUSE_HOST str clickhouse Nom d'hôte du serveur ClickHouse (via ja4_common)
CLICKHOUSE_PORT int 8123 Port HTTP ClickHouse (via ja4_common)
CLICKHOUSE_USER str admin Utilisateur ClickHouse (via ja4_common)
CLICKHOUSE_PASSWORD str "" Mot de passe ClickHouse (via ja4_common)
CLICKHOUSE_DB_PROCESSING str ja4_processing Base de données ML/agrégations (fallback : CLICKHOUSE_DB)
CLICKHOUSE_DB_LOGS str ja4_logs Base de données des logs HTTP

Modèle et entraînement

Variable Type Défaut Description
N_ESTIMATORS int 300 Nombre d'arbres pour l'Extended Isolation Forest
ISOLATION_CONTAMINATION float 0.001 Paramètre de contamination EIF (plage ]0, 0.5[)
ANOMALY_THRESHOLD float -0.05 Seuil de score brut pour la détection d'anomalie
ANOMALY_PERCENTILE int 5 Percentile pour le seuil adaptatif
MODEL_DIR str /var/lib/bot_detector Répertoire de persistance des modèles
MODEL_HISTORY_COUNT int 10 Nombre de versions de modèle conservées
RETRAIN_INTERVAL_HOURS int 24 Intervalle de réentraînement EIF (heures)
DRIFT_THRESHOLD float 0.30 Seuil de dérive KS (fraction de features driftées)
MIN_VALID_FEATURE_RATIO float 0.50 Ratio minimal de features valides pour entraîner
PRUNE_VARIANCE_THRESHOLD float 1e-6 Seuil de variance pour l'élagage de features
VAL_ANOMALY_GATE float 0.20 Garde-fou : taux maximum d'anomalies en validation

Autoencoder

Variable Type Défaut Description
AE_WEIGHT float 0.30 Poids de l'Autoencoder dans le score combiné (plage ]0, 1[)
AE_EPOCHS int 50 Nombre d'époques d'entraînement
AE_LATENT_DIM int 16 Dimension de l'espace latent
AE_LEARNING_RATE float 1e-3 Taux d'apprentissage Adam

XGBoost

Variable Type Défaut Description
XGB_WEIGHT float 0.20 Poids de XGBoost dans le score final (plage ]0, 1[)
XGB_MIN_LABELS int 100 Nombre minimal de labels SOC pour activer XGBoost
XGB_RETRAIN_INTERVAL_HOURS int 168 Intervalle de réentraînement XGBoost (7 jours)

Détection navigateur

Variable Type Défaut Description
BROWSER_CONFIDENCE_THRESHOLD float 0.55 Confiance minimale pour classifier LEGITIMATE_BROWSER
BROWSER_COHORT_RATIO float 0.70 Si ≥ 70 % des sessions d'un JA4 sont navigateur → propagation

Clustering et explicabilité

Variable Type Défaut Description
ENABLE_CLUSTERING bool true Activer le clustering HDBSCAN
CLUSTERING_MIN_SAMPLES int 3 Taille minimale de cluster
ENABLE_SHAP bool true Activer l'explicabilité SHAP (requiert shap installé)

Cycle et opérations

Variable Type Défaut Description
CYCLE_INTERVAL_SEC int 300 Intervalle entre les cycles (secondes)
MAX_CONSECUTIVE_FAILURES int 3 Échecs consécutifs avant healthy=False
DEDUP_TTL_MIN int 60 TTL de déduplication inter-cycle (minutes)
RECURRENCE_WEIGHT float 0.005 Poids de la récurrence dans le score brut
ENABLE_MULTIWINDOW bool false Activer l'analyse multi-fenêtre 24h
MULTIWINDOW_VIEW str view_ai_features_24h Vue ClickHouse pour le mode multi-fenêtre
ENABLE_FEEDBACK bool true Activer l'intégration du feedback SOC
FEEDBACK_WINDOW_DAYS int 7 Fenêtre de feedback SOC (jours)

Journalisation et santé

Variable Type Défaut Description
BOT_DETECTOR_LOG str /var/log/bot_detector/decisions.jsonl Chemin du fichier de décisions
LOG_BACKUP_COUNT int 7 Nombre de fichiers de rotation conservés
HEALTH_PORT int 8080 Port du serveur de santé HTTP

Pipeline ML — Ensemble à triple voix

Vue d'ensemble

Le bot-detector utilise trois modèles en parallèle, combinés par une pondération configurable :

                  ┌──────────────────────┐
                  │  Extended Isolation   │
                  │  Forest (isotree)     │──→ eif_norm (01)
                  └──────────────────────┘        │
                                                  │ × (1  AE_WEIGHT)
                  ┌──────────────────────┐        │
                  │  TrafficAutoEncoder   │        ├──→ combined_norm
                  │  (PyTorch)            │──→ ae_norm  (01)
                  └──────────────────────┘   × AE_WEIGHT
                                                  │ × (1  XGB_WEIGHT)
                  ┌──────────────────────┐        │
                  │  XGBoost             │        ├──→ anomaly_score
                  │  (supervisé, labels  │──→ xgb_prob  (01)
                  │   SOC)               │   × XGB_WEIGHT
                  └──────────────────────┘

Formule du score final :

combined_norm  = (1  AE_WEIGHT) × eif_norm + AE_WEIGHT × ae_norm
anomaly_score  = (1  XGB_WEIGHT) × combined_norm + XGB_WEIGHT × xgb_prob

Avec les poids par défaut (AE_WEIGHT=0.30, XGB_WEIGHT=0.20) :

anomaly_score = 0.56 × eif_norm + 0.24 × ae_norm + 0.20 × xgb_prob

Architecture duale

Deux modèles indépendants tournent sur chaque cycle :

Modèle Condition Features Données
Complet correlated = 1 77 (FEATURES_COMPLET) HTTP + TCP + TLS (L3→L7)
Applicatif correlated = 0 65 (FEATURES) HTTP seul (L7 pur)

En mode multi-fenêtre (ENABLE_MULTIWINDOW=true), deux variantes supplémentaires sont exécutées sur la vue 24h : Complet_24h et Applicatif_24h.

Extended Isolation Forest (EIF)

Modèle principal non supervisé. Utilise isotree.IsolationForest :

isotree.IsolationForest(
    ntrees=300,              # N_ESTIMATORS
    ndim=min(3, n_features),
    sample_size='auto',
    missing_action='impute',
    random_seed=42,
    nthreads=-1,
)

Fallback si isotree n'est pas disponible : sklearn.ensemble.IsolationForest(n_estimators=300, contamination=CONTAMINATION).

Calibration : le score isotree brut (∈ [0, 1], >0.5 = anomalous) est converti en convention sklearn : sklearn_equiv = 0.5 isotree_score.

TrafficAutoEncoder (PyTorch)

Architecture symétrique encodeur-décodeur :

Encodeur : n_features → dim1 → dim2 → 16 (latent)
Décodeur : 16 → dim2 → dim1 → n_features

dim1 = min(64, max(n_features, latent_dim + 4))
dim2 = min(32, max(dim1 // 2, latent_dim + 2))
  • Activations : ReLU + BatchNorm1d sur les couches cachées, Sigmoid en sortie du décodeur
  • Optimiseur : Adam(lr=1e-3, weight_decay=1e-5)
  • Perte : MSELoss
  • Entraînement : 50 époques, batch_size=256
  • Score : erreur de reconstruction MSE par échantillon
  • Normalisation des entrées : min-max [0, 1] par feature

XGBoost (supervisé)

Entraîné sur les labels issus du feedback SOC (table soc_feedback) :

xgb.XGBClassifier(
    n_estimators=200,
    max_depth=6,
    learning_rate=0.1,
    scale_pos_weight=auto,  # max(1, n_neg / n_pos)
    eval_metric='logloss',
    tree_method='hist',
    random_state=42,
    n_jobs=-1,
)
  • Labels positifs (bot) : HIGH, CRITICAL, ANUBIS_DENY, KNOWN_BOT
  • Labels négatifs (légitime) : NORMAL, LEGITIMATE_BROWSER
  • Activation requiert ≥ XGB_MIN_LABELS (100) labels
  • Réentraînement tous les XGB_RETRAIN_INTERVAL_HOURS (168h = 7 jours)

Détection multifactorielle des navigateurs

Module browser.py — classifie chaque session sur 5 axes pondérés :

Axe Clé Poids Composantes
1 — JA4 connu axis_ja4_known 0.25 Famille navigateur identifiée dans dict_browser_ja4 → 1.0, sinon 0.0
2 — Structure JA4 axis_ja4_struct 0.15 TLS 1.3 (×0.35), h2/h3 (×0.25), nb ciphers 1025 (×0.20), nb extensions 1025 (×0.20)
3 — HTTP moderne axis_http_modern 0.25 modern_browser_score ≥ 50 (×0.35), Accept-Language (×0.20), Sec-Fetch < 0.3 (×0.25), generic_accept < 0.3 (×0.10), pas de ua_ch_mismatch (×0.10)
4 — Comportement navigation axis_nav_behavior 0.15 has_cookie (×0.25), has_referer (×0.25), asset_ratio > 0.15 (×0.25), direct_access < 0.5 (×0.25)
5 — Cohérence TLS/TCP axis_tls_coherence 0.20 Pas d'alpn_mismatch (×0.25), window_scale OK (×0.20), tls12 < 0.1 (×0.20), pas d'http10 (×0.15), ALPN présent (×0.20)

Seuil : browser_confidence ≥ 0.55 + famille identifiée → LEGITIMATE_BROWSER

Propagation par cohorte : si ≥ 70 % des sessions partageant un JA4 sont classées navigateur, les sessions NORMAL/LOW restantes avec le même JA4 sont aussi classées LEGITIMATE_BROWSER.

Inférence de famille : pour les JA4 inconnus, correspondance structurelle avec les profils _BROWSER_JA4_PROFILES (Chromium, Firefox, Safari, Tor_Browser) — requiert browser_confidence ≥ 0.45.


Scoring et normalisation

Normalisation des scores (normalize_scores)

Les scores bruts (négatifs = anomalous) sont mappés vers [0, 1] avec 1 = le plus anomalous :

result[mask] = clip(scores / (s_min + 1e-9), 0, 1)

Les scores ≥ 0 sont mis à 0.

Seuil adaptatif (compute_adaptive_threshold)

threshold = min(percentile(scores_négatifs, ANOMALY_PERCENTILE), ANOMALY_THRESHOLD)

Avec ANOMALY_PERCENTILE=5 et ANOMALY_THRESHOLD=-0.05.

Pénalité de récurrence

Appliquée au raw_anomaly_score :

raw_anomaly_score = log1p(recurrence_count) × RECURRENCE_WEIGHT

Niveaux de menace

Plage de score brut Niveau Interprétation
< 0.30 CRITICAL Comportement extrêmement anomalous
< 0.15 HIGH Signal d'anomalie fort
< 0.05 MEDIUM Anomalie modérée
< 0 LOW Légèrement inhabituel
≥ 0 NORMAL Trafic normal

Clustering HDBSCAN des campagnes

Lorsque ENABLE_CLUSTERING=true, les anomalies sont regroupées en campagnes par HDBSCAN :

hdbscan.HDBSCAN(
    min_cluster_size=CLUSTERING_MIN_SAMPLES,      # défaut : 3
    min_samples=max(2, CLUSTERING_MIN_SAMPLES  1),  # défaut : 2
    cluster_selection_method='eom',
)

Espace de clustering : si un Autoencoder est disponible, le clustering s'effectue dans l'espace latent 16-dim de l'AE. Sinon, StandardScaler est appliqué sur les features brutes.

Fallback si hdbscan n'est pas disponible : DBSCAN(eps=0.5, min_samples=CLUSTERING_MIN_SAMPLES).

Chaque anomalie reçoit un campaign_id (1 = pas de cluster).


Liste des features

Features communes — modèle Applicatif (65 features)

Comportement HTTP

Feature Description
hits Nombre de requêtes dans la fenêtre
hit_velocity Requêtes par seconde
fuzzing_index Score de diversité chemins/paramètres
post_ratio Fraction de requêtes POST
port_exhaustion_ratio Fraction de ports source distincts / total
orphan_ratio Requêtes sans corrélation TLS
head_ratio Fraction de requêtes HEAD
http10_ratio Fraction de requêtes HTTP/1.0
generic_accept_ratio Fraction d'en-têtes Accept courts
sec_fetch_absence_rate Fraction sans Sec-Fetch-Site
missing_accept_enc_ratio Fraction sans Accept-Encoding
http_scheme_ratio Fraction utilisant HTTP (pas HTTPS)

Gestion de connexion

Feature Description
max_keepalives Max de requêtes sur une seule connexion Keep-Alive
tcp_shared_count Connexions TCP partagées entre sessions
multiplexing_efficiency Efficacité du multiplexage HTTP/2

Empreinte navigateur

Feature Description
header_count Nombre d'en-têtes HTTP envoyés
has_accept_language Présence de l'en-tête Accept-Language
has_cookie Présence de l'en-tête Cookie
has_referer Présence de l'en-tête Referer
modern_browser_score Score composite de conformité navigateur (0100)
ua_ch_mismatch Incohérence User-Agent vs Client Hints
ip_id_zero_ratio Paquets IP avec ID=0 (pile minimaliste/headless)
header_order_shared_count IPs partageant le même ordre d'en-têtes
header_order_confidence Entropie normalisée de l'ordre des en-têtes
distinct_header_orders Ordres d'en-têtes distincts par IP
is_fake_navigation Sec-Fetch-Mode=navigate avec destination non-document

Comportement de navigation

Feature Description
request_size_variance Variance de la taille des requêtes
mss_mobile_mismatch Incohérence TCP MSS vs profil mobile
asset_ratio Fraction de requêtes de ressources statiques
direct_access_ratio Accès directs (sans referer)
is_ua_rotating Rotation de User-Agent détectée
distinct_ja4_count Empreintes JA4 distinctes par IP
anomalous_payload_ratio Fraction de charges utiles anomalous

Concentration et rareté

Feature Description
src_port_density Entropie des ports source
ja4_asn_concentration Concentration JA4 au sein de l'ASN
ja4_country_concentration Concentration JA4 par pays
is_rare_ja4 Empreinte JA4 rare (< 100 hits totaux)

Temporel et diversité

Feature Description
temporal_entropy Entropie de la distribution temporelle
path_diversity_ratio Diversité des chemins URL
url_depth_variance Variance de la profondeur des URL

Anubis

Feature Description
anubis_is_flagged Signal de suspicion Anubis (bot détecté, action ni ALLOW/DENY/vide)

Navigateur multifactoriel

Feature Description
is_known_browser JA4 correspond à un navigateur connu
browser_consistency_score Score composite de cohérence navigateur
browser_confidence Confiance globale de l'identification navigateur
axis_ja4_known Score de l'axe 1 (JA4 connu)
axis_ja4_struct Score de l'axe 2 (structure JA4)
axis_http_modern Score de l'axe 3 (HTTP moderne)
axis_nav_behavior Score de l'axe 4 (comportement navigation)
axis_tls_coherence Score de l'axe 5 (cohérence TLS/TCP)

Thèse §5 — Features avancées

Feature Description
path_transition_entropy Entropie des transitions de chemins
cadence_cv Coefficient de variation de la cadence de requêtes
burst_ratio Fraction de requêtes en rafale
pause_ratio Fraction de pauses longues
lag1_autocorrelation Autocorrélation lag-1 des inter-arrivées
benford_deviation Déviation par rapport à la loi de Benford
host_diversity Diversité des hôtes ciblés
host_sweep_speed Vitesse de balayage des hôtes
host_coverage_uniformity Uniformité de couverture des hôtes

Features TCP fenêtre

Feature Description
true_window_size Taille réelle de la fenêtre TCP
window_mss_ratio Ratio fenêtre TCP / MSS

Features de détection avancées

Feature Description
has_xff Présence de l'en-tête X-Forwarded-For
unusual_content_type_ratio Fraction de Content-Type inhabituels
non_standard_port_ratio Fraction de ports non standards
login_post_concentration Concentration de POST sur les pages de login
sec_ch_mobile_mismatch Incohérence Sec-CH-UA-Mobile

Features supplémentaires — modèle Complet (+12 features TCP/TLS)

Feature Description
tcp_jitter_variance Variance du jitter TCP inter-paquets
alpn_http_mismatch Incohérence ALPN vs protocole HTTP réel
is_alpn_missing ALPN absent dans le ClientHello
sni_host_mismatch Incohérence TLS SNI vs en-tête Host HTTP
ja3_diversity_ratio Ratio de diversité JA3 par IP
syn_timing_cv Coefficient de variation du timing SYN
tls12_ratio Fraction de connexions TLS 1.2
ip_df_variance Variance du flag Don't-Fragment IP
avg_ttl TTL IP moyen (empreinte OS)
ttl_std Écart-type du TTL
no_window_scale_ratio Fraction sans TCP Window Scale
ja4_drift_ratio Dérive JA4 intra-session (§5.5)

Pipeline de détection

1. Requête view_ai_features_1h → DataFrame
2. Enrichissement optionnel view_thesis_features_1h (features thèse §5)
3. Prétraitement : preprocess_df() (nettoyage, browser axes, imputation)
4. Chargement du feedback SOC → reclassification
5. Chargement de la carte de récurrence (view_ip_recurrence)
6. Séparation par correlated = 1 / correlated = 0
7. Pour chaque modèle (Complet, Applicatif) :
   a. Validation des features (exclure constantes/manquantes)
   b. Séparation des bots connus → journalisation KNOWN_BOT
   c. Filtrage de la baseline humaine (asn_label = 'human')
   d. Chargement ou entraînement EIF + AE
   e. Scoring du trafic inconnu (EIF + AE)
   f. Chargement ou entraînement XGBoost (si labels disponibles)
   g. Combinaison des scores (formule triple voix)
   h. Normalisation [0, 1]
   i. Seuil adaptatif
   j. Pénalité de récurrence
   k. SHAP (top-3 features)
   l. HDBSCAN clustering → campaign_id
   m. Détection de dérive (KS test)
8. Mode multi-fenêtre (si activé) : idem sur view_ai_features_24h
9. Insertion → ml_all_scores (toutes les sessions scorées)
10. Déduplication intra-cycle (garder raw_anomaly_score le plus bas par IP)
11. Déduplication inter-cycle (TTL, skip si détecté récemment sauf aggravation ≥ 0.05)
12. Insertion → ml_detected_anomalies (anomalies filtrées)

Détection de dérive (Kolmogorov-Smirnov)

Par feature, un test KS bilatéral compare la distribution courante avec la distribution d'entraînement (reconstruite par interpolation à partir d'un digest quantile p10/p25/p50/p75/p90) :

  • Feature driftée si p_value < 0.05
  • Dérive globale = fraction de features driftées
  • Si drift > DRIFT_THRESHOLD (0.30) → réentraînement automatique

Fallback (sans scipy) : méthode Z-score — feature driftée si |moyenne_courante moyenne_entraînement| / std_entraînement > 2.0.


Explicabilité SHAP

Lorsque ENABLE_SHAP=true et que la librairie shap est disponible :

  • Calcul des valeurs SHAP via TreeExplainer sur le modèle EIF
  • Les 3 features les plus contributives sont stockées dans le champ reason
  • Format : "feature1=valeur (±shap), feature2=valeur (±shap), feature3=valeur (±shap)"

Enrichissement Anubis

La vue view_ai_features_1h enrichit chaque IP via les dictionnaires Anubis selon une cascade de priorité :

  1. UA + IP combinés (même rule_id) — confiance maximale
  2. UA seul (pas de condition IP)
  3. IP seul (pas de condition UA)
  4. Correspondance ASN
  5. Correspondance pays

Tables de sortie

ml_detected_anomalies

Détections d'anomalies au-dessus du seuil de menace. Engine : ReplacingMergeTree(detected_at), ORDER BY (src_ip, model_name), TTL 7 jours.

Colonnes clés : detected_at, src_ip, ja4, host, bot_name, anomaly_score, raw_anomaly_score, threat_level, model_name, recurrence, campaign_id, reason, anubis_bot_name, anubis_bot_action, anubis_bot_category, plus toutes les features ML.

ml_all_scores

Toutes les classifications (sans filtre de seuil) pour l'observabilité. Engine : ReplacingMergeTree(detected_at), ORDER BY (window_start, src_ip, ja4, host, model_name), TTL 7 jours.


Format du journal de décisions

Le fichier decisions.jsonl contient des entrées JSONL structurées :

{"event": "CYCLE_START", "cycle_id": "20260309T143000", "total": 5000, "human": 1500, "known_bot": 200, "correlated": 3000}
{"event": "ANOMALY", "src_ip": "203.0.113.42", "score": -0.25, "threat_level": "HIGH", "reason": "hit_velocity=45.2, fuzzing_index=0.8, ...", "campaign_id": 3}
{"event": "KNOWN_BOT", "src_ip": "198.51.100.10", "bot_name": "AhrefsBot"}
{"event": "CYCLE_END", "cycle_id": "20260309T143000", "anomalies": 15, "known_bots": 200, "duration_sec": 12.5}

Rotation des logs : 50 Mo max × LOG_BACKUP_COUNT sauvegardes (défaut : 7).


Point de santé

  • URL : GET http://localhost:8080/
  • Réponses : 200 OK (corps OK) ou 503 Service Unavailable (corps DEGRADED)
  • Exécuté dans un thread daemon au démarrage
  • État mis à False après MAX_CONSECUTIVE_FAILURES (3) échecs consécutifs ClickHouse, remis à True dès le premier succès

Persistance des modèles

Fichier Description
model_<name>_<version>.joblib EIF sérialisé (joblib)
model_<name>_<version>.meta.json Métadonnées (features, seuils, statistiques d'entraînement, digest quantile)
model_<name>.current Pointeur vers la version active
training_history.jsonl Historique d'entraînement

Rotation automatique : seules les MODEL_HISTORY_COUNT dernières versions (défaut : 10) sont conservées.


Déploiement Docker

# Construction de l'image
make build-bot-detector

# Exécution avec docker-compose
cd services/bot-detector
docker-compose up -d

# Tests
make test-bot-detector

Volumes

Chemin hôte Chemin conteneur Description
./bot_detector_logs /var/log/bot_detector Journaux de décisions (JSONL)
./bot_detector_models /var/lib/bot_detector Modèles ML persistés
./reputation/data/user_files/bot_ip.csv /data/bot_ip.csv (ro) Liste d'IPs de bots connus
./reputation/data/user_files/bot_ja4.csv /data/bot_ja4.csv (ro) Liste de JA4 de bots connus
./reputation/data/user_files/asn_reputation.csv /data/asn_reputation.csv (ro) Labels de réputation ASN