#+TITLE: Setting up a DHCP server on OpenBSD #+DATE: 2020-07-10T16:10:09-04:00 #+DRAFT: false #+DESCRIPTION: Cofiguring dhcpd for a small home network on OpenBSD #+TAGS[]: openbsd dhcp #+KEYWORDS[]: openbsd dhcp #+SLUG: #+SUMMARY: #+ATTR_HTML: :alt OpenBSD DHCP Server #+ATTR_HTML: :title OpenBSD DHCP Server [[file:cover.png]] [[https://www.openbsd.org/faq/faq4.html#Download][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 [[{{< ref "pcengines-comparison" >}}][PC Engines]] APU2E4 [[{{< ref "installing-openbsd-on-pcengines" >}}][running OpenBSD]]. One of the key services that I have to setup for this is the [[https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol][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 [[http://man.openbsd.org/dhcpd][=dhcpd(8)=]] for the DHCP server itself, [[http://man.openbsd.org/dhcpd.conf.5][=dhcpd.conf(5)=]] for the configuration file, and [[http://man.openbsd.org/dhcpd.leases.5][=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. #+BEGIN_SRC doas cp /etc/examples/dhcpd.conf /etc/ #+END_SRC Then I'll edit the file with =mg=, an emacs-like editor that comes with OpenBSD. #+BEGIN_SRC doas mg /etc/dhcpd.conf #+END_SRC Here's the finished configuration file. #+BEGIN_SRC # 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; } } #+END_SRC 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 [[https://en.wikipedia.org/wiki/Bootstrap_Protocol][BOOTP]] clients. Here I set the domain name and DNS servers globally. #+BEGIN_SRC option domain-name "home.local" option domain-name-servers 192.168.0.23, 8.8.8.8; #+END_SRC Then I declare the configuration for my subnet. #+BEGIN_SRC subnet 192.168.0.0 netmask 255.255.255.0 { } #+END_SRC 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. #+BEGIN_SRC option routers 192.168.0.1; range 192.168.0.30 192.168.0.200; #+END_SRC 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). #+BEGIN_SRC default-lease-time 604800; max-lease-time 2592000; #+END_SRC 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 IP. #+BEGIN_SRC host example-static-client { hardware ethernet 22:33:44:55:66:77; fixed-address 192.168.0.201; } #+END_SRC To run the DHCP server, I first enable, then start it using =rcctl=. #+BEGIN_SRC doas rcctl enable dhcpd doas rcctl start dhcpd #+END_SRC To see the leases the =dhcpd= is currently holding, you can check =/var/db/dhcpd.leases=. If you followed along these steps, you not have a running DHCP sever!