C2 Server (C3PO)¶
Documentation complète disponible
Cette page est un résumé. La documentation exhaustive de C3PO est disponible dans la section dédiée :
C3PO — Control Server — Architecture, installation, TUI, dashboard, API (40+ endpoints), déploiement, sécurité.
Le serveur C2 (Command & Control) C3PO gère la communication avec les agents ESP32 déployés.
Vue d'ensemble¶
C3PO est le serveur C2 principal d'Espilon, offrant :
- CLI interactif avec autocomplétion
- TUI multi-pane (Textual) pour voir tous les devices simultanément
- Dashboard Web (Flask) avec Dashboard, Cameras, MLAT, OTA, Build, CAN
- Réception caméra UDP avec enregistrement vidéo
- Multilatération (MLAT) pour le positionnement RSSI
- Communication chiffrée ChaCha20 + Protocol Buffers
- Gestion de groupes de devices
graph TB
subgraph "ESP32 Agents"
A1[Agent 1]
A2[Agent 2]
A3[Agent 3]
CAM[ESP32-CAM]
end
subgraph "C3PO Server"
TCP[TCP Server<br/>Port 2626]
UDP[UDP Receiver<br/>Port 5000]
WEB[Web Dashboard<br/>Port 8000]
MLAT[MLAT Engine]
CLI[CLI / TUI]
end
A1 <-->|ChaCha20 + Protobuf| TCP
A2 <-->|ChaCha20 + Protobuf| TCP
A3 <-->|ChaCha20 + Protobuf| TCP
CAM -->|JPEG Frames| UDP
TCP --> CLI
UDP --> WEB
MLAT --> WEB
CLI --> WEB
Installation¶
Prérequis¶
- Python 3.10+ (testé avec 3.11)
- pip (gestionnaire de paquets)
Étapes¶
Dépendances¶
| Package | Version | Usage |
|---|---|---|
pycryptodome |
>=3.15.0 | Chiffrement ChaCha20 |
protobuf |
>=4.21.0 | Sérialisation Protocol Buffers |
flask |
>=2.0.0 | Dashboard Web + API |
python-dotenv |
>=1.0.0 | Configuration .env |
textual |
>=0.40.0 | Interface TUI multi-pane |
opencv-python |
>=4.8.0 | Traitement vidéo caméra |
numpy |
>=1.24.0 | Calculs matriciels |
scipy |
>=1.10.0 | Algorithme MLAT |
Vérification¶
Configuration¶
Fichier .env¶
Copiez .env.example vers .env et ajustez :
# C2 TCP Server
C2_HOST=0.0.0.0
C2_PORT=2626
# Web Dashboard
WEB_HOST=0.0.0.0
WEB_PORT=8000
WEB_USERNAME=admin
WEB_PASSWORD=admin
FLASK_SECRET_KEY=change_this_for_prod
# Camera UDP
UDP_HOST=0.0.0.0
UDP_PORT=5000
CAMERA_SECRET_TOKEN=Sup3rS3cretT0k3n
# MLAT API
MULTILAT_AUTH_TOKEN=multilat_secret_token
# Storage
IMAGE_DIR=static/streams
VIDEO_FPS=10
VIDEO_CODEC=MJPG
Clés de chiffrement¶
Les clés ChaCha20 doivent correspondre entre le C2 et le firmware ESP32.
Sécurité des clés
- Ne jamais utiliser les clés par défaut en production
- Ne jamais commiter les clés dans le repo
- Les clés doivent être identiques sur le C2 et les ESP32
Lancement¶
Mode CLI (classique)¶
Mode TUI (Textual)¶
Le mode TUI affiche :
- Panneau gauche : Tous les devices connectés avec leurs logs
- Panneau droit : Logs globaux du système
- Barre inférieure : Input avec autocomplétion style zsh
Raccourcis TUI¶
| Touche | Action |
|---|---|
| Alt+G | Toggle panneau global |
| Ctrl+L | Clear logs globaux |
| Ctrl+Q | Quitter |
| Esc | Focus sur l'input |
| Tab | Autocomplétion |
| Up / Down | Historique |
Commandes CLI¶
Gestion des devices¶
list¶
Liste tous les devices connectés :
c2:> list
Connected Devices:
ID IP Address Status Connected For Last Seen
─────────────────────────────────────────────────────────────────────
ce4f626b 192.168.1.42 online 2m 34s 0s
a1b2c3d4 192.168.1.43 online 15m 12s 2s
send¶
Envoie une commande à un device :
# À un device spécifique
c2:> send ce4f626b system_uptime
# À tous les devices
c2:> send all system_mem
# À un groupe
c2:> send group scanners mlat start AA:BB:CC:DD:EE:FF
modules¶
Affiche les commandes ESP disponibles par module :
c2:> modules
╔══════════════════════════════════════════════════════════════╗
║ ESP MODULES & COMMANDS ║
╚══════════════════════════════════════════════════════════════╝
┌─ system ─────────────────────────────────────────────────────┐
│ system_reboot Reboot ESP32 │
│ system_mem Memory info │
│ system_uptime Device uptime │
│ system_info Auto-query on connect │
└──────────────────────────────────────────────────────────────┘
...
Gestion des groupes¶
# Créer/ajouter à un groupe
c2:> group add scanners ce4f626b a1b2c3d4
# Lister les groupes
c2:> group list
# Voir les membres d'un groupe
c2:> group show scanners
# Retirer d'un groupe
c2:> group remove scanners ce4f626b
Services¶
web¶
Gère le dashboard web :
c2:> web start # Démarre sur http://0.0.0.0:8000
c2:> web stop # Arrête le serveur
c2:> web status # Affiche le statut + stats MLAT
camera¶
Gère le récepteur UDP caméra :
c2:> camera start # Démarre sur UDP port 5000
c2:> camera stop # Arrête le récepteur
c2:> camera status # Packets reçus, frames décodés, erreurs
Autres commandes¶
| Commande | Description |
|---|---|
help [cmd] |
Aide générale ou par commande |
active_commands |
Commandes en cours d'exécution |
clear |
Efface l'écran (CLI) ou logs globaux (TUI) |
exit |
Quitter C3PO |
Commandes ESP (Modules)¶
Les commandes envoyées aux ESP32 sont organisées par module.
Module System¶
| Commande | Description |
|---|---|
system_reboot |
Redémarre l'ESP32 |
system_mem |
Affiche la mémoire disponible |
system_uptime |
Temps depuis le boot |
system_info |
Infos complètes (envoyé auto à la connexion) |
Module Network¶
| Commande | Arguments | Description |
|---|---|---|
ping |
<host> |
Ping ICMP |
arp_scan |
- | Scan ARP du réseau local |
proxy_start |
<ip> <port> |
Démarre proxy TCP |
proxy_stop |
- | Arrête le proxy |
dos_tcp |
<ip> <port> <count> |
TCP flood (test) |
Module FakeAP¶
| Commande | Arguments | Description |
|---|---|---|
fakeap_start |
<ssid> [open\|wpa2] [pass] |
Crée un point d'accès |
fakeap_stop |
- | Arrête le Fake AP |
fakeap_status |
- | Statut du Fake AP |
fakeap_clients |
- | Liste les clients connectés |
fakeap_portal_start |
- | Active le portail captif |
fakeap_portal_stop |
- | Désactive le portail |
fakeap_sniffer_on |
- | Active le sniffer |
fakeap_sniffer_off |
- | Désactive le sniffer |
Module Recon (Camera + MLAT)¶
Caméra¶
| Commande | Arguments | Description |
|---|---|---|
cam_start |
<ip> <port> |
Démarre le flux vidéo vers C2 |
cam_stop |
- | Arrête le flux |
MLAT (Multilatération)¶
| Commande | Arguments | Description |
|---|---|---|
mlat config |
[gps\|local] <c1> <c2> |
Configure la position du scanner |
mlat mode |
<ble\|wifi> |
Mode de scan (BLE ou WiFi) |
mlat start |
<mac> |
Démarre le scan d'une cible |
mlat stop |
- | Arrête le scan |
mlat status |
- | Statut du scanner |
Exemples MLAT :
# Configurer un scanner en GPS
c2:> send scanner1 mlat config gps 48.8566 2.3522
# Configurer en coordonnées locales (mètres)
c2:> send scanner2 mlat config local 0 5
# Démarrer le scan BLE
c2:> send scanner1 mlat mode ble
c2:> send scanner1 mlat start AA:BB:CC:DD:EE:FF
Dashboard Web¶
Accès¶
Après web start, accédez à :
Identifiants par défaut : admin / admin
Pages¶
| Page | Description |
|---|---|
/dashboard |
Liste des devices connectés |
/cameras |
Flux caméras en direct + enregistrement |
/mlat |
Visualisation multilatération |
/ota |
Gestion des mises à jour firmware OTA |
/build |
Build firmware depuis le navigateur |
Enregistrement Caméra¶
Sur la page /cameras :
- Cliquez sur le bouton record (cercle rouge)
- Le timer s'affiche pendant l'enregistrement
- Re-cliquez pour arrêter
- Les fichiers sont dans
static/recordings/
API REST¶
Authentification par session (login) ou Bearer token :
Endpoints¶
| Méthode | Endpoint | Description |
|---|---|---|
| GET | /api/devices |
Liste des devices |
| GET | /api/cameras |
Liste des caméras |
| GET | /api/stats |
Statistiques serveur |
| POST | /api/recording/start/<id> |
Démarrer enregistrement |
| POST | /api/recording/stop/<id> |
Arrêter enregistrement |
| GET | /api/recordings |
Liste des enregistrements |
| POST | /api/mlat/collect |
Recevoir données MLAT |
| GET | /api/mlat/state |
État MLAT (scanners + cible) |
| POST | /api/mlat/config |
Configurer MLAT |
| POST | /api/mlat/clear |
Reset MLAT |
| GET | /api/can/frames |
Frames CAN (device_id, can_id, limit, offset) |
| GET | /api/can/stats |
Statistiques CAN |
| GET | /api/can/frames/export |
Export CSV des frames CAN |
| POST | /api/ota/update |
Déclencher mise à jour OTA |
| POST | /api/build/start |
Lancer un build firmware |
| GET | /api/build/status |
Status du build en cours |
| GET | /api/build/log |
Log du build (offset) |
| GET | /api/build/defaults |
Defaults depuis deploy.json |
| POST | /api/commands/send |
Envoyer commande à un device |
| GET | /api/commands/history |
Historique des commandes |
MLAT (Multilatération)¶
Principe¶
La multilatération utilise les mesures RSSI de plusieurs scanners pour localiser une cible (device BLE ou WiFi).
graph TB
subgraph "Scanners ESP32"
S1[Scanner 1<br/>Position connue]
S2[Scanner 2<br/>Position connue]
S3[Scanner 3<br/>Position connue]
end
TARGET((Cible<br/>Position ?))
S1 -.->|RSSI -45| TARGET
S2 -.->|RSSI -52| TARGET
S3 -.->|RSSI -48| TARGET
subgraph "C2 Server"
MLAT[MLAT Engine<br/>scipy.optimize]
end
S1 -->|MLAT:G;lat;lon;rssi| MLAT
S2 -->|MLAT:G;lat;lon;rssi| MLAT
S3 -->|MLAT:G;lat;lon;rssi| MLAT
MLAT -->|Position calculée| WEB[Dashboard]
Configuration¶
- Placer 3+ scanners avec positions connues
- Configurer chaque scanner :
- Démarrer le scan :
- Visualiser sur
/mlat
Calibration¶
Ajustez les paramètres via l'API :
curl -X POST http://localhost:8000/api/mlat/config \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"rssi_at_1m": -40, "path_loss_n": 2.5}'
| Paramètre | Défaut | Description |
|---|---|---|
rssi_at_1m |
-40 | RSSI à 1 mètre (calibration) |
path_loss_n |
2.5 | Exposant path loss (2.0 = espace libre, 3.5 = indoor) |
smoothing_window |
5 | Fenêtre de lissage RSSI |
Architecture¶
tools/C3PO/
├── c3po.py # Point d'entrée (CLI / TUI)
├── requirements.txt # Dépendances Python
├── .env.example # Template configuration
│
├── core/ # Coeur du système
│ ├── crypto.py # ChaCha20 encryption
│ ├── device.py # Classe Device
│ ├── registry.py # DeviceRegistry
│ ├── groups.py # GroupRegistry
│ ├── transport.py # TCP handler + CAN/HP prefix parsing
│ ├── session.py # Central runtime state
│ └── can_store.py # CAN frame ring buffer storage
│
├── commands/ # Command system
│ └── registry.py # CommandRegistry
│
├── tui/ # Interface Textual
│ ├── app.py # Application TUI
│ ├── commander.py # Command dispatcher (can, groups, etc.)
│ ├── help.py # Help system
│ ├── styles/ # CSS Textual
│ └── widgets/ # Composants UI
│
├── web/ # Dashboard Flask
│ ├── server.py # UnifiedWebServer
│ ├── mlat.py # MlatEngine
│ ├── auth.py # Decorators auth
│ ├── build_manager.py # Background firmware builder
│ └── routes/ # Blueprints API
│ ├── pages.py # HTML pages
│ ├── api_devices.py
│ ├── api_cameras.py
│ ├── api_mlat.py
│ ├── api_stats.py
│ ├── api_ota.py
│ ├── api_build.py
│ ├── api_commands.py
│ ├── api_monitor.py
│ └── api_can.py # CAN frame API
│
├── streams/ # Réception caméra
│ ├── config.py # Configuration .env
│ └── udp_receiver.py # UDP + Recording
│
├── templates/ # HTML Jinja2
├── static/ # CSS/JS/images
│ ├── streams/ # Frames JPEG (runtime)
│ └── recordings/ # Vidéos AVI (runtime)
│
├── utils/ # Utilitaires
│ └── display.py # Formatage console
│
└── proto/ # Protocol Buffers
└── c2_pb2.py # Messages générés
Dépannage¶
L'agent ne se connecte pas
Vérifications :
- Le serveur C2 tourne ? (
python c3po.py) - Port 2626 ouvert dans le firewall ?
- IP du serveur correcte dans le firmware ?
- Clés ChaCha20 identiques ?
Erreur de déchiffrement
Cause : Clés différentes entre C2 et ESP32
Solution : Vérifier que CRYPTO_KEY et CRYPTO_NONCE sont identiques dans :
tools/c2/core/crypto.pyidf.py menuconfig→ Security
Pas de flux caméra
Vérifications :
camera startlancé sur le C2 ?cam_start <ip> <port>envoyé à l'ESP32-CAM ?- Token identique ? (
CAMERA_SECRET_TOKENetCAMERA_UDP_TOKEN) - Port UDP 5000 accessible ?
MLAT ne calcule pas de position
Vérifications :
- Au moins 3 scanners actifs ?
- Chaque scanner configuré avec sa position ?
- Les scanners envoient des données RSSI ?
Sécurité¶
Production
- Changez toutes les clés par défaut
- Utilisez un VPN pour l'accès distant
- Limitez l'accès au port 2626 (firewall)
- Changez
WEB_USERNAME/WEB_PASSWORD - Changez
FLASK_SECRET_KEY - Changez
MULTILAT_AUTH_TOKEN