# Architecture

ja4-platform est un pipeline de sécurité qui capture le trafic réseau en temps réel, génère des empreintes TLS JA4/JA3, corrèle les handshakes TLS avec les requêtes HTTP, applique une détection d'anomalies par apprentissage automatique (ensemble triple voix), et présente les résultats dans un tableau de bord SOC. ClickHouse sert de magasin central reliant tous les services, organisé en deux bases de données distinctes.

## Architecture système

```
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                               Serveur Linux cible (Apache)                          │
│                                                                                     │
│  ┌─────────────────┐  HTTP req    ┌───────────────────────┐                         │
│  │   Client         │────────────▶│  Apache HTTPD          │                        │
│  │  (navigateur /   │             │  + mod-reqin-log (C)   │                        │
│  │   bot)           │             └───────────┬───────────┘                         │
│  │                  │                         │ JSON / UNIX DGRAM                   │
│  │                  │                         │ /var/run/logcorrelator/http.socket   │
│  │                  │                         ▼                                     │
│  │                  │  TLS CH     ┌──────────────────────────────────────┐           │
│  │                  │────────────▶│  sentinel (Go · libpcap)             │          │
│  └─────────────────┘   (pcap)    │  → JA4/JA3 fingerprints              │          │
│                                   └───────────┬──────────────────────────┘          │
│                                               │ JSON / UNIX DGRAM                   │
│                                               │ /var/run/logcorrelator/network.socket│
│                                               ▼                                     │
│                                   ┌───────────────────────────────┐                 │
│                                   │  correlator (Go · hex. arch)  │                 │
│                                   │  join src_ip:src_port + TTL   │                 │
│                                   └───────────┬───────────────────┘                 │
│                                               │                                     │
└───────────────────────────────────────────────┼─────────────────────────────────────┘
                                                │ INSERT (Native TCP :9000)
                                                ▼
                    ┌───────────────────────────────────────────────────────┐
                    │                    ClickHouse 24.8                    │
                    │                                                       │
                    │   ja4_logs                    ja4_processing           │
                    │  ┌────────────────┐          ┌────────────────────┐   │
                    │  │ http_logs_raw  │──(MV)──▶ │ agg_host_ip_ja4_1h│   │
                    │  │   ↓ mv_http_logs           │ agg_header_fp_1h │   │
                    │  │ http_logs      │──(MVs)──▶│ agg_path_seq_1h  │   │
                    │  └────────────────┘          │ agg_request_tm_1h│   │
                    │                               │ agg_ip_behavior_1h│  │
                    │                               │ agg_resource_cas_1h│ │
                    │                               │ ml_detected_anom. │  │
                    │                               │ ml_all_scores     │  │
                    │                               │ view_ai_features  │  │
                    │                               │ view_thesis_feat. │  │
                    │                               │ audit_logs, dicts │  │
                    │                               └────────────────────┘  │
                    └──────────┬──────────────────────────┬────────────────┘
                               │ SELECT                    │ SELECT / INSERT
                ┌──────────────┘                           └──────────────┐
                ▼                                                          ▼
     ┌───────────────────────┐                              ┌───────────────────────┐
     │  bot-detector          │                              │  dashboard             │
     │  Python 3.11           │                              │  FastAPI + Jinja2      │
     │                        │                              │  htmx + Chart.js       │
     │  Lit :                 │                              │  Tailwind CSS (CDN)    │
     │   view_ai_features_1h  │                              │                        │
     │   view_thesis_feat_1h  │                              │  53 routes (37 API     │
     │   view_ip_recurrence   │                              │   + 16 pages HTML)     │
     │  Écrit :               │                              │  16 templates Jinja2   │
     │   ml_detected_anomalies│                              │  16 pages SOC          │
     │   ml_all_scores        │                              │                        │
     │   fleet_detections     │                              │  Lit : ml_*, agg_*,    │
     │   ml_performance_metrics│                             │   http_logs, audit_logs│
     └───────────────────────┘                              └───────────────────────┘
```

## Flux de données — 5 phases

### Phase 1 — Capture

1. **mod-reqin-log** (module Apache C11) intercepte chaque requête HTTP dans le hook `post_read_request`. Il sérialise method, path, headers, client IP/port en JSON et envoie le datagramme vers `/var/run/logcorrelator/http.socket`.

2. **sentinel** (démon Go) capture les paquets TLS ClientHello via libpcap sur les ports configurés (défaut : 443, 8443). Il extrait les métadonnées IP/TCP, génère les empreintes JA4 et JA3, et envoie le résultat en JSON vers `/var/run/logcorrelator/network.socket`.

### Phase 2 — Corrélation

3. **correlator** (démon Go, architecture hexagonale) écoute les deux sockets Unix. Il met en tampon les événements entrants et les corrèle par `src_ip:src_port` dans une fenêtre temporelle configurable (défaut : 10 s). Le mode `one_to_many` (Keep-Alive) permet de réutiliser un seul handshake TLS (source B) pour plusieurs requêtes HTTP (source A). Les événements corrélés fusionnent les champs HTTP + TLS en un objet `CorrelatedLog` JSON, inséré dans **`ja4_logs.http_logs_raw`**.

### Phase 3 — Enrichissement (ClickHouse)

4. **mv_http_logs** (vue matérialisée) transforme le JSON de `http_logs_raw` en la table structurée `ja4_logs.http_logs`, enrichissant chaque ligne avec :
   - Données ASN via `dict_iplocate_asn` (IP_TRIE)
   - Identification Anubis via `dict_anubis_ip` (IP_TRIE) et `dict_anubis_asn` (FLAT) — règles IP/CIDR + ASN uniquement, avec priorité COALESCE(IP, ASN)

5. **6 vues matérialisées d'agrégation** alimentent les tables `ja4_processing.agg_*` en fenêtres comportementales d'1 heure :
   - `agg_host_ip_ja4_1h` — Agrégations par (host, src_ip, ja4)
   - `agg_header_fingerprint_1h` — Empreintes d'en-têtes HTTP
   - `agg_path_sequences_1h` — Séquences de chemins (n-grams)
   - `agg_request_timing_1h` — Métriques de timing inter-requêtes
   - `agg_ip_behavior_1h` — Comportement réseau par IP
   - `agg_resource_cascade_1h` — Cascades de ressources

6. **view_ai_features_1h** joint les tables d'agrégation et calcule ~63 features ML par tuple `(src_ip, ja4, host)`.

### Phase 4 — Détection

7. **bot-detector** (Python 3.11, 12 modules) s'exécute en cycle de 5 minutes :
   - **Pipeline bifurqué** :
     - **Complet** (L3→L7, ~85 features, `correlated=1`) — trafic corrélé TCP+TLS+HTTP
     - **Applicatif** (L7 seulement, ~73 features, `correlated=0`) — trafic HTTP non corrélé
   - **Ensemble triple voix** :
     - **Extended Isolation Forest** (isotree) — scoreur non supervisé principal
     - **Autoencoder** (PyTorch, architecture n→64→32→16→32→64→n) — erreur de reconstruction
     - **XGBoost** — supervisé, entraîné sur les labels SOC (`soc_feedback`)
   - **Score final** : `final = meta_learner.predict(eif_norm, ae_norm, xgb_prob, volume, correlated)` avec fallback sur pondération linéaire fixe `(1-β) × ((1-α) × eif_norm + α × ae_norm) + β × xgb_prob` (α=0.30, β=0.20)
   - **MetaLearner** (régression logistique) entraîné automatiquement sur les labels accumulés (seuil: 1000 labels)
   - **Seuil adaptatif** par percentile, détection de dérive conceptuelle (KS + KL divergence)
   - **fleet_detector** (NetworkX) — graphe bipartite JA4×ASN, `fleet_score`, table `fleet_detections`
   - **HDBSCAN** — regroupement en campagnes d'attaque
   - **Détection de navigateur** — 6 axes multifactoriels (confiance ≥ 0.55 → `LEGITIMATE_BROWSER`)
   - **ExIFFI** — importance de features native à l'EIF (alternative à SHAP)
   - **Explicabilité SHAP** — contribution de chaque feature au score d'anomalie
   - **Métriques de cycle** (`metrics.py`) — table `ml_performance_metrics`, alertes calibration
   - **Niveaux de menace** : `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`, `NORMAL`, `LEGITIMATE_BROWSER`, `KNOWN_BOT`, `ANUBIS_DENY`, `ANUBIS_ALLOW`

### Phase 5 — Visualisation

8. **dashboard** (FastAPI + Jinja2 + htmx + Chart.js + Tailwind CSS CDN) expose 53 routes (37 API JSON + 16 pages HTML) et 16 templates Jinja2 pour les analystes SOC :
   - Pages : overview, detections, scores, traffic, ip_detail, ja4_detail, cluster_detail, campaigns, features, models, classify, tactics, reflists, network, fleet, health

## Matrice d'interaction des composants

| De ↓ \ Vers → | mod-reqin-log | sentinel | correlator | ClickHouse | bot-detector | dashboard |
|----------------|:---:|:---:|:---:|:---:|:---:|:---:|
| **mod-reqin-log** | — | — | UNIX DGRAM (source A) | — | — | — |
| **sentinel** | — | — | UNIX DGRAM (source B) | — | — | — |
| **correlator** | — | — | — | Native TCP :9000 (INSERT) | — | — |
| **ClickHouse** | — | — | — | MVs internes | — | — |
| **bot-detector** | — | — | — | HTTP :8123 (SELECT/INSERT) | — | — |
| **dashboard** | — | — | — | HTTP :8123 (SELECT/INSERT) | — | — |

## Propriété des tables ClickHouse

### Base `ja4_logs`

| Table / Vue | Écrit par | Lu par |
|-------------|-----------|--------|
| `http_logs_raw` | correlator | mv_http_logs (MV) |
| `http_logs` | mv_http_logs (MV) | mv_agg_* (6 MVs), dashboard |
| `mv_http_logs` | — (MV automatique) | — |

### Base `ja4_processing`

| Table / Vue | Écrit par | Lu par |
|-------------|-----------|--------|
| `agg_host_ip_ja4_1h` | mv_agg_host_ip_ja4_1h | view_ai_features_1h, dashboard |
| `agg_header_fingerprint_1h` | mv_agg_header_fingerprint_1h | view_ai_features_1h, dashboard |
| `agg_path_sequences_1h` | mv_agg_path_sequences_1h | view_thesis_features_1h |
| `agg_request_timing_1h` | mv_agg_request_timing_1h | view_thesis_features_1h |
| `agg_ip_behavior_1h` | mv_agg_ip_behavior_1h | view_thesis_features_1h |
| `agg_resource_cascade_1h` | mv_agg_resource_cascade_1h | view_thesis_features_1h |
| `ml_detected_anomalies` | bot-detector | dashboard |
| `ml_all_scores` | bot-detector | dashboard |
| `fleet_detections` | bot-detector (`fleet.py`) | dashboard |
| `ml_performance_metrics` | bot-detector (`metrics.py`) | dashboard |
| `soc_feedback` | dashboard (`/api/classify`) | bot-detector |
| `audit_logs` | dashboard | dashboard |
| `anubis_ip_rules` | fetch_rules.py | dict_anubis_ip |
| `anubis_asn_rules` | fetch_rules.py | dict_anubis_asn |
| `ref_bot_networks` | update-csv-data.sh | dict_bot_ip |
| `bot_ip` | update-csv-data.sh | dict_bot_ip |
| `bot_ja4` | update-csv-data.sh | dict_bot_ja4 |
| `view_ai_features_1h` | — (vue) | bot-detector |
| `view_ip_recurrence` | — (vue) | bot-detector |
| `view_thesis_features_1h` | — (vue) | bot-detector |
| `view_form_bruteforce_detected` | — (vue) | dashboard |
| `view_host_ip_ja4_rotation` | — (vue) | dashboard |
| `view_dashboard_user_agents` | — (vue) | dashboard |
| `view_dashboard_entities` | — (vue) | dashboard |
| `view_resource_cascade_1h` | — (vue) | dashboard |

### Dictionnaires (8)

| Dictionnaire | Layout | Source | Utilisation |
|--------------|--------|--------|-------------|
| `dict_iplocate_asn` | IP_TRIE | Fichier CSV | Géolocalisation IP → ASN |
| `dict_bot_ip` | IP_TRIE | Table `bot_ip` | IPs de bots connues |
| `dict_bot_ja4` | COMPLEX_KEY_HASHED | Table `bot_ja4` | Signatures JA4 de bots |
| `dict_browser_ja4` | COMPLEX_KEY_HASHED | Table (CSV) | Signatures JA4 de navigateurs |
| `dict_browser_h2` | COMPLEX_KEY_HASHED | Table (CSV) | Fingerprints HTTP/2 SETTINGS par navigateur |
| `dict_asn_reputation` | HASHED | Fichier CSV | Réputation ASN (isp/datacenter/hosting/cdn) |
| `dict_anubis_ip` | IP_TRIE | Table `anubis_ip_rules` | Règles Anubis IP/CIDR |
| `dict_anubis_asn` | FLAT | Table `anubis_asn_rules` | Règles Anubis ASN |

## Algorithme de corrélation

Le correlator joint les événements HTTP (source A) avec les événements TLS/réseau (source B) via une corrélation à deux clés :

1. **Clé** : `src_ip + src_port` — l'IP source et le port éphémère du client identifient une connexion TCP de manière unique.
2. **Fenêtre temporelle** : Les événements doivent arriver dans la fenêtre configurée (défaut 10 secondes).
3. **Mode de correspondance** :
   - `one_to_one` : Chaque événement B correspond à un seul événement A (consommé après correspondance).
   - `one_to_many` (défaut, Keep-Alive) : Un seul B (handshake TLS) peut correspondre à plusieurs A (requêtes HTTP) sur la même connexion. Le B possède un TTL configurable (défaut 120 s) réinitialisé à chaque correspondance.
4. **Gestion des orphelins** : Les événements A sans correspondance sont émis après un délai configurable (défaut 500 ms) avec `correlated=false` et `orphan_side=A`.

La sortie est insérée dans **`ja4_logs.http_logs_raw`** (base `ja4_logs`), pas dans `ja4_processing`.

## Pipeline ML — bot-detector (détail)

```
view_ai_features_1h ──┐                    ┌─── ml_detected_anomalies
view_thesis_feat_1h ──┤   ┌────────────┐   │
view_ip_recurrence ───┤   │ Pré-       │   │
                      ├──▶│ traitement │──▶│ Bifurcation :
                      │   │ + filtrage │   │  ├── Complet   (correlated=1, ~85 feat.)
                      │   └────────────┘   │  └── Applicatif(correlated=0, ~73 feat.)
                      │                    │
                      │   ┌────────────┐   │  Pour chaque branche :
                      │   │ Ensemble   │   │   ├── Extended Isolation Forest (EIF)
                      │   │ triple     │──▶│   ├── Autoencoder (PyTorch)
                      │   │ voix       │   │   └── XGBoost (supervisé)
                      │   └────────────┘   │
                      │                    │  Score = MetaLearner(eif, ae, xgb) ou
                      │                    │          (1-β)×((1-α)×EIF + α×AE) + β×XGB
                      │   ┌────────────┐   │
                      │   │ Post-      │   ├─── ml_all_scores
                      └──▶│ traitement │──▶│
                          │ HDBSCAN    │   │  Niveaux : CRITICAL / HIGH / MEDIUM /
                          │ fleet.py   │   │   LOW / NORMAL / LEGITIMATE_BROWSER /
                          │ Browser 6ax│   │   KNOWN_BOT / ANUBIS_DENY / ANUBIS_ALLOW
                          │ ExIFFI+SHAP│   │
                          │ metrics.py │   ├─── fleet_detections
                          └────────────┘   └─── ml_performance_metrics
```

## Référence des empreintes JA4/JA3

### JA4

Format moderne de fingerprinting TLS (successeur de JA3) :

```
t{TLS_VER}{SNI}{CIPHER_COUNT}{EXT_COUNT}_{CIPHER_HASH}_{EXT_HASH}
```

Exemple : `t13d1516h2_8daaf6152771_b0da82dd1658`

- Préfixe `t` = TLS, suivi de la version (`13` = TLS 1.3)
- `d` = SNI présent, `i` = SNI absent
- Nombre de cipher suites et nombre d'extensions
- Hash SHA-256 tronqué des cipher suites et extensions triées

### JA3

Format original de fingerprinting TLS :

```
{TLS_VER},{CIPHERS},{EXTENSIONS},{ELLIPTIC_CURVES},{EC_POINT_FORMATS}
```

Le `ja3_hash` est le hash MD5 de la chaîne JA3.

Les deux empreintes sont générées par sentinel à partir du payload TLS ClientHello.

## Stack technologique

| Composant | Technologie |
|-----------|-------------|
| Capture de paquets | Go 1.24.6 + libpcap (gopacket) |
| Logging HTTP | Module Apache C11 (APR, `apxs`) |
| Corrélation d'événements | Go 1.24.6 (architecture hexagonale) |
| Détection ML — EIF | Python 3.11 + isotree |
| Détection ML — Autoencoder | Python 3.11 + PyTorch |
| Détection ML — Supervisé | Python 3.11 + XGBoost |
| Détection ML — Ensemble | Python 3.11 + MetaLearner (régression logistique) |
| Clustering de campagnes | HDBSCAN + NetworkX (fleet detection) |
| Explicabilité | SHAP + ExIFFI |
| Backend dashboard | FastAPI + Jinja2 (Python 3.11) |
| Frontend dashboard | htmx + Chart.js + ECharts + Tailwind CSS (CDN) |
| Magasin de données | ClickHouse 24.8 (dual-database) |
| Déploiement | systemd, Docker, RPM (Rocky 8/9/10) |
| IPC | Sockets UNIX datagramme |
| Workspace Go | `go.work` (Go 1.24.6) |

## Fichiers de schéma SQL (13)

```
shared/clickhouse/
├── 00_database.sql           # Création des bases ja4_logs + ja4_processing
├── 01_raw_tables.sql         # ja4_logs.http_logs_raw (TTL 2 heures)
├── 02_dictionaries.sql       # dict_iplocate_asn, ref_bot_networks, bot_ip, bot_ja4
├── 03_anubis_tables.sql      # anubis_ip_rules, anubis_asn_rules + 2 dictionnaires
├── 04_mv_http_logs.sql       # ja4_logs.http_logs + mv_http_logs (JSON → colonnes)
├── 05_aggregation_tables.sql # agg_host_ip_ja4_1h, agg_header_fingerprint_1h + MVs + 4 dicts
├── 06_ml_tables.sql          # ml_detected_anomalies, ml_all_scores, view_ip_recurrence
├── 07_ai_features_view.sql   # view_ai_features_1h (feature engineering ~63 features)
├── 08_users.sql              # Utilisateurs data_writer + analyst
├── 09_audit_table.sql        # audit_logs (trace SOC, TTL 90 jours)
├── 10_perf_indexes.sql       # Index et projections de performance
├── 11_views.sql              # Vues métier du dashboard (4 vues)
├── 12_thesis_features.sql    # agg_path_sequences, agg_request_timing, agg_ip_behavior,
│                             #   agg_resource_cascade + MVs + view_thesis_features_1h
│                             #   + view_resource_cascade_1h
└── deploy_schema.sh          # Script de déploiement automatisé (substitution env vars)
```
