Ubuntu Server 18.04 – Serving IP addresses with isc-dhcp-server

How to Create a Droplet with DigitalOcean

While most network appliances you purchase nowadays often come with their own DHCP server, rolling your own gives you ultimate flexibility. Some of these built-in DHCP servers are full-featured and come with everything you need, while others may contain just enough features for it to function, but nothing truly exciting. Ubuntu servers make great DHCP servers, and rolling your own server is actually very easy to do.

First, the server that serves DHCP will need a static IP address. This means you’ll need to configure Netplan with a static IP assignment. A static lease won’t work here, since the DHCP server can’t assign an IP address to itself.

If you have yet to set a static IP, Chapter 4, Connecting to Networks, has a section that will walk you through the process.

Once you assign a static IP address, the next step is to install the isc-dhcp-server package:

sudo apt install isc-dhcp-server 

Depending on your configuration, the isc-dhcp-server service may have started automatically, or your server may have attempted to start it and failed to do so with an error. You can check the status of the daemon with the following command:

systemctl status isc-dhcp-server 

The output will either show that the service failed or is running. If the service failed to start, that’s perfectly fine—we haven’t even configured it yet. If it’s running, then you need to stop it for now, since it’s not a good idea to leave an unconfigured DHCP server running on your network. It might conflict with your existing one.

sudo systemctl stop isc-dhcp-server 

Now that you’ve installed the isc-dhcp-server package, you’ll have a default configuration file for it at /etc/dhcp/dhcpd.conf. This file will contain some default configuration, with some example settings that are commented out. Feel free to take a look at this file to get an idea of some of the settings you can configure. We’ll create our own dhcpd.conf file from scratch. So when you’re done looking at it, copy the existing file to a new name so we can refer to it later if we ever need to:

sudo mv /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.orig 

Now, we’re ready to create our own dhcpd.conf file. Open /etc/dhcp/dhcpd.conf in your preferred text editor. Since the file no longer exists (we moved it), we should start with an empty file. Here’s an example dhcpd.conf file that I will explain so that you understand how it works:

default-lease-time 86400; 
max-lease-time 86400; 
option subnet-mask 255.255.255.0; 
option broadcast-address 192.168.1.255; 
option domain-name "local.lan"; 
authoritative; 
subnet 192.168.1.0 netmask 255.255.255.0 { 
    range 192.168.1.100 192.168.1.240; 
    option routers 192.168.1.1;   
    option domain-name-servers 192.168.1.1; 
} 

As always, change the values I’ve used with those that match your network. I’ll explain each line so that you’ll understand how it affects the configuration of your DHCP server.

default-lease-time 43200; 

When a device connects to your network and requests an IP address, the expiration of the lease will be set to the number of seconds in default-lease-time if the device doesn’t explicitly ask for a longer lease time. Here, I’m setting that to 43200 seconds, which is equivalent to half a day. This basically means that the device will need to renew its IP address every 43200 seconds, unless it asks for a longer duration.

max-lease-time 86400; 

While the previous setting dictated the default lease time for devices that don’t ask for a specific lease time, the max-lease-time is the most that the device is allowed to have. In this case, I set this to one day (86400 seconds). Therefore, no device that receives an IP address from this DHCP server is allowed to hold onto their lease for longer than this without first renewing it.

option subnet-mask 255.255.255.0; 

With this setting, we’re informing clients that their subnet mask should be set to 255.255.255.0, which is for a default 24-bit network. If you plan to subnet your network, you’ll put in a different value here. 255.255.255.0 is fine if all you need is a 24-bit network.

option broadcast-address 192.168.1.255; 

With this setting, we’re informing the client to use 192.168.1.255 as the broadcast address, which is typically the last address in the subnet and cannot be assigned to a host.

option domain-name "local.lan"; 

Here, we’re setting the domain name of all hosts that connect to the server to include local.lan. The domain name is added to the end of the hostname. For example, if a workstation with a hostname of muffin receives an IP address from our DHCP server, it will be referred to as muffin.local.lan. Feel free to change this to the domain name of your organization, or you can leave it as is if you don’t have one.

authoritative;

With the authoritative; setting (the opposite is not authoritative;), we’re declaring our DHCP server as authoritative to our network. Unless you are planning to have multiple DHCP servers for multiple networks (which is rare), the authoritative; option should be included in your config file.

Now, we get to the most important part of our configuration file for DHCP. The following block details the specific information that will be provided to clients:

subnet 192.168.1.0 netmask 255.255.255.0 { 
    range 192.168.1.100 192.168.1.240; 
    option routers 192.168.1.1; 
    option domain-name-servers 192.168.1.1; 
} 

This block is probably self-explanatory, but we’re basically declaring our pool of addresses for the 192.168.1.0 network. We’re declaring a range of IPs from 192.168.1.100 through 192.168.1.240 to be available from clients. Now when our DHCP server provides an address to clients, it will choose one from this pool. We’re also providing a default gateway (option routers) and DNS server of 192.168.1.1. This is assuming that your router and local DNS server are both listed at that address, so make sure that you change it accordingly. Otherwise, anyone who receives a DHCP lease from your server will not be able to connect to anything. For the address pool (range), feel free to expand it or shrink it accordingly. For example, you might need more addresses than the 140 that are allowed in my sample range, so you may change it to something like 192.168.1.50 through 192.168.1.250. Feel free to experiment.

Now we have our configuration file in place, but the DHCP server will likely still not start until we declare an interface for it to listen for requests on. You can do that by editing the /etc/default/isc-dhcp-server file, where you’ll see a line toward the bottom similar to the following:

INTERFACESv4="" 

Simply type the name of the interface within the quotes:

INTERFACESv4="enp0s3" 

In case you forgot, the command to list the details of the interfaces on your server is ip addr show, or the shortened version, ip a.

Now that we have our DHCP server configured, we should be able to start it:

sudo systemctl start isc-dhcp-server 

Next, double-check that there were no errors; the daemon should report that it’s active (running), similar to what’s shown in the following screenshot (note that I use a different IP address scheme on this network):

sudo systemctl status isc-dhcp-server 
Checking the status of the isc-dhcp-server process

Assuming all went well, your DHCP server should be running. When an IP lease is assigned to a client, it will be recorded in the /var/lib/dhcp/dhcpd.leases file. While your DHCP server runs, it will also record information to your server’s system log, located at /var/log/syslog. To see your DHCP server function in all its glory, you can follow the log as it gets written to with the following:

sudo tail -f /var/log/syslog 

The -f flag of the tail command is indispensable, and it is something you’ll likely use quite often as a server administrator. With the -f option, you’ll watch the log as it gets written to, rather than needing to refresh it manually. You can press Ctrl + C to break out of the file.

While your DHCP server runs, you’ll see notices appear within the syslog file whenever a DHCP request was received and when a lease is offered to a client. A typical DHCP request will appear in the log similar to the following (the name of my DHCP server is hermes, in case you were wondering):

May  5 22:07:36 hermes dhcpd: DHCPDISCOVER from 52:54:00:88:f8:bc via enp0s3 
May  5 22:07:36 hermes dhcpd: DHCPOFFER on 192.168.1.103 to 51:52:01:87:f7:bc via enp0s3 

Active and previous DHCP leases are stored in the /var/lib/dhcp/dhcpd.leases file, and a typical lease entry in that file would look similar to the following:

lease 192.168.1.138 { 
  starts 0 2016/05/06 16:37:30; 
  ends 0 2016/05/06 16:42:30; 
  cltt 0 2016/05/06 16:37:30; 
  binding state active; 
  next binding state free; 
  rewind binding state free; 
  hardware ethernet 32:6e:92:01:1f:7f; 
} 

When a new device is added to your network and receives an IP address from your new DHCP server, you should see the lease information populate into that file. This file can be incredibly helpful, because whenever you connect a new device, you won’t have to interrogate the device itself to find out what its IP address is. You can just check the /var/lib/dhcp/dhcpd.leases file. If the device advertises its hostname, you’ll see it within its lease entry. A good example of how this can be useful is connecting a Raspberry Pi to your network. Once you plug it in and turn it on, you’ll see its IP address in the dhcpcd.leases file, and then you can connect to it via SSH without having to plug a monitor in to it. Similarly, you can view the temporary IP address of a new network appliance you plug in so that you can connect to it and configure it.

If you have any trouble setting up the isc-dhcp-server daemon, double-check that you have set all the correct and matching values within your static IP assignment (the /etc/network/interfaces file), as well as within your /etc/dhcp/dhcpd.conf file. For example, your server must be within the same network as the IPs you’re assigning to clients. As long as everything matches, you should be fine and it should start properly.

Comments are closed.