Bael#
Serveur DHCP intégré, en coexistence avec dnsmasq, et documentation du projet.
Fonctionnalités#
Serveur DHCP intégré
Nouveau binaire
dhcp, une instance par subnet lancée dans le netns du VPC par l’unitdhcp@<netns>_<bridge>. Il reçoit son bridge et ses deux chemins de fichiers en paramètres : il ne compose aucun chemin et ignore le netns dans lequel il tournePiloté par l’agent sur une socket Unix
/run/two/dhcp/<netns>_<bridge>.sock, en JSON par ligne. Ordres idempotents en remplacement intégral : configuration du subnet à sa création, une réservation par interface à chaque création ou suppression de VMRéservations statiques uniquement, pas de baux : une MAC inconnue n’obtient rien, et le serveur reste silencieux plutôt que de répondre par un refus. Aucun
DHCPNAKn’est émisÉtat auto-persisté dans
/run/two/dhcp/<netns>_<bridge>.state, en écriture atomique et lisible par le seulroot. Le fichier appartient au processus, qui le relit à son démarrage ; l’agent ne l’écrit jamais et se borne à le supprimer — à la création du subnet pour écarter un résidu, à sa suppression après avoir arrêté l’unitLa route par défaut est décidée par interface et non plus par subnet, ce qui permet de ne l’annoncer que sur une interface d’une VM multi-réseaux
L’encodage RFC 3442 de l’option 121 est délégué à
github.com/insomniacslk/dhcp
Coexistence avec dnsmasq
Nouvelle clé
dhcp.backend,dnsmasqoutwo, qui choisit le serveur des subnets créés par cet agent. Le défaut estdnsmasq: un fichier de configuration de la 0.1.0, non modifié, se comporte exactement comme avantLa bascule est une opération manuelle sur un hyperviseur vide — l’option ne migre rien, un subnet déjà créé reste servi par le serveur qui l’a été. La procédure est documentée
Toute valeur autre que
dnsmasqoutwofait échouer le démarrage de l’agent
Exploitation
Le watchdog interroge le serveur DHCP intégré et compare les réservations servies à celles que la base implique. Il nomme ce qui diverge — ordre perdu à la création, ordre perdu à la suppression, adresse ou route par défaut divergente — et reste en lecture seule
La socket de contrôle répond à
get-stateet àprobe, ce dernier montrant sans effet de bord ce qui serait envoyé à une MAC donnée : adresse, masque, routeur, DNS et routesDocumentation Sphinx du projet : concepts, architecture, déploiement et exploitation
Correctifs#
Un fichier de configuration présent mais invalide fait désormais échouer le démarrage. Jusqu’en 0.1.0 l’erreur de lecture était ignorée : l’agent tournait alors entièrement sur ses valeurs par défaut sans le dire, ce qui rendait indétectable une simple tabulation d’indentation
probeannonce explicitement"served": falsepour une MAC non réservée, au lieu d’omettre le champ et de le rendre indistinguable d’une réponse tronquée
Changements internes#
Le module passe à Go 1.25, exigé par la bibliothèque DHCP retenue. La version de Go du workflow de build, restée à 1.21 alors que le module en demandait davantage, est alignée
Nouveau paquet
pkg/db/statefile: persistance générique d’un état de composant dans un fichier, en écriture atomique. Badger a été écarté pour cet usage — une instance par subnet coûterait une memtable de 64 Mio et quatre goroutines de compaction pour environ un kilo-octet d’état, dans untmpfs, et laisserait un verrou résiduel après un arrêt brutalinternal/subnetetinternal/vmne parlent plus à dnsmasq en direct mais à une interfaceBackendà deux implémentations
Périmètre et limites connues#
Celles de la 0.1.0 restent valables, sauf mention contraire ci-dessus. S’y ajoutent :
dnsmasq n’est pas retiré et reste un paquet requis : le backend intégré ne sert que les subnets créés après la bascule, et le retour arrière suppose dnsmasq installé
Pas de DNS, pas de pool dynamique, pas de PXE, pas de DHCPv6 dans le serveur intégré
La comparaison faite par le watchdog porte sur les réservations et non sur la configuration du subnet : celle-ci dépend de la route par défaut de l’host, dont la lecture au moment du contrôle produirait de faux écarts. Un serveur dépourvu de configuration est en revanche signalé
L’option 249 (routes classless de Microsoft) n’est pas émise, comme dnsmasq ne l’émet pas
Le serveur intégré écoute UDP/67 sans authentification, comme tout serveur DHCP : l’isolation entre locataires d’un même subnet repose sur les règles ebtables anti-usurpation, inchangées
internal/dhcpbackendn’est testé sous Linux que pour ses appels systemd ; le reste, y compris le dialogue avec le serveur intégré, est couvert sur toute plateforme
Mise à jour depuis la 0.1.0#
curl -O https://git.g3e.fr/syonad/two/raw/branch/main/scripts/deploy.sh
bash ./deploy.sh -t 0.2.0
Aucune action n’est requise : sans dhcp.backend dans /etc/two/agent.yml, le comportement est
celui de la 0.1.0. Pour passer au serveur intégré, suivre la procédure de bascule dans la
documentation d’exploitation — elle suppose un hyperviseur vidé.