Files
ja4-platform/docs/deployment.md
toto 3b047b680a fix(ja4ebpf): split bpf2go generate into Ja4Tc + Ja4Ssl, fix RPM systemd-rpm-macros
- Use two separate //go:generate directives (Ja4Tc for tc_capture.c, Ja4Ssl
  for uprobe_ssl.c) to avoid duplicate LICENSE symbol and multi-file clang issue
- Update loader.go to hold tcObjs/sslObjs separately with correct field names:
  UprobeSslSetFd, UprobeSslReadEntry, UretprobeSslReadExit,
  KprobeAccept4Entry, KretprobeAccept4Exit
- Add systemd-rpm-macros to all three RPM build stages (el8/el9/el10)
  so that %{_unitdir} macro resolves correctly
- RPMs now build successfully for el8, el9, el10

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-11 23:21:11 +02:00

473 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)
```bash
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
```bash
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
```bash
cd shared/clickhouse/
chmod +x deploy_schema.sh
./deploy_schema.sh
```
### Déploiement avec des noms personnalisés
```bash
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)
```bash
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
```bash
# 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)
```bash
# 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é) :
```sql
-- 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)
```sql
-- 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 :
```bash
# 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
```bash
# 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
```bash
# Sur le serveur cible (Rocky 9 par exemple)
sudo yum install -y ./ja4ebpf-*.el9.x86_64.rpm
```
### Configuration de ja4ebpf
```bash
# 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) |
```bash
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
```bash
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 de l'Autoencoder dans l'ensemble (α) |
| `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 |
```bash
docker compose up -d
```
### Dashboard
```bash
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 |
```bash
docker compose up -d
```
---
## Étape 7 — Vérification de bout en bout
### 1. Vérifier que les services tournent
```bash
# 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
```bash
# 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
```bash
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
```bash
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
```bash
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 :
```bash
./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 :
```bash
./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 :
```bash
./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) :
```bash
./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+AE+XGB) |
| |--> INSERT ml_all_scores, ml_detected_anomalies
+-----------------+
+-----------------+
| dashboard |<-- ja4_processing.ml_*, agg_*, views
| (FastAPI) |<-- ja4_logs.http_logs
+-----------------+
```