Configuration d'une redondance DHCP

Ce billet est basé sur l'excellent billet de Paul Heinlein et publié avec son aimable autorisation. Le billet original se trouve ici.

Je suis dans la situation suivante : j'ai une machine exécutant entre autres un serveur DHCP et un serveur DNS, et je souhaite réinstaller cette machine. Problème, si je la réinstalle, le DHCP et le DNS seront indisponibles. Il me faut donc redonder ces deux services pour ne pas perturber les autres machines. Ce billet ne porte cependant que sur DHCP.

Commençons par jeter un oeil à la configuration actuelle du serveur DHCP, elle ressemble un peu à ceci :

ddns-domainname "anotherhomepage.loc";
ddns-update-style none;
ddns-updates off;
ignore client-updates;
authoritative;
allow unknown-clients;
max-lease-time 3600;
default-lease-time 1800;
subnet 10.13.37.0 netmask 255.255.255.0 {
        pool {
        deny dynamic bootp clients;
        range 10.13.37.200 10.13.37.249;
        option domain-name-servers 10.13.37.5;
        option domain-name "anotherhomepage.loc";
        option routers 10.13.37.254;
        option broadcast-address 10.13.37.255;
group {
use-host-decl-names true ;

# Virtual Machine de tests PXE
host pxemachine {
        hardware ethernet 08:00:27:d3:8f:2d;
        fixed-address 10.13.37.199;
        option host-name "pxemachine";
}
}
}
}

On y trouve un pool, un groupe et une machine dans ce groupe avec une adresse IP fixée grâce à son adresse MAC : n'importe quelle machine se verra attribuer une adresse entre 10.13.37.200 et 10.13.37.249, mais la machine dont l'adresse MAC est 08:00:27:d3:8f:2d se verra attribuer l'IP 10.13.37.199.

Que se passe-t-il si je stoppe le serveur DHCP ? Les clients n'ont plus d'IP, donc plus d'accès au réseau, ce qui peut s'avérer gênant. Recopions la configuration sur l'autre serveur puis modifions celle-ci, qui va maintenant ressembler à ça :

ddns-domainname "anotherhomepage.loc";
ddns-update-style none;
ddns-updates off;
ignore client-updates;
authoritative;
allow unknown-clients;
max-lease-time 3600;
default-lease-time 1800;
failover peer "dhcp-failover" {
        primary; # declare this to be the primary server
        address 10.13.37.5;
        port 647;
        peer address 10.13.37.60;
        peer port 647;
        max-response-delay 30; 
        max-unacked-updates 10; 
        load balance max seconds 3;
        mclt 1800;
        split 128;
}
subnet 10.13.37.0 netmask 255.255.255.0 {
        pool {
        failover peer "dhcp-failover";
        deny dynamic bootp clients;
        range 10.13.37.200 10.13.37.249;
        option domain-name-servers 10.13.37.5;
        option domain-name "anotherhomepage.loc";
        option routers 10.13.37.254;
        option broadcast-address 10.13.37.255;
group {
use-host-decl-names true ;

# Virtual Machine de tests PXE
host pxemachine {
        hardware ethernet 08:00:27:d3:8f:2d;
        fixed-address 10.13.37.199;
        option host-name "pxemachine";
}
}
}
}

Maintenant notre machine est serveur primaire DHCP et communique avec le serveur désigné après peer address. Allons d'ailleurs voir la nouvelle configuration du serveur secondaire :

ddns-domainname "anotherhomepage.loc";
ddns-update-style none;
ddns-updates off;
ignore client-updates;
authoritative;
allow unknown-clients;
max-lease-time 3600;
default-lease-time 1800;
failover peer "dhcp-failover" {
        secondary; # declare this to be the secondary server
        address 10.13.37.60;
        port 647;
        peer address 10.13.37.5;
        peer port 647;
        max-response-delay 30; 
        max-unacked-updates 10; 
        load balance max seconds 3;
        mclt 1800;
        split 128;
}
subnet 10.13.37.0 netmask 255.255.255.0 {
        pool {
        failover peer "dhcp-failover";
        deny dynamic bootp clients;
        range 10.13.37.200 10.13.37.249;
        option domain-name-servers 10.13.37.5;
        option domain-name "anotherhomepage.loc";
        option routers 10.13.37.254;
        option broadcast-address 10.13.37.255;
group {
use-host-decl-names true ;

# Virtual Machine de tests PXE
host pxemachine {
        hardware ethernet 08:00:27:d3:8f:2d;
        fixed-address 10.13.37.199;
        option host-name "pxemachine";
}
}
}
}

A noter que si vous utilisez un pare-feu sur vos machines, il faudra autoriser les ports 647/tcp et 647/udp qui permettent la communication entre les deux serveurs.

Que se passe-t-il au démarrage et arrêt des serveurs ?

Exemple dans les logs du serveur primaire, après ajout de la configuration, le serveur dhcp primaire est nommé master-dhcp et le secondaire slave-dhcp :

Apr 20 22:28:30 master-dhcp dhcpd: Wrote 0 deleted host decls to leases file.
Apr 20 22:28:30 master-dhcp dhcpd: Wrote 0 new dynamic host decls to leases file.
Apr 20 22:28:30 master-dhcp dhcpd: Wrote 53 leases to leases file.
Apr 20 22:28:31 master-dhcp dhcpd: failover peer dhcp-failover: I move from communications-interrupted to startup
Apr 20 22:28:45 master-dhcp dhcpd: failover peer dhcp-failover: I move from startup to communications-interrupted

Démarrons maintenant DHCPD sur le serveur secondaire, et voyons le résultat sur le serveur primaire :

Apr 20 22:30:29 master-dhcp dhcpd: failover peer dhcp-failover: peer moves from normal to normal
Apr 20 22:30:29 master-dhcp dhcpd: failover peer dhcp-failover: I move from communications-interrupted to normal
Apr 20 22:30:29 master-dhcp dhcpd: pool 80c3200 192.168.6/24 total 50  free 26  backup 24  lts -1

Et regardons les logs du serveur secondaire :

Apr 20 22:30:28 slave-dhcp dhcpd: Wrote 0 deleted host decls to leases file.
Apr 20 22:30:29 slave-dhcp dhcpd: Wrote 0 new dynamic host decls to leases file.
Apr 20 22:30:29 slave-dhcp dhcpd: Wrote 50 leases to leases file.
Apr 20 22:30:29 slave-dhcp dhcpd: failover peer dhcp-failover: I move from normal to startup
Apr 20 22:30:29 slave-dhcp dhcpd: failover peer dhcp-failover: peer moves from normal to communications-interrupted
Apr 20 22:30:29 slave-dhcp dhcpd: failover peer dhcp-failover: I move from startup to normal
Apr 20 22:30:29 slave-dhcp dhcpd: failover peer dhcp-failover: peer moves from communications-interrupted to normal
Apr 20 22:30:29 slave-dhcp dhcpd: pool 7f7ffd8a5150 192.168.6/24 total 50  free 26  backup 24  lts 1

Si je stoppe le serveur primaire, on le voit dans les logs du serveur secondaire :

Apr 20 22:32:08 slave-dhcp dhcpd: peer dhcp-failover: disconnected
Apr 20 22:32:08 slave-dhcp dhcpd: failover peer dhcp-failover: I move from normal to communications-interrupted

Et le redémarrage est aussi visible :

Apr 20 22:32:40 slave-dhcp dhcpd: failover peer dhcp-failover: peer moves from normal to normal
Apr 20 22:32:40 slave-dhcp dhcpd: failover peer dhcp-failover: I move from communications-interrupted to normal
Apr 20 22:32:40 slave-dhcp dhcpd: pool 7f7ffd8a5150 192.168.6/24 total 50  free 26  backup 24  lts 1

Pour finir, cette configuration n'est possible que si les deux serveurs DHCP ont la même version d'ISC DHCP. Heureusement (?), de NetBSD 4.0 jusqu'à NetBSD 5.1 inclus, ISC DHCP est toujours en version 3.0.3 ;-)