DHCP failover with config sync on a Raspberry Pi

This evening I decided to use my Raspberry Pi as a secondary DHCP server for my home network. If you donât know what DHCP is, then probably this article is not for youâŚ
I have installed Raspbian on the little device. It is powered by a wall USB charger, and it doesnât take much power. As such, it is ideal for small network tasks such as DNS, DHCP, and maybe some monitoring. My main server provides a DHCP service to my other computers. In case of a server failure, I want another DHCP server to take over.
I currently do not use dynamic DNS for my small home network. I use a lot of static mappings. For a small network, it is nice when the machines always have the same IP address. I maybe should use dynamic DNS so I donât have to maintain a local DNS as well, but the effort is minimal because of the small number of computers. If your DHCP settings donât change that much, then maybe you donât need to synchronize the settings as I do.

The great thing about the ISC DHCP daemon is that it supports failover and the synchronization of lease states between DHCP servers. The less great thing is that it does not synchronize the configurations (settings). Also, it does not follow a multi-master model but a master-slave model (with a primary and a secondary node), so simply copying the configuration files or storing then on some NFS share wonât do. Besides, storing the config files for both redundant DHCP servers on one storage location defeats the whole idea of redundancy.
So I decided to split the dhcpd.conf file in two parts: a specific part for the primary or the secondary, and a generic part for both of them. Furthermore, I decided to use the primary node as the machine where the generic part of the configuration should be edited. The secondary node should sync with that. I use the rsync daemon on the primary node to offer access to the dhcpd.conf settings. The secondary will periodically sync with the primary.
Needless to say, it makes good sense to configure all DHCP servers with a static IP address. Also make sure both servers use NTP; timesync is important for correct failover functionality.
And if you plan to implement this for complex and big environments, then be warned: the current failover method might be just too complex.
This guide assumes a Debian or Ubuntu environment. See the comments at the end of the document for a RHEL / SL environment.
Configuration on the Primary Node
Of course you have already installed and activated the DHCP server on your primary machine, havenât you? If you did not, then this is not a guide that will help you with that. You should be able to figure that out on your own if you want to take it a step further with DHCP failover.
This is my dhcpd.conf on my primary node:
failover peer "evert.net" {
   primary;
   address 10.0.0.1;
   port 647;
   peer address 10.0.0.2;
   peer port 647;
   max-response-delay 20;
   max-unacked-updates 10;
   mclt 600; # only on the primary; do comment out on secondary
   split 128; # only on the primary; do comment out on secondary
   load balance max seconds 3;
}
include "/etc/dhcp/dhcpd.evert.net";
In this example, 10.0.0.1 is the IP address of the primary node, and 10.0.0.2 is the secondary node.
Note the use of the include statement. I just include the generic settings. Here is an abbreviated version of my dhcpd.evert.net:
default-lease-time 43200;
max-lease-time 86400;
option subnet-mask 255.0.0.0;
option broadcast-address 10.255.255.255;
option routers 10.0.0.1;
subnet 10.0.0.0 netmask 255.0.0.0 {
   pool { # needs a pool for the failover stuff
      failover peer "evert.net";
      range 10.0.0.100 10.0.0.200;
   }
}
Still on the primary machine, we need to configure the rsync daemon. Of course you need to edit /etc/default/rsync to set RSYNC_ENABLE=true, or inetd if you prefer, and then (re)start the rsync daemon. Furthermore, we need to add to /etc/rsync.conf:
max connections = 4
log file = /var/log/rsync.log
timeout = 300
[dhcpd]
   comment = DHCP daemon config
   path = /etc/dhcp
   read only = yes
   list = yes
   uid = root
   gid = root
   auth users = rsyncuser
   secrets file = /etc/rsyncd.secrets
If you use servers open to the internet, then you might want to limit the rsync port on your firewall, or to use other uid/gid values. Anyway, letâs continue with the /etc/rsyncd.secrets file:
rsyncuser:mypasswordhere
Restart your DHCP daemon and check /var/log/syslog for possible error messages.
Configuration on the Secondary Node
Raspbian needs to have the DHCP daemon installed. Then, edit the /etc/dhcpd.conf file:
failover peer "evert.net" {
   secondary;
   address 10.0.0.2;
   port 647;
   peer address 10.0.0.1;
   peer port 647;
   max-response-delay 20;
   max-unacked-updates 10;
   #mclt 600; # only on the primary; do comment out on secondary
   #split 128; # only on the primary; do comment out on secondary
   load balance max seconds 3;
}
include "/etc/dhcp/dhcpd.evert.net";
It is nearly identical to the file on the primary. I have marked the parts that are different (red, bold).
Now we need to get the dhcpd.evert.net generic file that is to be included. This is a good time to test the rsync functionality. Create a file called get_dhcp_config_from_primary.sh
#!/bin/sh
# Gets the DHCPD config from the primary DHCPD server,
# who makes this available using rsync (read-only).
# Place this script in e.g. /etc/dhcp
# Link to this script in e.g. /etc/cron.hourly
export RSYNC_PASSWORD=mypasswordhere
rsync rsync://rsyncuser@10.0.0.1/dhcpd/dhcpd.evert.net /etc/dhcp/
/usr/sbin/service isc-dhcp-server restart > /dev/null 2>&1
After a chmod +x, try out this script. The file /etc/dhcp/dhcpd.evert.net should now be present on the secondary. If not, then you have some troubleshooting to do. If it works, you should add it to a cron job so that this script is executed periodically. I decided that an hourly execution would be good enough for my use-case:
ln -s /etc/dhcp/get_dhcp_config_from_primary.sh /etc/cron.hourlygetdhcpconfig
Restart the DHCP daemon and check /var/log/syslog for errors and (hopefully) nice messages about the failover functionality. Also check /var/lib/dhcp/dhcpd.leases for the current leases and failover state.
Good luck!
RHEL comments
If you run Fedora, Red Hat Enterprise Linux or a âcloneâ (Scientific Linux, CentOS), then maybe these notes can help you.
To set up an rsync server, see the article Rsync server on RedHat/Cent OS Linux. Also, set SElinux right:
setsebool -P rsync_export_all_ro 1
2014-03-25 added RHEL comments and service restart
Deze blogpost werd in december 2022 overgezet van WordPress naar een methode gebaseerd op Markdown; het is mogelijk dat hierbij fouten of wijzigingen zijn ontstaan t.o.v. de originele blogpost.