Vue d'ensemble Architecture
Architecture complète du NOC RGZ — 22 conteneurs, réseaux, sécurité.
Documentation par Rôle
Sélectionnez votre profil: Guides par Rôle · Parcours Utilisateurs · Interfaces
Diagramme architecture (Mermaid)
Équipements réseau physiques
FortiGate Firewall
Rôle: Gateway de sécurité physique entre les CPE terrain et la stack Docker.
- VLAN Gateway: Termine les VLANs 100-499 (un par revendeur) depuis les switches Cisco
- NAT: Traduit les adresses privées des abonnés (10.x.0.x) vers Internet
- ACL: Règles deny-all par défaut, ouvertures explicites par VLAN
- RADIUS NAS: Envoie les Access-Request vers rgz-radius (1812/udp) avec NAS-Identifier =
access_[slug] - VPN IPSec: Tunnels inter-sites (sites revendeurs distants)
- SNMP v3: Métriques collectées par Prometheus (CPU, sessions, throughput)
- Syslog: Logs firewall → Logstash → Elasticsearch
- NetFlow v5: Flux réseau envoyés vers rgz-netflow (2055/udp)
Intégration Dashboard: Le composant StepVlanCpe du pipeline onboarding (#56) contient un bouton "Synchroniser depuis FortiGate" (actuellement placeholder, intégration API FortiGate planifiée).
Cisco L2/L3 Switches
Rôle: Commutation L2 avec VLAN trunking 802.1Q entre les CPE et le FortiGate.
- Ports access: Un port par CPE, affecté au VLAN du revendeur (100-499)
- Ports trunk: Vers FortiGate — transportent tous les VLANs tagués
- PoE: Alimentation des CPE LiteBeam 5AC via le switch
- Spanning Tree: RSTP activé pour redondance
- SNMP v3: Métriques collectées (port status, errors, utilisation)
Cohabitation FortiGate / rgz-gateway (nftables)
CPE → Cisco Switch (L2 VLAN) → FortiGate (NAT/ACL/RADIUS NAS)
↓
Serveur Docker
↓
rgz-gateway (nftables: QoS HTB + isolation Docker)- FortiGate gère le réseau physique : VLAN, NAT, ACL, RADIUS NAS
- rgz-gateway gère le réseau Docker : QoS (HTB/fq_codel), DSCP, isolation containers
- Les deux coexistent — FortiGate en amont (couche physique), rgz-gateway en aval (couche Docker)
Composants principaux
Groupe 1: API & Frontend (4 services)
rgz-api (FastAPI Python)
- Hub central de la stack
- 59+ endpoints métier (paiement, billing, auth, onboarding)
- WebSocket pour live metrics
- Routes:
/api/v1/*,/webhooks/*,/health
rgz-web (React + Tailwind)
- Dashboard admin responsive
- 24 pages (dashboards #51-55, onboarding #56, etc.)
- Auth JWT + CORS
- Connected to rgz-api:8000
rgz-portal (HTML/JS/CSS <50KB)
- Portail captif abonnés WiFi
- Flow: MSISDN → OTP → Paiement → Session
- Branding dynamique (#18)
- SPA <50KB total (HTML+CSS+JS)
rgz-nginx
- Reverse proxy interne
- load balancer vers API workers
- Static files cache
Groupe 2: Infrastructure (3 services)
rgz-db (PostgreSQL 16 + TimescaleDB)
- Schéma: 20+ tables (subscribers, sessions, transactions)
- Hypertables pour métriques (SNMP, SLA)
- Replication: logical (standby via WAL)
- Backup: pg_dump daily 03:00 UTC
rgz-redis (Redis 7)
- Sessions abonnés (rgz:session:{id})
- Rate limiting (rgz:rate:{phone})
- OTP storage (rgz:otp:{phone}, TTL=300s)
- Cache config (rgz:portal:config:{nas_id}, TTL=3600s)
- DBA MIR (rgz:dba:mir:{reseller_id}, TTL=600s)
rgz-beat (Celery Beat)
- Scheduler tâches périodiques
- 15 tasks (SLA probe, SNMP poll, backup, reports)
- Broker: Redis 6379/0
- Result backend: Redis 6379/1
Groupe 3: Réseau (5 services)
rgz-gateway (Alpine + nftables)
- QoS HTB + fq_codel (#27-28) — traffic shaping côté Docker
- DSCP marking (#28) — classification MGMT/Inter/Bulk
- Isolation conteneurs Docker (deny-all interne)
- Cohabite avec FortiGate (FortiGate = couche physique, rgz-gateway = couche Docker)
- ⚠️ JAMAIS
nft flush ruleset(Docker chains break — LL#40)
rgz-dns (Unbound)
- DNS authoritative + recursive
- Blocklist ads/malware
- Sinkhole (#34): wildcard → portail 302 redirect
- Peut exposer port 53 ou rester interne
rgz-kea (Kea DHCP)
- Pools par VLAN 100-499
- Option 82 (Remote-ID = NAS-ID)
- Leases: 24h
- Config via API (#31)
rgz-radius (FreeRADIUS 3.2)
- Auth 1812/udp + Acct 1813/udp
- CoA 3799/udp (DBA recalcul MIR)
- REST module pour queries API
- Simultaneous-Use = 2 par défaut (multi-device #13)
- NAS client = FortiGate (Access-Request forwarded depuis FortiGate)
rgz-wireguard
- VPN inter-site (réseau private RGZ)
- Port 51820/udp
- Endpoint découverte dynamique
- Optional (Phase V2 Q3 2026)
Groupe 4: Sécurité (1 service)
rgz-ids (Suricata 7.x)
- IDS/IPS sur gateway
- Rules custom (fraude #17, DoS)
- EVE JSON logs → Elasticsearch
- Mode: IDS (tap) ou IPS (inline)
Groupe 5: Tests (1 service)
rgz-canary (Python Celery task)
- Sondes synthétiques 5min (#80)
- Tests: API health, RADIUS auth, DNS lookup
- Resultats → Prometheus metrics
- Alerts si > 2 failures consecutifs
Groupe 6: Monitoring (8 services)
rgz-prometheus
- Scrape metrics API
/metrics - Retention: 15 days
- Rules alertes (CPU>80%, API latency>500ms)
- Remote write: optional (Thanos)
rgz-grafana
- 15+ dashboards
- Datasources: Prometheus, Elasticsearch
- Alerting intégré
- Provisioning via config files (IaC)
rgz-alertmanager
- Routes alertes (P0/P1/P2)
- Grouping, inhibition, silence
- Channels: SMS (Letexto), email, webhook
rgz-elasticsearch
- Logs storage 12 mois
- Indices: logstash-api-, logstash-radius-, logstash-cpe-, logstash-netflow-
- ILM: 30d hot, 300d warm, delete after 365d
- Cluster: 1 node (HA en V2)
rgz-kibana
- Logs visualization
- Discover, dashboards, alerts
- Saved searches pour incidents
- Connected to Elasticsearch 9200
rgz-logstash
- 4 pipelines: API logs, RADIUS logs, CPE syslog, NetFlow
- Parsers: grok, json, mutate
- Output: Elasticsearch (bulk indexing)
rgz-netflow
- goflow2 (v5 NetFlow collector)
- Port 2055/udp
- Output: JSON → Elasticsearch
- Visualisation bandwidth trends
rgz-docs
- MkDocs Material 9.7.1
- Site documentation (ce site)
- Built from docs/ folder
- Auto-rebuild on file change
Flux de données complet
1. Abonné WiFi (smartphone/laptop)
↓ Connexion WiFi
→ CPE LiteBeam 5AC (access point revendeur)
↓ VLAN taggé (802.1Q)
→ Cisco Switch (port access → trunk)
↓ Trunk VLAN 100-499
→ FortiGate (terminaison VLAN, NAT, ACL)
↓ DHCP relay
→ rgz-kea (DHCP 67/udp) → lease 10.(100+n).0.x
↓ HTTP request captif
→ rgz-dns (sinkhole) → 302 → https://access-rgz.duckdns.org
↓ Portal load
→ rgz-portal (proxy /api/ → rgz-api:8000)
↓ MSISDN + OTP
→ rgz-api (/api/v1/otp/request)
→ rgz-redis (store OTP) + Letexto (SMS)
↓ OTP verify
→ rgz-api (/api/v1/otp/verify)
↓ RADIUS auth
→ FortiGate (NAS) → rgz-radius (Access-Request, NAS-ID=access_[slug])
→ rgz-db (create session)
→ rgz-redis (session cache)
↓ RADIUS Access-Accept + Simultaneous-Use
→ FortiGate → CPE (grant 2 devices max)
↓ Data flow
→ FortiGate (NAT, ACL) → rgz-gateway (QoS HTB)
→ rgz-ids (threat detection)
→ InternetRéseaux Docker
rgz_rgz-net (172.23.0.0/16):
├─ rgz-api:172.23.0.10
├─ rgz-db:172.23.0.11
├─ rgz-redis:172.23.0.12
├─ rgz-radius:172.23.0.13
├─ rgz-gateway:172.23.0.14 (+ host network mode)
├─ rgz-dns:172.23.0.15
├─ rgz-beat:172.23.0.16
├─ rgz-portal:172.23.0.17
├─ rgz-web:172.23.0.18
├─ rgz-kea:172.23.0.19
├─ rgz-ids:172.23.0.20
├─ rgz-nginx:172.23.0.21
├─ rgz-wireguard:172.23.0.22
├─ rgz-canary:172.23.0.23
├─ rgz-prometheus:172.23.0.30
├─ rgz-grafana:172.23.0.31
├─ rgz-alertmanager:172.23.0.32
├─ rgz-elasticsearch:172.23.0.33
├─ rgz-kibana:172.23.0.34
├─ rgz-logstash:172.23.0.35
├─ rgz-netflow:172.23.0.36
└─ rgz-docs:172.23.0.37
traefik-public (10.0.9.0/24):
├─ traefik:10.0.9.2
├─ rgz-api:10.0.9.10 (exposed)
├─ rgz-web:10.0.9.18 (exposed)
├─ rgz-portal:10.0.9.17 (exposed)
├─ rgz-grafana:10.0.9.31 (exposed)
└─ rgz-docs:10.0.9.37 (exposed)Isolation VLAN CPE
CPE LiteBeam 5AC (WiFi Zone Revendeur)
↓ Trafic WiFi abonnés
→ Cisco Switch (port access VLAN n, 802.1Q)
↓ Trunk VLAN tagué
→ FortiGate (terminaison VLAN, interface VLAN n)
↓ ACL FortiGate
→ Deny inter-VLAN (isolation revendeurs)
→ Allow VLAN n → Internet (NAT)
→ Allow VLAN n → rgz-radius (1812/udp)
↓ DHCP relay via FortiGate
→ rgz-kea identifie VLAN n (Option 82 + NAS-ID)
↓ IP allocation
→ 10.(100+n).0.x/24 (n ∈ [0, 399])
↓ Gateway
→ FortiGate interface VLAN n = 10.(100+n).0.1
↓ Trafic Internet
→ FortiGate NAT → rgz-gateway (QoS HTB) → InternetCouches de sécurité VLAN :
| Couche | Équipement | Rôle |
|---|---|---|
| L2 | Cisco Switch | VLAN tagging 802.1Q, isolation ports |
| L3 | FortiGate | ACL deny inter-VLAN, NAT, RADIUS NAS |
| Docker | rgz-gateway | QoS HTB/fq_codel, DSCP marking |
| App | rgz-ids (Suricata) | IDS/IPS, détection anomalies |
Sécurité par défaut
✅ Network segmentation: rgz_rgz-net isolé de l'hôte
✅ Deny-all firewall: nftables règles explicites (LL#40)
✅ TLS 1.3: Traefik → Let's Encrypt auto-renew
✅ Auth JWT RS256: 15min expiry, 7j refresh, jti blacklist Redis
✅ CORS: whitelist API → admin-rgz.duckdns.org
✅ Secrets management: .env vars, jamais en code
✅ Rate limiting: nginx limit_req (auth=5/min, otp=3/min)
✅ Logs immutables: SHA-256 hash append-only (#45)
Performance metrics
| Métrique | Target | Notes |
|---|---|---|
| API response time | <200ms p95 | Sans DB query |
| DB query time | <50ms p95 | Indexes optimisés |
| Redis hit rate | >95% | Session cache |
| RADIUS auth time | <100ms | FreeRADIUS optimisé |
| DNS lookup | <10ms | Unbound cache |
| Portal load time | <2s | <50KB assets |
| CPU usage | <60% | 4 cores, 4 workers |
| RAM usage | <80% | 8GB min, 16GB rec |
| Disk I/O | <70% | SSD required |
Haute disponibilité (V2 Q2 2026)
Roadmap:
- [ ] PostgreSQL streaming replication
- [ ] Redis sentinel (3 nodes)
- [ ] API horizontal scaling (load balancer)
- [ ] Elasticsearch cluster (3 nodes)
- [ ] Prometheus remote storage (Thanos)
- [ ] Traefik HA (2 nodes)
Étapes suivantes
- Docker Network — Réseaux détaillés
- Ports Reference — Tableau tous ports
- Dataflow — Flux 12 données
- Dependencies — Graph 81 outils