OpenBSD DHCP Server

OpenBSD makes a great router. It's simplicity and ease of configuration makes it perfect for network infrastructure applications. Everything you need to build a network of any size is built into the base system, plus its man pages and examples cover everything you'd need to know.

While I've been an OpenBSD user for years, I'm finally in the process of replacing the router provided by my ISP with a PC Engines APU2E4 running OpenBSD.

One of the key services that I have to setup for this is the DHCP server, which is responsible for giving out IP addresses to machines when they join the network.

This task is incredibly easy on OpenBSD, as it comes with dhcpd on the base system. The OpenBSD project provides excellent documentation for this system under dhcpd(8) for the DHCP server itself, dhcpd.conf(5) for the configuration file, and dhcpd.leases(5) for the lease database format.

The example we'll be going over in this post will be extremely simple, as it's only for a small home network without any advanced options. I encourage you to read the man pages if you're ever setting up your own, as I might not cover what you need to know here.

For my case, I'll be handing out IP addresses in the 192.168.0.0/24 subnet, with addresses 192.168.0.30 through 192.168.0.200 assigned with DHCP. The gateway router will be at the address 192.168.0.1.

I will assign the devices on the network the home.local domain. I'll use 192.168.0.23 as the DNS server, as I have a caching DNS server which filters out advertisers setup at that address, with 8.8.8.8 as the secondary DNS server in case my DNS server ever goes down.

I'll also set the default lease time to one week, and the maximum lease time to one month.

To jumpstart the configuration, I'll first copy the file from /etc/examples/dhcpd.conf to /etc/dhcpd.conf so I don't have to start from scratch.

doas cp /etc/examples/dhcpd.conf /etc/

Then I'll edit the file with mg, an emacs-like editor that comes with OpenBSD.

doas mg /etc/dhcpd.conf

Here's the finished configuration file.

# Network:          192.168.0.0/255.255.255.0
# Domain name:      home.local
# Name servers:     192.168.0.23 and 8.8.8.8
# Default router:   192.168.0.1
# Addresses:        192.168.0.30 - 192.168.0.200
#
option  domain-name "home.local";
option  domain-name-servers 192.168.0.23, 8.8.8.8;

subnet 192.168.0.0 netmask 255.255.255.0 {
    option routers 192.168.0.1;

    range 192.168.0.30 192.168.0.200;
    default-lease-time 604800;
    max-lease-time 2592000;

    host example-static-client {
            hardware ethernet 22:33:44:55:66:77;
            fixed-address 192.168.0.201;
    }
}

Let's go through this line-by-line to get a better understanding of what's going on here.

The comments at the top are just to help understand the file at a glance, and don't serve any practical function.

An option can be specified globally or per-subnet, and can also be specified per-client for BOOTP clients. Here I set the domain name and DNS servers globally.

option domain-name "home.local"
option domain-name-servers 192.168.0.23, 8.8.8.8;

Then I declare the configuration for my subnet.

subnet 192.168.0.0 netmask 255.255.255.0 {

}

The subnet-specific configuration goes inside the braces. You may specify as many subnets as you need in the configuration file, although for a home network like this I only need one.

Inside of the subnet configuration block, I set the gateway router and the range of IPs I'll be handing out with DHCP.

option routers 192.168.0.1;

range 192.168.0.30 192.168.0.200;

I also specify the default lease time and max lease time. The default lease time is the number of seconds the DHCP server will hold a lease for a client if the client doesn't ask for a specific lease length, and the max lease length is the maximum allowed lease length. Here I set the default to 604800 (one week), and the max to 2592000 (one month).

default-lease-time 604800;
max-lease-time 2592000;

Finally I have an example static client configuration. Here the client with the MAC address 22:33:44:55:66:77 will all ways be given the IP 192.168.0.201. This is useful when you want to assign a specific IP to a certain client without having to manually configure the interface.

host example-static-client {
        hardware ethernet 22:33:44:55:66:77;
        fixed-address 192.168.0.201;
}

Now that I'm done with the configuration file, it's time to start the DHCP server. To do this, I first enable, then start it using rcctl.

doas rcctl enable dhcpd
doas rcctl start dhcpd

With the server running, to see the leases that dhcpd is currently holding, you can check /var/db/dhcpd.leases. Entries will be added to this file as clients make DHCP requests.

If you followed along these steps, you now have a running DHCP sever!