Skip to content

#30 — kea-dhcp

PLANIFIÉ

Priorité: 🔴 CRITIQUE · Type: TYPE F · Conteneur: rgz-kea · Code: config/kea/kea-dhcp4.conf

Dépendances: #7 rgz-gateway


Description

Kea DHCP est le serveur DHCP de la plateforme ACCESS, basé sur ISC Kea (successeur de ISC DHCP). Il attribue les adresses IP aux CPE et aux appareils abonnés dans chaque sous-réseau VLAN. Sans Kea, aucun abonné ne peut obtenir d'adresse IP et accéder au réseau — c'est pourquoi cet outil est classifié CRITIQUE.

Kea est choisi pour sa gestion native des bases de données PostgreSQL (stockage des baux dans rgz-db), son support de l'Option 82 (relay agent information — essentielle pour transmettre le NAS-ID au serveur RADIUS), et sa configuration dynamique via API REST sans redémarrage du service. Par opposition à l'ISC DHCP classique, Kea supporte le rechargement à chaud de la configuration, ce qui est indispensable lors de l'onboarding de nouveaux revendeurs (#56) qui crée de nouveaux pools VLAN.

Le plan d'adressage est strict : chaque VLAN reçoit un sous-réseau /24 dans 10.[vlan_id].0.0/24. La passerelle est toujours .1, les AP sont .2, .3… selon le nombre de sites, et le pool DHCP démarre à .10 pour laisser de la marge aux équipements statiques. La durée de bail est fixée à 3600 secondes (1 heure) — un compromis entre performance (peu de renouvellements) et récupération rapide des IP en cas de déconnexion.

Architecture Interne

Paquet DHCP Discover (broadcast depuis abonné)


CPE LiteBeam (relay agent DHCP)
        │ → Ajoute Option 82 : NAS-Identifier = nas_id du revendeur


rgz-kea :: port 67/udp

        ├── Lecture Option 82 → identification VLAN → sélection subnet correspondant

        ├── Vérification baux existants en PostgreSQL (rgz-db)
        │   Table : kea_leases4 (ip_address, hwaddr, valid_lft, subnet_id)

        ├── Attribution IP : 10.[vlan_id].0.10 → 10.[vlan_id].0.254 (premier disponible)

        ├── Enregistrement bail en DB (durée 3600s)

        └── DHCP Offer → DHCP Ack
                Options envoyées :
                  Option 1  : Masque = 255.255.255.0
                  Option 3  : Gateway = 10.[vlan_id].0.1
                  Option 6  : DNS = 10.[vlan_id].0.1 → vers rgz-dns (sinkhole avant auth)
                  Option 51 : Lease time = 3600s
                  Option 82 : Relay info (retransmise au client)

Configuration

Variables d'environnement

VariableValeur exempleDescription
KEA_DB_HOSTrgz-dbHostname PostgreSQL pour baux DHCP
KEA_DB_PORT5432Port PostgreSQL
KEA_DB_NAMEkeaBase de données Kea (séparée de rgzdb)
KEA_DB_USERkeaUtilisateur PostgreSQL Kea (rôle limité)
KEA_DB_PASS(depuis .env)Mot de passe PostgreSQL Kea
KEA_CTRL_PORT8001Port API REST Kea Control Agent
DHCP_LEASE_TIME3600Durée bail DHCP (secondes)
VLAN_BASE100Premier VLAN (100+n)
SUBNET_BASE_OCTET10Premier octet subnets abonnés

kea-dhcp4.conf (extrait représentatif)

json
{
    "Dhcp4": {
        "interfaces-config": {
            "interfaces": ["eth0"]
        },
        "lease-database": {
            "type": "postgresql",
            "host": "rgz-db",
            "name": "kea",
            "user": "kea",
            "password": "$(KEA_DB_PASS)"
        },
        "valid-lifetime": 3600,
        "renew-timer": 1800,
        "rebind-timer": 2700,
        "option-def": [
            {
                "name": "agent-circuit-id",
                "code": 82,
                "space": "dhcp4",
                "type": "binary"
            }
        ],
        "subnet4": [
            {
                "id": 100,
                "subnet": "10.100.0.0/24",
                "pools": [{"pool": "10.100.0.10 - 10.100.0.254"}],
                "option-data": [
                    {"name": "routers", "data": "10.100.0.1"},
                    {"name": "domain-name-servers", "data": "10.100.0.1"}
                ],
                "relay": {"ip-addresses": ["10.100.0.1"]},
                "user-context": {"nas-id": "access_revendeur1", "vlan-id": 100}
            }
        ],
        "control-socket": {
            "socket-type": "unix",
            "socket-name": "/tmp/kea4-ctrl-socket"
        },
        "loggers": [{"name": "kea-dhcp4", "severity": "INFO"}]
    }
}

Ajout dynamique d'un subnet (onboarding revendeur)

Kea permet le rechargement à chaud via API REST (kea-ctrl-agent) sans redémarrer le conteneur :

bash
# Ajouter un nouveau subnet pour VLAN 142 (revendeur Kossou, onboarding)
curl -X POST http://rgz-kea:8001/ \
  -H "Content-Type: application/json" \
  -d '{
    "command": "subnet4-add",
    "service": ["dhcp4"],
    "arguments": {
      "subnet4": [{
        "id": 142,
        "subnet": "10.142.0.0/24",
        "pools": [{"pool": "10.142.0.10 - 10.142.0.254"}],
        "option-data": [
          {"name": "routers", "data": "10.142.0.1"},
          {"name": "domain-name-servers", "data": "10.142.0.1"}
        ]
      }]
    }
  }'

Commandes Utiles

bash
# Vérifier l'état du service Kea
docker exec rgz-kea kea-ctrl-agent --version
docker ps | grep kea

# Lister les baux DHCP actifs
docker exec rgz-db psql -U kea -d kea -c \
  "SELECT address, hwaddr, valid_lft, subnet_id FROM lease4 WHERE valid_lft > 0 LIMIT 20;"

# Lister les subnets configurés (via API Kea)
curl -s http://localhost:8001/ -d '{"command": "subnet4-list", "service": ["dhcp4"]}' \
  | python3 -m json.tool

# Statistiques DHCP par subnet (Kea API)
curl -s http://localhost:8001/ -d '{"command": "statistic-get-all", "service": ["dhcp4"]}' \
  | python3 -m json.tool | grep "assigned"

# Forcer rechargement configuration Kea (sans restart)
docker exec rgz-kea kea-ctrl-agent -c /etc/kea/kea-ctrl-agent.conf &
curl -s http://localhost:8001/ -d '{"command": "config-reload", "service": ["dhcp4"]}'

# Logs Kea
docker logs rgz-kea --tail=50

# Vérifier le healthcheck Kea
docker inspect rgz-kea | python3 -c "import sys,json; d=json.load(sys.stdin); \
  print(d[0]['State']['Health']['Status'])"

# Compter les baux actifs par VLAN (subnet_id = vlan_id)
docker exec rgz-db psql -U kea -d kea -c \
  "SELECT subnet_id, count(*) FROM lease4 WHERE valid_lft > 0 GROUP BY subnet_id ORDER BY subnet_id;"

Sécurité

RègleApplication
SEC-08rgz-db : rôle PostgreSQL kea avec accès limité à la base kea uniquement (pas de rgzdb)
LL#33restart: unless-stopped dans docker-compose.core.yml pour rgz-kea
LL#27Logs Docker rgz-kea : max-size: 10m, max-file: 3
SEC-07Kea Control Agent accessible uniquement sur le réseau Docker interne rgz-net (jamais exposé publiquement)

Healthcheck Docker

yaml
# docker-compose.core.yml
healthcheck:
  test: ["CMD", "curl", "-sf", "http://127.0.0.1:8001/"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 20s

Implémentation TODO

  • [ ] Ajouter service rgz-kea dans docker-compose.core.yml (image docker.io/isc/kea-dhcp4)
  • [ ] Créer config/kea/kea-dhcp4.conf avec subnet template générique (VLAN 100-499)
  • [ ] Créer config/kea/kea-ctrl-agent.conf (API REST port 8001)
  • [ ] Créer base de données kea dans rgz-db avec rôle kea (rôle limité — SEC-08)
  • [ ] Configurer relay agent DHCP Option 82 sur les CPE LiteBeam pour transmettre le NAS-ID
  • [ ] Tester ajout dynamique de subnet via API Kea (pour intégration onboarding #56)
  • [ ] Vérifier que domain-name-servers pointe vers rgz-dns (sinkhole avant auth RADIUS)
  • [ ] Configurer kea-dhcp4 avec stockage PostgreSQL (pas fichier CSV)
  • [ ] Valider que le bail time 3600s convient aux sessions WiFi horaires/journalières
  • [ ] Documenter la procédure de suppression de subnet en cas d'offboarding revendeur

Dernière mise à à jour: 2026-02-21

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