Skip to content

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)
   → Internet

Ré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) → Internet

Couches de sécurité VLAN :

CoucheÉquipementRôle
L2Cisco SwitchVLAN tagging 802.1Q, isolation ports
L3FortiGateACL deny inter-VLAN, NAT, RADIUS NAS
Dockerrgz-gatewayQoS HTB/fq_codel, DSCP marking
Apprgz-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étriqueTargetNotes
API response time<200ms p95Sans DB query
DB query time<50ms p95Indexes optimisés
Redis hit rate>95%Session cache
RADIUS auth time<100msFreeRADIUS optimisé
DNS lookup<10msUnbound 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

  1. Docker Network — Réseaux détaillés
  2. Ports Reference — Tableau tous ports
  3. Dataflow — Flux 12 données
  4. Dependencies — Graph 81 outils

PROJET MOSAÏQUE — 81 outils, 22 conteneurs, 500+ revendeurs WiFi Zone