Skip to content

Using ISC Kea DHCP

Foreword

Let me start by getting this out of the way – I don’t disagree with assigning an IP address on the machine itself, it’s a great way of ensuring that a machine gets the right IP address. That being said, there comes a point when you have too many machines to manage and it all becomes a bit of a mess trying to keep track of it all.

One of the things I’ve been trying to achieve with my home network is to have one consolidated point of authority and configuration. For example I have DNS servers, LDAP servers, all of which provide total configuration over the network. Configuration isn’t spread across machines, it’s centralised on one machine.

I run PfSense as my network router, and I love it. It’s has a fantastic suite of tools to operate a network, including ISC DHCPD. Though, I wanted to take it one step further. Rather than managing multiple networks from a web interface, not very interesting, I instead wanted to setup my own machine. I could have run with ISC DHCPD which is generally considered the industry standard, I wanted to jump into something new. I’ve decided to go with ISC Kea.

ISC Kea DHCP

ISC Kea is a relatively new system that builds on top of the ever popular ISC DHCPD. It’s certainly not completely community adopted, but I feel like it offers excellent opportunities that DHCPD does not.

Kea is modular by design, and splits it’s functionalities into extensible hooks. The DHCPv4, DHCPv6, and DDNS modules run separately and are dynamically loaded. You only need to run what you are using. The modular design also allows you to develop your own hooks in C++, or integrate community developed hooks.

Kea supports an “On-Line Re-configuration” REST API using a JSON configuration file that can be modified remotely using set commands. The API reloads the server without stopping and restarting. Particularly useful when you’re network has scaled massively, and your DHCP server is frequently dishing out leases. Allowing for On-Line Re-Configuration minimises downtime and network interruptions.

Kea strictly follows RFC and IEEE standards, allowing it to be smoothly integrated with existing systems. Even if you are currently using ISC DHCPD, you can migrate to Kea with minimal complications.

Kea supports multiple methods of storing DHCP leases; MySQL, PostgreSQL, Cassandra, even file-based CSV databases stored on a remote server over NFS or some other FTP.

Installing ISC Kea 1.9 DHCPv4 on Debian 10

The instructions I used are here. You can also build from source, if you would like. I will not be covering how to build from source.

Adding the Cloudsmith APT Repository

ISC publishes RPM, Deb and APK packages through Cloudsmith, we can use these to install ISC Kea 1.9 DHCPv4.

Start by going to the ISC repository on Cloudsmith, and selecting the latest version of Kea, for me that’s v1.9. From there, click the drop-down icon on the “Set Me Up” button near to the top. Select what kind of package you’d like to download, in my case I selected Debian.

Cloudsmith instructs us to execute the following command. This will add the repository to our sources list. curl -1sLf 'https://dl.cloudsmith.io/public/isc/kea-1-9/setup.deb.sh' | sudo -E bash

After being run, you should see OK: The repository has been installed successfully - You're ready to rock!

Installing through APT

Checkout apt search isc-kea. It shows us all the packages we can install. The most important ones we’ll need are;

  • isc-kea-admin
  • isc-kea-ctrl-agent
  • isc-kea-common
  • isc-kea-dhcp4-server
  • isc-kea-doc

Install them through apt install [package] -y.

Confirming Successful Installation

Once that’s all completed, ISC Kea should have successfully installed. Let’s check out some stuff.

Do systemctl status isc-kea-dhcp4-server. This is our service that starts /usr/sbin/kea-dhcp4 for us. It starts running after installation, I’d stop it before it screws with your existing infrastructure. Do systemctl stop isc-kea-dhcp4-server. We can start it up again once we’ve configured it.

You can find the Kea DHCPv4 config at /etc/kea/kea-dhcp4.conf. Open it and have a quick read through.

Kea writes its logs to journalctl by default. We can check them out by doing journalctl -u isc-kea-dhcp4-server.

DHCP Fundamentals

Before continuing, lets refresh ourselves on how Dynamic Host Configuration Protocol (DHCP) works. I’m sure if you’re this far in you at least understand that a DHCP server dishes out network configuration based on received broadcast messages.

When a device connects to a network it sends a broadcast here I am message. If there is a DHCP server listening on the network, a brief back and forth takes place where configuration is sent to a machine, and is acknowledged by the machine. DHCP leases have a lifecycle, let’s quickly look at that.

Lease Lifecycle

  • DHCPNAK – Server to Client, DHCP config is incorrect.
  • DHCPOFFER – Server to Client in response to a DHCP Discover, contains configuration
  • DHCPACK – Server to Client acknowledging new config
  • DHCPDISCOVER – Client broadcast to locate available DHCP servers
  • DHCPREQUEST – Client to Server requesting DHCP Lease with config
  1. When a device first connects to a network, it enters the INIT stage. The client sends a broadcast DHCPDISCOVER message.
  2. Any server that is also listening on that network responds with DHCPOFFER. This message contains various bits of config like the clients new IP Address, subnet mask, gateway, and other stuff like domain names and DNS IPs.
  3. The client then enters the SELECTING stage, where it sends a DHCPREQUEST to a specific DHCP server. The client requests to use the IP and config it had received in the first DHCPOFFER message.
  4. The server responds with DHCPACK, acknowledging that the server has recorded the DHCP Lease, and that the client can continue to use the IP address.
  5. The lease is now BOUND with the client and the DHCP server.
  6. After a set period (defined in DHCPOFFER), the client sends the DHCP server a DHCPREQUEST, requesting to continue to using the IP address. It enters the RENEWING stage.
  7. If the server finds no conflicts or other issues, it responds directly back with DHCPACK. The client returns to BOUND and can continue using the IP.
  8. What if the first DHCP server does not respond to the DHCPREQUEST, the client then enters the REBINDING stage. A broadcast DHCPREQUEST message is sent. If some other DHCP server an approve the exact same request and reply with DHCPACK, the client is rebound back into BOUND with a different DHCP server.
  9. If no other DHCP servers reply. We return to the INIT stage, the whole process begins again.

DHCP Options

When a DHCPOFFER message is sent to a client, it can contain various bits and pieces of information for the client to use when on the network. Notably, it can contain; the clients new IP address, the subnet mask, the gateway IP address, the DHCP server IP address, domain name, DNS IP addresses. Other cool ones are;

  • time-servers
  • swap-server
  • font-servers
  • www-server
  • log-servers
  • policy-filter
  • boot-file-name
  • pop-server
  • cookie-servers
  • static-routes
  • smtp-server
  • ntp-server

Configuring ISC Kea

All config is located in /etc/kea/. Let’s start by having a look at /etc/kea/kea-dhcp4.conf. Despite the .conf, all Kea config is stored in JSON syntax except it also allows for // comments. The DHCP4 config file will by default contain a lot of comments and some useful starting config, feel free to read through them!

It would be best for us to start with a clean slate and build our config from the ground up to what we need. Before we begin – take a backup of this file. Do cp /etc/kea/kea-dhcp4.conf /etc/kea/kea-dhcp4.conf.dist.

Wrapping it

Let’s start by getting the important stuff out of the way, to actually operate the server-side stuff.

All of the config relating to our DHCPv4 server needs to be wrapped within a “Dhcp4” object.

Within that, we specify what interfaces we want our server to listen on. Add an “interfaces-config” object, and create a “interfaces” array of strings. Here I’ve used “eth0”.

If we wish to utilise the ISC Kea Management API, we must open a socket for communication.

How you store our DHCP leases is totally up to you. The simplest method is using “memfile”. Simply a database stored as a .csv file. If your server is for larger deployments I would not recommend this. Go here for more details.

We also need to specify how we want to process expired leases. The settings I have specified here should be sufficient in most cases.

We finally need to specify how often a lease should be renewed “renew-timer”, how often a client should rebind to the DHCP server “rebind-timer”, and how long a DHCP lease is valid for “valid-lifetime”. All these values are in seconds.

{
    "Dhcp4":{
        "interfaces-config":{
            "interfaces":["eth0"]
        },
        "control-socket":{
            "socket-type":"unix",
            "socket-name":"/tmp/kea4-ctrl-socket"
        },
        "lease-database":{
            "type":"memfile",
            "name": "/tmp/kea-leases4.csv",
            "lfc-interval":3600
        },
        "expired-leases-processing":{
            "reclaim-timer-wait-time": 10,
            "flush-reclaimed-timer-wait-time": 25,
            "hold-reclaimed-time": 3600,
            "max-reclaim-leases": 100,
            "max-reclaim-time": 250,
            "unwarned-reclaim-cycles": 5
        },
        "renew-timer": 900,
        "rebind-timer": 1800,
        "valid-lifetime": 3600
    }
}

Logging

Logging usage is of great importance to us, particularly in development. Here we are logging our output to stdout. If you were to run the server directly through a shell you’d see messages flowing through. Though, if you’re running it through systemctl (which you really should be), messages will appear within journalctl.

You can view these messages by doing journalctl -u isc-kea-dhcp4-server.

{
    "Dhcp4": {
        "loggers": [
            {
                "name": "kea-dhcp4",
                "output_options": [
                    {
                        "output": "stdout",
                        "pattern": "%-5p %m\n"
                    }
                ],
                "severity": "INFO",
                "debuglevel": 0
            }
        ]
    }
}

Subnets and Pools

Lets make our first subnet and pool of IP addresses to allocate. We’ll add a subnet4 array of subnets. It’s important to note, Kea (like DHCPD) can serve multiple subnets. We define subnet4 as an array of subnets.

With our first subnet, let’s give it the standard subnet syntax of 192.168.0.0/24. We’ll also add our DHCP lease pool, 192.168.0.10 to 192.168.0.200.

Let’s also specify our router through option-data. option-data is an array of DHCP options supplied to clients by the DHCP server.

If we want, we can also reserve some IP addresses to a specific MAC address. There are many different ways this can be achieved. This is simply an example.

{
    "Dhcp4" :{
        "subnet4":[
            {
                "subnet":"192.168.0.0/24",
                "pools":[{"pool":"192.168.0.10 - 192.168.0.200"}],
                "option-data":[
                    {
                        "name": "routers",
                        "data": "192.168.0.1"
                    }
                ],
                "reservations":[
                    {
                        "hw-address":"1a:1b:1c:1d:1e:1f",
                        "ip-address":"192.168.0.5"
                    }
                ]
            }
        ]
    }
}

Option Data

One of the key functions of a DHCP server is to provide configuration to clients. To achieve this with Kea we specify our DHCP options as option-data arrays. These can be place almost everywhere throughout the configuration. Where you place this can scale its impact.

You can place option-data almost anywhere from the root of the config for global impact right down to a specific MAC address.

option-data follows pretty much the same formatting everywhere. Let’s have a look at a few examples I’ve placed here (from top to bottom).

I’ve defined our DNS servers as global config, regardless of what subnet or class you belong to, you’re going to be given those IP addresses as the DNS servers.

For subnet 192.168.0.0/24, I’ve defined our router as 192.168.0.1. Only leases that belong to that subnet will be provided that IP address.

If you’re the lucky device who sends a MAC address of 1a:1b:1c:1d:1e:1f, you’ll be given a special log-server option as well.

{
    "Dhcp4": {
        "option-data":[
            {
                "name": "domain-name-servers",
                "data": "192.168.0.3, 192.168.0.4",
                "always-send": true
            }
        ],
        "subnet4": [
            {
                "subnet": "192.168.0.0/24",
                "pools": [
                    {
                        "pool": "192.168.0.10 - 192.168.0.200"
                    }
                ],
                "option-data": [
                    {
                        "name": "routers",
                        "data": "192.168.0.1"
                    }
                ],
                "reservations": [
                    {
                        "hw-address": "1a:1b:1c:1d:1e:1f",
                        "ip-address": "192.168.0.5",
                        "option-data":[
                            {
                                "name":"log-servers",
                                "data":"192.168.0.8"
                            }
                        ]
                    }
                ]
            }
        ]
    }
}

Basic Starter Config

Here’s something to get you going! Compiling the bits and pieces from above, this configuration will serve requests.

Obviously one of the cool things you can achieve with JSON based config is messing around with the config formatting in such a way that makes it human readable. Feel free to do whatever, as long as it’s correctly formatted JSON.

{
    // Comments start with two slashes
    "Dhcp4": {
        // Actual config starts here.
        "interfaces-config": {
            "interfaces": ["eth0"],
            "dhcp-socket-type": "raw"
        },
        "valid-lifetime": 4000,
        "renew-timer": 1000,
        "rebind-timer": 2000,
        // We define our subnets in this list
        "subnet4": [
            {
                "subnet": "192.0.2.0/24",
                "pools":[{"pool": "192.0.2.10-192.0.2.200"}],
                "option-data":[
                    {"name":"routers","data":"192.168.2.1"},
                    {"name":"domain-name-servers","data":"192.168.2.4, 192.168.2.5"}
                ]
            }
        ],
        // We define our loggers in this list
        "loggers": [
            {
                "name": "kea-dhcp4",
                "output_options":[{"output":"stdout"}],
                "severity": "INFO",
                "debuglevel":0
            }
        ]
    }
}

Final Bits and Bytes

ISC Kea ARM (Administrator Reference Manual)

I’ve from experience found the Administrator Reference Manual written by ISC of great use. Obviously my article here is primarily to express and share my love for the Kea project but is in no way conclusive! ISC have very clearly put in a lot of time and thought into developing the server and it’s documentation. If you have any questions the best place to start is the ARM.

ISC Kea DHCP Webinars

I’ve also found the webinar series presented by Carsten Strotmann to be a fantastic resource in truly understanding Kea’s operation. It’s a 6 part series, roughly 1 hour session each. Incredibly valuable!

Stork Dashboard for Kea

ISC have also developed a Web based monitoring and management system that works in conjunction with ISC Kea DHCP and other Kea Modules called Stork!

ISC Kea Mailing List

If you’re interested in getting involved with the community, you can sign up to the mailing list.

ISC Kea is Open Source

As with many ISC projects, Kea is Open Source! Feel free to checkout the repository on GitLab. Submit issues if you run into any.

Leave a Reply

Your email address will not be published. Required fields are marked *