Files
ja4-platform/docs/deployment.md
Jacquin Antoine f88b739992 feat(e2e): add distributed E2E test framework with parametric traffic generation
Add run-e2e-test.sh with CLI parameters (--hits, --http-ratio, --dns, --tls,
--src-ips, --keep-analysis, --up) for configurable traffic generation. Traffic
runs from VM endpoints with multiple source IPs (alias IPs on eth0) to produce
distinct sessions for the ML pipeline. Fix curl TLS flags (--tlsv1.2 instead
of --tls-v1-2), skip redundant local verification in distributed mode, and
fix dashboard is_available() cache that never retried after ClickHouse recovery.

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

16 KiB
Raw Permalink Blame History

Guide de déploiement — ja4-platform

Prérequis

Composant Version minimale Notes
ClickHouse 23.8+ Requis pour REGEXP_TREE, IP_TRIE dictionaries
Docker 20.10+ Pour build des images et RPMs
Make 3.81+ Orchestration des builds
OS cible (RPM) Rocky/RHEL 8, 9, ou 10 RPMs générés pour les 3 versions

Services et leur runtime

Service Runtime Port par défaut
ja4ebpf Go binary + eBPF CO-RE (RPM) — (capture réseau passive)
bot-detector Python 3.11 (Docker) 8080 (health check)
dashboard Python 3.11 / FastAPI (Docker) 8000 (API)

Étape 1 — Installation de ClickHouse

Installation (Rocky Linux / RHEL)

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://packages.clickhouse.com/rpm/clickhouse.repo
sudo yum install -y clickhouse-server clickhouse-client
sudo systemctl enable --now clickhouse-server

Vérification

clickhouse-client --query "SELECT version()"

Étape 2 — Déploiement du schéma ClickHouse

Le schéma est géré par 13 fichiers SQL ordonnés dans shared/clickhouse/ et un script de déploiement automatisé.

Architecture des bases de données

Le système utilise deux bases de données séparées :

Base Variable d'env Défaut Contenu
Logs CLICKHOUSE_DB_LOGS ja4_logs Logs bruts et parsés
Traitement CLICKHOUSE_DB_PROCESSING ja4_processing Agrégations, ML, dictionnaires, vues, audit

Fichiers de migration

shared/clickhouse/
├── 00_database.sql           # Création des bases ja4_logs + ja4_processing
├── 01_raw_tables.sql         # ja4_logs.http_logs_raw (ingestion brute, TTL 2 heures)
├── 02_dictionaries.sql       # ja4_processing : dict_iplocate_asn, ref_bot_networks, bot_ip, bot_ja4
├── 03_anubis_tables.sql      # ja4_processing : anubis_ip_rules, anubis_asn_rules + 2 dicts (IP/CIDR + ASN)
├── 04_mv_http_logs.sql       # ja4_logs.http_logs + mv_http_logs (parsing JSON → colonnes typées)
├── 05_aggregation_tables.sql # ja4_processing : agg_host_ip_ja4_1h, agg_header_fingerprint_1h + MVs + 4 dicts
├── 06_ml_tables.sql          # ja4_processing : ml_detected_anomalies, ml_all_scores, view_ip_recurrence
├── 07_ai_features_view.sql   # ja4_processing : view_ai_features_1h (feature engineering ~63 features)
├── 08_users.sql              # Utilisateurs data_writer et analyst + permissions
├── 09_audit_table.sql        # ja4_processing : audit_logs (trace SOC, TTL 90 jours)
├── 10_perf_indexes.sql       # Index et projections de performance sur tables existantes
├── 11_views.sql              # Vues métier du dashboard (bruteforce, rotation, user_agents, entities)
├── 12_thesis_features.sql    # Tables d'agrégation avancées (path_sequences, request_timing,
│                             #   ip_behavior, resource_cascade) + MVs + vues thèse
└── deploy_schema.sh          # Script de déploiement automatisé (substitution env vars)

Déploiement avec les noms par défaut

cd shared/clickhouse/
chmod +x deploy_schema.sh
./deploy_schema.sh

Déploiement avec des noms personnalisés

CLICKHOUSE_DB_LOGS=prod_logs \
CLICKHOUSE_DB_PROCESSING=prod_analysis \
CLICKHOUSE_HOST=clickhouse.internal \
CLICKHOUSE_PORT=9000 \
CLICKHOUSE_USER=default \
CLICKHOUSE_PASSWORD=MonMotDePasse \
./deploy_schema.sh

Le script effectue une substitution sed sur chaque fichier SQL avant de l'envoyer à clickhouse-client --multiquery.

Déploiement manuel (fichier par fichier)

clickhouse-client --multiquery < shared/clickhouse/00_database.sql
clickhouse-client --multiquery < shared/clickhouse/01_raw_tables.sql
# ... etc., dans l'ordre

Vérification du déploiement

# Tables dans ja4_logs
clickhouse-client --query "SHOW TABLES FROM ja4_logs"
# Attendu : http_logs, http_logs_raw

# Tables dans ja4_processing
clickhouse-client --query "SHOW TABLES FROM ja4_processing"
# Attendu : agg_header_fingerprint_1h, agg_host_ip_ja4_1h, agg_ip_behavior_1h,
#            agg_path_sequences_1h, agg_request_timing_1h, agg_resource_cascade_1h,
#            anubis_asn_rules, anubis_ip_rules, audit_logs, bot_ip, bot_ja4,
#            ml_all_scores, ml_detected_anomalies, ref_bot_networks, ...

# Dictionnaires chargés
clickhouse-client --query "SELECT name, status FROM system.dictionaries WHERE database IN ('ja4_logs', 'ja4_processing')"

# Utilisateurs créés
clickhouse-client --query "SHOW USERS"

Étape 3 — Configuration des utilisateurs ClickHouse

Le fichier 08_users.sql crée deux utilisateurs avec des mots de passe par défaut à changer impérativement :

Utilisateurs et permissions

Utilisateur Mot de passe défaut Rôle Permissions
data_writer ChangeMe Ingestion (correlator) INSERT, SELECT sur ja4_logs.http_logs_raw
analyst ChangeMe Lecture (dashboard, bot-detector) SELECT sur ja4_logs.http_logs, ja4_processing.ml_*, ja4_processing.view_*, ja4_processing.audit_logs

Changement des mots de passe (obligatoire en production)

# Utiliser SHA256 pour la production
clickhouse-client --query "
  ALTER USER data_writer IDENTIFIED WITH sha256_password BY 'VotreMotDePasseWriter';
  ALTER USER analyst IDENTIFIED WITH sha256_password BY 'VotreMotDePasseAnalyst';
"

Permissions supplémentaires pour le bot-detector

Le bot-detector a besoin d'écrire dans les tables ML. Ajoutez ces grants pour l'utilisateur utilisé par le bot-detector (ici admin ou un utilisateur dédié) :

-- Créer un utilisateur dédié pour le bot-detector
CREATE USER IF NOT EXISTS bot_writer IDENTIFIED WITH sha256_password BY 'VotreMotDePasse';

-- Lectures : features et récurrence (ja4_processing)
GRANT SELECT ON ja4_processing.view_ai_features_1h  TO bot_writer;
GRANT SELECT ON ja4_processing.view_ip_recurrence   TO bot_writer;
GRANT SELECT ON ja4_processing.ml_detected_anomalies TO bot_writer;

-- Écritures : résultats ML (ja4_processing)
GRANT INSERT ON ja4_processing.ml_all_scores          TO bot_writer;
GRANT INSERT ON ja4_processing.ml_detected_anomalies  TO bot_writer;

-- Lectures/écritures : tables Anubis (ja4_processing) — pour fetch_rules.py
-- Seules les règles IP/CIDR et ASN sont utilisées (UA et Country ont été supprimés)
GRANT SELECT, INSERT, ALTER ON ja4_processing.anubis_ip_rules      TO bot_writer;
GRANT SELECT, INSERT, ALTER ON ja4_processing.anubis_asn_rules     TO bot_writer;
GRANT SYSTEM RELOAD DICTIONARY ON *.* TO bot_writer;

Permissions pour l'audit (dashboard)

-- Le dashboard doit pouvoir écrire dans audit_logs
GRANT INSERT ON ja4_processing.audit_logs TO analyst;

Étape 4 — Fichiers de données externes

Certains dictionnaires ClickHouse chargent des fichiers CSV depuis le disque :

# Répertoire des fichiers utilisateur ClickHouse
sudo mkdir -p /var/lib/clickhouse/user_files/

# Fichiers requis (à fournir par l'opérateur) :
# - iplocate_asn.csv    → dict_iplocate_asn (géolocalisation IP/ASN)
# - bot_ip.csv          → bot_ip (IPs de bots connues)
# - bot_ja4.csv         → bot_ja4 (signatures JA4 de bots)
# - asn_reputation.csv  → dict_asn_reputation (réputation ASN)

# Exemple de format bot_ip.csv :
# prefix,bot_name
# 198.51.100.0/24,ExampleBot
# 203.0.113.42/32,ScannerBot

# Permissions
sudo chown -R clickhouse:clickhouse /var/lib/clickhouse/user_files/

Étape 5 — Installation de ja4ebpf (RPM)

Build des RPMs

# RPM ja4ebpf × 3 distros (el8, el9, el10)
make rpm-ja4ebpf
# → services/ja4ebpf/dist/rpm/el{8,9,10}/

Le build utilise un pipeline Docker multi-étapes Rocky Linux :

  1. Létape go-builder compile le bytecode eBPF (clang/llvm) puis le binaire Go statique
  2. Les étapes rpm-el8, rpm-el9, rpm-el10 exécutent rpmbuild pour chaque distro cible
  3. Létape alpine collecte les RPMs via --output type=local

Installation du RPM

# Sur le serveur cible (Rocky 9 par exemple)
sudo yum install -y ./ja4ebpf-*.el9.x86_64.rpm

Configuration de ja4ebpf

# Fichier de configuration principal
sudo cp /etc/ja4ebpf/config.yml.example /etc/ja4ebpf/config.yml
sudo vi /etc/ja4ebpf/config.yml

Variables denvironnement clés (dans /etc/sysconfig/ja4ebpf) :

Variable Défaut Description
JA4EBPF_INTERFACE eth0 Interface réseau à observer
JA4EBPF_CLICKHOUSE_DSN DSN ClickHouse (ex: clickhouse://data_writer:pwd@host:9000/ja4_logs)
JA4EBPF_TARGET_BINARY /usr/sbin/httpd Binaire OpenSSL à hooker (uprobe SSL_read)
JA4EBPF_BATCH_SIZE 500 Taille des batchs dinsertion ClickHouse
JA4EBPF_FLUSH_INTERVAL_MS 200 Intervalle de flush (ms)
JA4EBPF_SESSION_TIMEOUT_MS 500 Timeout orphelin (ms)
sudo systemctl enable --now ja4ebpf
sudo systemctl status ja4ebpf
journalctl -u ja4ebpf -f

Capabilities Linux requises (SELinux Enforcing)

ja4ebpf ne tourne pas en root absolu. Le fichier systemd utilise les capabilities minimales :

Capability Raison
CAP_BPF Chargement des programmes eBPF (kernel 5.8+)
CAP_SYS_ADMIN Requis pour les uprobes et RHEL 8 (kernel 4.18 <5.8)
CAP_NET_ADMIN Attachement des hooks TC ingress
CAP_PERFMON Accès aux perf events pour les uprobes

Étape 6 — Installation des services Python (Docker)

Bot-detector

cd services/bot-detector

# Copier et configurer .env
cp .env.example .env
vi .env   # Renseigner CLICKHOUSE_HOST, mots de passe, etc.

Variables d'environnement clés :

Variable Défaut Description
CLICKHOUSE_HOST clickhouse Hôte ClickHouse
CLICKHOUSE_PORT 8123 Port HTTP ClickHouse
CLICKHOUSE_DB_PROCESSING ja4_processing Base de traitement
CLICKHOUSE_DB_LOGS ja4_logs Base de logs
CLICKHOUSE_USER admin Utilisateur (utiliser bot_writer en prod)
CLICKHOUSE_PASSWORD Mot de passe
ANOMALY_THRESHOLD -0.05 Seuil de détection d'anomalies (fallback)
CYCLE_INTERVAL_SEC 300 Intervalle entre cycles de détection (secondes)
RETRAIN_INTERVAL_HOURS 24 Intervalle de réentraînement des modèles
AE_WEIGHT 0.30 Poids du NFEnsemble dans l'ensemble (α)
NF_UNCERTAINTY_THRESHOLD 1.0 Seuil d'incertitude inter-modèles pour détection adversariale
MIN_HUMAN_BASELINE 500 Nombre minimum de sessions humaines pour entraîner l'IF
BASELINE_ACCEPT_UNKNOWN false Mode test : fallback ASN unknown si baseline ISP insuffisante
XGB_WEIGHT 0.20 Poids de XGBoost dans l'ensemble (β)
ENABLE_MULTIWINDOW false Active les variantes 24h (Complet/Applicatif)
HEALTH_PORT 8080 Port du endpoint /health
docker compose up -d

Dashboard

cd services/dashboard

# Copier et configurer .env
cp .env.example .env
vi .env   # Renseigner CLICKHOUSE_HOST, mots de passe, etc.

Variables d'environnement clés :

Variable Défaut Description
CLICKHOUSE_HOST clickhouse Hôte ClickHouse
CLICKHOUSE_PORT 8123 Port HTTP ClickHouse
CLICKHOUSE_DB_PROCESSING ja4_processing Base de traitement
CLICKHOUSE_DB_LOGS ja4_logs Base de logs
CLICKHOUSE_USER analyst Utilisateur en lecture
CLICKHOUSE_PASSWORD Mot de passe
API_HOST 0.0.0.0 Adresse d'écoute de l'API
API_PORT 8000 Port de l'API FastAPI
CORS_ORIGINS ["http://localhost:3000"] Origines CORS autorisées
docker compose up -d

Étape 7 — Vérification de bout en bout

1. Vérifier que les services tournent

# Services systemd (Go)
sudo systemctl status ja4ebpf

# Services Docker (Python)
docker compose -f services/bot-detector/docker-compose.yml ps
docker compose -f services/dashboard/docker-compose.yaml ps

2. Vérifier l'ingestion des logs

# Logs bruts ingérés par ja4ebpf
clickhouse-client --query "SELECT count() FROM ja4_logs.http_logs_raw"

# Logs parsés par la vue matérialisée
clickhouse-client --query "SELECT count() FROM ja4_logs.http_logs"

# Derniers logs
clickhouse-client --query "
  SELECT time, src_ip, method, host, path, ja4
  FROM ja4_logs.http_logs
  ORDER BY time DESC
  LIMIT 5
"

3. Vérifier les agrégations

clickhouse-client --query "
  SELECT window_start, count()
  FROM ja4_processing.agg_host_ip_ja4_1h
  GROUP BY window_start
  ORDER BY window_start DESC
  LIMIT 5
"

4. Vérifier les détections ML

clickhouse-client --query "
  SELECT src_ip, anomaly_score, label, detected_at
  FROM ja4_processing.ml_detected_anomalies
  ORDER BY detected_at DESC
  LIMIT 5
"

5. Tester le dashboard

curl -s http://localhost:8000/api/metrics | python3 -m json.tool | head -20
curl -s http://localhost:8000/api/health

Scripts utilitaires

Les scripts dans scripts/ facilitent l'initialisation et la maintenance de la stack :

init-stack.sh — Initialisation complète

Déploie le schéma SQL, charge les données CSV de référence et vérifie que tous les composants sont opérationnels :

./scripts/init-stack.sh                         # init stack de dev
./scripts/init-stack.sh --container my-ch-1     # conteneur ClickHouse spécifique
./scripts/init-stack.sh --reset                 # DROP databases, tout recréer
./scripts/init-stack.sh --import-prod            # init + import données prod

import-prod-data.sh — Import de données de production

Importe les données exportées au format Native avec décalage temporel automatique :

./scripts/import-prod-data.sh                    # décalage auto (max(time) → now)
./scripts/import-prod-data.sh --shift 3600       # décalage manuel (secondes)
./scripts/import-prod-data.sh --no-truncate      # conserver les données existantes

reload-prod-logs.sh — Rechargement depuis la production

Exporte les http_logs de la production et les réimporte dans la base de dev :

./scripts/reload-prod-logs.sh                    # décalage auto
./scripts/reload-prod-logs.sh --days 7           # exporte les N derniers jours
./scripts/reload-prod-logs.sh --cron             # mode silencieux (pour crontab)

update-csv-data.sh — Mise à jour des données CSV

Télécharge et génère tous les fichiers CSV de référence (bot IPs, JA4, ASN) :

./scripts/update-csv-data.sh                     # génère tout
./scripts/update-csv-data.sh --install-stubs     # copie aussi les stubs de test

Schéma réseau récapitulatif

 Trafic HTTPS/HTTP (port 80/443)
         |
         v
+-----------------+
|    ja4ebpf      |  TC ingress hook  -- L3/L4/L5 (SYN, TLS ClientHello)
|  (eBPF CO-RE)   |  uprobe SSL_read  -- L7 HTTPS (flux déchiffré)
|                 |  kprobe tcp_recvmsg - L7 HTTP (port 80/8080)
+-----------------+
         |
         | INSERT batch (HTTP bulk)
         v
+-----------------+                    +------------------+
|   ClickHouse    |-- MV parse JSON -> | ja4_logs.        |
|                 |                    |   http_logs_raw  |
|                 |                    |   http_logs      |
|                 |-- 6 MVs agg -----> | ja4_processing.  |
|                 |                    |   agg_*(x6)      |
|                 |                    |   ml_*(x2)       |
+-----------------+                    +------------------+
         ^
         |
+-----------------+     SELECT view_ai_features
|   bot-detector  |<--  view_thesis_features
|  (EIF+NF+XGB)   |
|                 |-->  INSERT ml_all_scores, ml_detected_anomalies
+-----------------+
+-----------------+
|   dashboard     |<--  ja4_processing.ml_*, agg_*, views
|   (FastAPI)     |<--  ja4_logs.http_logs
+-----------------+