Furor Teutonicus blog | over | volg | teuto | lyme | archief | doneer | todo
🕰️
  ⬩  
✍️ Evert Mouw
  ⬩  
⏱️ 5 min

DHCP failover with config sync on a Raspberry Pi

raspberry pi logo

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.

DHCP DORA process from Wikipedia (author Endaargaanweweer)

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.