Files
ja4-platform/services/bot-detector/CLICKHOUSE_FEATURES_DIAGNOSTIC.md
toto 9f3e0621e5 feat: split ClickHouse into dual configurable databases (ja4_logs / ja4_processing)
Architecture:
- ja4_logs: raw log ingestion (http_logs_raw, http_logs, mv_http_logs)
- ja4_processing: analytics, aggregation, ML, dictionaries, audit

Configuration (env vars):
- CLICKHOUSE_DB_LOGS (default: ja4_logs)
- CLICKHOUSE_DB_PROCESSING (default: ja4_processing)

Changes:
- SQL migrations (10 files): all mabase_prod refs → ja4_logs or ja4_processing
  with correct cross-database references (MVs, views, dicts)
- deploy_schema.sh: substitutes DB names from env vars at deploy time
- Python shared settings: added CLICKHOUSE_DB_LOGS + CLICKHOUSE_DB_PROCESSING
- Dashboard routes (19 files): replaced ~80 hardcoded mabase_prod refs
  with settings.CLICKHOUSE_DB_LOGS / settings.CLICKHOUSE_DB_PROCESSING
- Bot-detector: DB → CLICKHOUSE_DB_PROCESSING, fetch_rules.py configurable
- Correlator: DSN example updated to ja4_logs
- Docker-compose + .env files: new env vars with defaults
- All documentation updated (14 markdown files)

All tests pass: sentinel 10/10, correlator 67.1%, bot-detector 11, dashboard 20, ja4_common 18

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-07 19:10:35 +02:00

8.8 KiB
Raw Permalink Blame History

Diagnostic — Features manquantes dans view_ai_features_1h

Généré le 2026-03-17 — Mis à jour le 2026-03-17 (corrections appliquées) — À destination de l'administrateur ClickHouse

Statut des corrections (2026-03-17 13:05)

Problème Correction appliquée Résultat
1 — MV mv_agg_header_fingerprint_1h absente MV recréée + backfill 25h 10 features header actives
2header_order_shared_count / distinct_header_orders globales Se corrige avec Problème 1 Résolu automatiquement
3orphan_ratio = 0 pour correlated=1 Comportement normal (by design) Pas d'action requise
4 — 4 vues dashboard absentes Vues créées
5view_dashboard_variability référence header_user_agent inexistant Colonne remplacée par reason Bug corrigé
6 — Anciennes vues heuristiques orphelines Droppées

Cycle post-correction (13:05) — features dans les warnings :

  • Complet : seulement orphan_ratio (by design)
  • Applicatif : request_size_variance, mss_mobile_mismatch, is_rare_ja4 (see §4 below)
  • Header features disparues des warnings → pipeline opérationnel


Résumé

Le service Bot Detector signale des features non-discriminantes à chaque cycle. Ce document en explique les causes exactes et les corrections nécessaires côté ClickHouse.

Ces avertissements n'empêchent pas le service de fonctionner — les features invalides sont automatiquement exclues du modèle (A7). Mais leur absence réduit la qualité de la détection.


Problème 1 — Pipeline agg_header_fingerprint_1h arrêté ⚠️ CRITIQUE

Symptôme

Les features suivantes sont toujours à 0 dans view_ai_features_1h :

  • header_count
  • has_accept_language
  • has_cookie
  • has_referer
  • modern_browser_score
  • ua_ch_mismatch
  • mss_mobile_mismatch (dépend de modern_browser_score)

Cause

La table ja4_processing.agg_header_fingerprint_1h (AggregatingMergeTree) n'a plus reçu de données depuis le 2026-03-13 23:00 :

SELECT max(window_start), count()
FROM ja4_processing.agg_header_fingerprint_1h;
-- Résultat : 2026-03-13 23:00:00, 73024 lignes

La vue fait un LEFT JOIN avec condition window_start >= now() - INTERVAL 24 HOUR, et comme aucune ligne récente n'existe dans agg_header_fingerprint_1h, toutes les colonnes issues de ce JOIN retournent NULL (→ 0 après coalesce).

Recherche de la MV source

La liste des Materialized Views ne montre aucune MV dédiée à agg_header_fingerprint_1h :

SELECT name FROM system.tables
WHERE database = 'ja4_processing' AND engine = 'MaterializedView';
-- mv_agg_host_ip_ja4_1h
-- mv_http_logs
-- view_dashboard_entities_mv
-- view_dashboard_user_agents_mv

Aucune MV ne cible agg_header_fingerprint_1h. Elle est probablement alimentée par un processus externe (ETL, script, pipeline Kafka, etc.) qui s'est arrêté.

Correction appliquée

La MV mv_agg_header_fingerprint_1h était définie dans deploy_views.sql mais n'avait jamais été créée en base. Elle a été recréée le 2026-03-17 :

-- Recréation de la MV (déjà appliquée)
CREATE MATERIALIZED VIEW ja4_processing.mv_agg_header_fingerprint_1h
TO ja4_processing.agg_header_fingerprint_1h AS
SELECT
    toStartOfHour(src.time) AS window_start,
    toIPv6(src.src_ip) AS src_ip,
    any(toString(cityHash64(src.client_headers))) AS header_order_hash,
    max(toUInt16(length(src.client_headers) - length(replaceAll(src.client_headers, ',', '')) + 1)) AS header_count,
    -- ... (voir deploy_views.sql §5)
FROM ja4_logs.http_logs AS src
GROUP BY window_start, src.src_ip;

Un backfill de 25 heures a été effectué depuis http_logs pour alimenter la table avec des données historiques (377 689 lignes insérées). Les nouvelles données sont désormais alimentées en temps réel par la MV.

Cause historique

La MV avait été omise lors du déploiement initial. La table agg_header_fingerprint_1h contenait 73 024 lignes datant du 2026-03-13 (probablement issues d'un backfill manuel ponctuel), puis n'avait plus été alimentée.


Problème 2 — Features non-discriminantes (agrégat global, non per-IP)

Symptôme

Les features suivantes ont une valeur unique non-nulle identique pour toutes les IPs :

  • header_order_shared_count (valeur ≈ 421 000 pour toutes les lignes)
  • distinct_header_orders (valeur identique pour toutes les lignes)

Cause

Ces features sont calculées via des window functions PARTITION BY header_order_hash :

-- Dans la vue :
count() OVER (PARTITION BY h.header_order_hash) AS header_order_shared_count
uniqExact(h.header_order_hash) OVER (PARTITION BY a.src_ip) AS distinct_header_orders

Comme h.header_order_hash est NULL pour toutes les lignes (problème 1 ci-dessus), la PARTITION BY NULL regroupe toutes les lignes dans une seule partitioncount() retourne le total de toutes les lignes pour chaque IP.

Correction (auto-résolue avec Problème 1)

Ce problème s'est résolu automatiquement une fois la MV mv_agg_header_fingerprint_1h recréée. header_order_hash est désormais non-NULL, les partitions de window functions sont correctement calculées par hash d'ordre d'en-têtes.


Problème 3 — orphan_ratio absent pour le trafic corrélé TCP

Symptôme

orphan_ratio = 0 pour toutes les lignes avec correlated = 1 (trafic TCP enrichi).

Cause

La colonne orphan_count dans ja4_processing.agg_host_ip_ja4_1h est calculée par la MV mv_agg_host_ip_ja4_1h :

sum(IF(src.orphan_side = 'A' OR src.correlated = 0, 1, 0)) AS orphan_count

Pour les connexions correlated=1, correlated = 0 est toujours faux, et orphan_side = 'A' n'est jamais vrai pour le trafic corrélé → orphan_count = 0 systématiquement.

C'est un comportement intentionnel : les connexions TCP corrélées ont une réponse confirmée, donc elles ne sont pas des requêtes orphelines par définition.

Statut

Pas d'action requise. La feature reste exclue automatiquement par A7 pour le modèle Complet (correlated=1).


Problème 4 — Features à 0 persistantes dans le modèle Applicatif

Symptôme (post-correction)

Depuis le 2026-03-17 13:05, le modèle Applicatif (trafic non-corrélé) signale encore ces features à 0 :

  • request_size_variance
  • mss_mobile_mismatch
  • is_rare_ja4

Cause

Ces features sont calculées depuis des colonnes L4/TCP qui sont absent ou non-pertinentes pour le trafic applicatif pur (correlated=0) :

Feature Cause
request_size_variance varPopMerge(total_ip_length_var) — variance de longueur IP ; trafic non-corrélé = pas de données IP brutes fiables
mss_mobile_mismatch Dépend de tcp_meta_mss et modern_browser_score — MSS non fiable sans corrélation TCP
is_rare_ja4 sum(hits) OVER (PARTITION BY ja4) < 100 — dans la fenêtre Applicatif (1h, trafic réduit), tous les JA4 sont rares

Impact

Faible — ces features sont exclues automatiquement (A7). Elles ne dégradent pas le modèle.


Impact sur le modèle IA

Feature Impact si absente Statut
header_count Perte d'un signal fort : bots envoient souvent peu d'en-têtes Corrigé
has_accept_language Perte de détection des bots sans localisation Corrigé
has_cookie Perte de détection des sessions sans état Corrigé
has_referer Perte du signal de navigation directe Corrigé
modern_browser_score Perte du score composite de conformité navigateur Corrigé
ua_ch_mismatch Perte de détection des fausses déclarations UA Corrigé
header_order_shared_count Perte de la détection de fingerprints d'en-têtes partagés Corrigé
orphan_ratio Signal faible pour trafic corrélé By design
request_size_variance Signal L4 faible pour Applicatif Normal
mss_mobile_mismatch Signal TCP faible pour Applicatif Normal

Vérification post-correction

Cycle du 2026-03-17 13:05 — résultat observé :

[Complet]    Features à 0 : ['orphan_ratio']                          ← by design ✅
[Applicatif] Features à 0 : ['request_size_variance', 'mss_mobile_mismatch', 'is_rare_ja4']  ← normales ✅
[Applicatif] Features non-discriminantes : ['tcp_shared_count']       ← agrégat global résiduel

Les 10 features header (header_count, has_accept_language, has_cookie, has_referer, modern_browser_score, ua_ch_mismatch, header_order_shared_count, distinct_header_orders, header_order_confidence, mss_mobile_mismatch pour Complet) ne sont plus dans les warnings. Le pipeline est opérationnel.