# 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 | |---------|---------|-----------------| | sentinel | Go binary + libpcap (RPM) | — (capture réseau passive) | | correlator | Go binary (RPM) | 8080 (metrics, optionnel) | | mod-reqin-log | Apache module .so (RPM) | — (intégré à httpd) | | bot-detector | Python 3.11 (Docker) | 8080 (health check) | | dashboard | Python 3.11 / FastAPI (Docker) | 8000 (API) + 3000 (frontend) | --- ## É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 des services Go (RPM) ### Build des RPMs ```bash # Tous les RPMs (sentinel + correlator + mod-reqin-log) × 3 distros make rpm-all # Ou individuellement make rpm-sentinel # → services/sentinel/dist/ make rpm-correlator # → services/correlator/dist/ make rpm-mod-reqin-log # → services/mod-reqin-log/dist/ ``` Les RPMs sont générés dans `services//dist/` avec un sous-dossier par distro (el8, el9, el10). ### Installation des RPMs ```bash # Sur le serveur cible (Rocky 9 par exemple) sudo yum install -y ./ja4sentinel-*.el9.x86_64.rpm sudo yum install -y ./logcorrelator-*.el9.x86_64.rpm sudo yum install -y ./mod_reqin_log-*.el9.x86_64.rpm ``` ### Configuration du sentinel ```bash # Fichier de configuration principal sudo cp /etc/ja4sentinel/config.yml.default /etc/ja4sentinel/config.yml sudo vi /etc/ja4sentinel/config.yml ``` Variables d'environnement (dans `/etc/sysconfig/ja4sentinel` ou `.env`) : ```bash JA4SENTINEL_INTERFACE=eth0 # Interface réseau à capturer JA4SENTINEL_PORTS=443,8443 # Ports TLS à surveiller ``` Le sentinel écrit vers le socket Unix du correlator : `/var/run/logcorrelator/network.socket` ```bash sudo systemctl enable --now ja4sentinel sudo systemctl status ja4sentinel journalctl -u ja4sentinel -f ``` ### Configuration du correlator ```bash sudo cp /etc/logcorrelator/config.yml.default /etc/logcorrelator/config.yml sudo vi /etc/logcorrelator/config.yml ``` Configuration minimale pour activer ClickHouse (`config.yml`) : ```yaml outputs: clickhouse: enabled: true dsn: clickhouse://data_writer:VotreMotDePasse@localhost:9000/ja4_logs table: http_logs_raw batch_size: 500 flush_interval_ms: 200 file: enabled: true path: /var/log/logcorrelator/correlated.log ``` Variable d'environnement alternative (dans `/etc/sysconfig/logcorrelator`) : ```bash LOGCORRELATOR_CLICKHOUSE_DSN=clickhouse://data_writer:VotreMotDePasse@localhost:9000/ja4_logs ``` ```bash sudo systemctl enable --now logcorrelator sudo systemctl status logcorrelator ``` ### Configuration de mod-reqin-log Le module Apache écrit les requêtes HTTP en JSON vers le socket Unix du correlator. ```bash # Le RPM installe automatiquement le module dans Apache # Vérifier le chargement httpd -M | grep reqin # La configuration est dans /etc/httpd/conf.d/mod_reqin_log.conf # Le socket par défaut : /var/run/logcorrelator/http.socket sudo systemctl restart httpd ``` --- ## É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 ja4sentinel logcorrelator httpd # 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 le correlator 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 ``` ┌──────────────┐ Unix socket ┌──────────────┐ ClickHouse ┌──────────────────┐ │ mod-reqin-log│──── http.socket ─────→│ │ INSERT INTO │ │ │ (Apache C11) │ (source A) │ correlator │───→ ja4_logs. │ ClickHouse │ └──────────────┘ │ │ http_logs_raw │ │ │ │ │ ┌──────────────┐ │ ┌──────────────┐ Unix socket │ │ MV parse JSON │ │ ja4_logs │ │ │ sentinel │──── network.socket ──→│ │ ↓ │ │ _raw → _logs│ │ │ (Go+libpcap) │ (source B) └──────────────┘ ja4_logs. │ └──────────────┘ │ └──────────────┘ http_logs │ │ │ │ ┌──────────────┐ │ 6 MVs agrégation│ │ ja4_processing│ │ ↓ │ │ agg_* (×6) │ │ ┌──────────────┐ SELECT features ┌──────────────┐ ja4_processing. │ │ ml_* (×2) │ │ │ bot-detector │←─── view_ai_features ─│ │ agg_*, view_* │ │ views, dicts│ │ │ (Python 3.11)│ view_thesis_feat │ ClickHouse │ │ │ audit_logs │ │ │ EIF+AE+XGB │ │ │ ml_all_scores │ └──────────────┘ │ │ │───→ INSERT scores ────→│ │ ml_detected_* │ │ └──────────────┘ └──────────────┘ └──────────────────┘ ↑ ┌──────────────┐ SELECT * │ │ dashboard │←─── ja4_processing.ml_*, agg_*, views ────────────────────────────┘ │ (FastAPI) │←─── ja4_logs.http_logs ───────────────────────────────────────────┘ └──────────────┘ ```