Chapter 14 Managing Host Addresses Dynamically with DHCP
Chapter Overview
In this chapter I introduce the Dynamic Host Configuration Protocol (DHCP), which automatically manages key network parameters on a LAN—IP addresses, subnet masks, gateways, and DNS servers. DHCP improves IP utilization, speeds up configuration, and reduces operating overhead.
I configure and deploy the Kea DHCP service on Linux, explain each parameter in its configuration file, and complete hands‑on labs: dynamically allocating IP addresses and binding fixed addresses to specific MACs. By the end, you’ll feel the practical power of DHCP and be able to use it confidently in production.
14.1 The DHCP protocol
DHCP is a UDP‑based protocol used inside local networks. It’s best suited to large LANs or environments with many mobile devices. A DHCP server automatically provides clients with IP configuration, offering a one‑stop service for network parameters.
Put simply, DHCP lets hosts in the same LAN obtain network settings automatically. In a topology like Figure 14‑1, manually configuring every machine would be tedious, and future maintenance would be painful. As the number of hosts grows (100, 1,000, or more), the work becomes overwhelming. DHCP not only assigns parameters automatically and ensures uniqueness of addresses, it can also reserve a fixed IP for a particular host.
Figure 14-1 DHCP topology
DHCP is everywhere: server rooms, homes, airports, cafés. For example, a café owner wants to focus on serving coffee, not on setting each visitor’s IP, mask, and gateway. A typical café LAN uses a private /24 such as 192.168.10.0/24, which can hold just over 200 hosts; daily customer count easily exceeds that. If customers were assigned addresses manually, those IPs wouldn’t be released when they leave, quickly exhausting the pool and raising management costs. With DHCP, clients automatically obtain the IP they need to get online; when they leave, the server reclaims the lease for others to use.
Since DHCP is essential in real environments, let me review several common terms:
- scope: a complete IP subnet; DHCP uses scopes to manage distribution, address allocation, and parameters.
- superscope: a list of scopes on a single physical network that are managed together.
- exclusion range: addresses inside a scope that will never be handed to clients.
- address pool: the remaining range within the scope that can be allocated dynamically.
- lease: how long a client may use an assigned IP.
- reservation: a guarantee that a particular device always receives the same IP.
14.2 Deploying the Kea service
On RHEL 10, the traditional ISC DHCP server package (dhcp-server, service name dhcpd) has been removed. The distribution now ships ISC Kea as the next‑generation DHCP service. The theory is the same, but configuration differs substantially, so follow the steps carefully.
After confirming my repositories, I install Kea (package name kea):
root@linuxprobe:~# dnf install kea
Updating Subscription Management repositories.
BaseOS 2.7 MB/s | 2.7 kB 00:00
AppStream 2.7 MB/s | 2.8 kB 00:00
Dependencies resolved.
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
kea x86_64 2.6.1-4.el10 BaseOS 1.3 M
Installing dependencies:
boost-system x86_64 1.83.0-4.el10 BaseOS 16 k
kea-libs x86_64 2.6.1-4.el10 BaseOS 3.1 M
libpq x86_64 16.1-7.el10 BaseOS 253 k
log4cplus x86_64 2.1.1-7.el10 BaseOS 355 k
mariadb-connector-c x86_64 3.4.1-1.el10 BaseOS 214 k
mariadb-connector-c-config noarch 3.4.1-1.el10 BaseOS 10 k
Installed:
boost-system-1.83.0-4.el10.x86_64
kea-2.6.1-4.el10.x86_64
kea-libs-2.6.1-4.el10.x86_64
libpq-16.1-7.el10.x86_64
log4cplus-2.1.1-7.el10.x86_64
mariadb-connector-c-3.4.1-1.el10.x86_64
mariadb-connector-c-config-3.4.1-1.el10.noarch
Complete!
Kea’s IPv4 configuration lives in kea-dhcp4.conf
. The file is 468 lines long, but most are comments. I take a quick look (I’ll explain options shortly):
root@linuxprobe:~# cat /etc/kea/kea-dhcp4.conf
You’ll notice the familiar JSON format. Much of the file is blank lines and comments. I create a condensed version by stripping both with grep
, then review the numbered lines:
root@linuxprobe:~# cd /etc/kea/
root@linuxprobe:/etc/kea# mv kea-dhcp4.conf kea-dhcp4.bak
root@linuxprobe:/etc/kea# grep -v "^$" kea-dhcp4.bak | grep -v "//" > kea-dhcp4.conf
root@linuxprobe:/etc/kea# cat -n kea-dhcp4.conf
Even the condensed file is 127 lines—about one quarter of the original. Table 14‑1 summarizes common Kea parameters and what they do.
Table 14-1 Common Kea parameters and their purposes
Parameter | Purpose |
---|---|
interfaces | Which interfaces Kea listens on (e.g., ens160 ) |
subnet | Address scope, e.g., 192.168.10.0/24 |
pools | Address ranges used for dynamic allocation |
reservations | Bind specific IPs to clients by MAC or identifier |
valid-lifetime | IP lease lifetime in seconds |
renew-timer | Lease renewal timer |
rebind-timer | Lease rebind timer |
option-data | A set of DHCP options (gateway, DNS, NTP, etc.) |
routers | Default gateway for clients |
domain-name-servers | DNS server addresses for clients |
domain-name | DNS search domain for clients (e.g., example.org ) |
ntp-servers | NTP server addresses |
nis-servers | NIS domain server addresses |
time-offset | Offset from UTC in seconds (e.g., UTC+8 is 28800) |
server-name | DHCP server’s hostname or identifier |
ddns-send-updates | Enable/disable dynamic DNS updates (true/false) |
ddns-qualifying-suffix | Suffix used for DDNS (e.g., example.com. ) |
host-reservation-identifiers | Which identifiers to use for reservations (e.g., hw-address ) |
hw-address | Client MAC address for a reservation |
ip-address | Fixed IP to be handed to that client |
client-classes | Classify clients and apply different policies |
lease-database | Where leases are stored |
loggers | How Kea logs (method, level, destination) |
14.3 Automating IP address management
DHCP was built to centralize and streamline IP management. The server automatically provides clients with IP, mask, gateway, DNS, and more—and reclaims leases when they expire.
Let me simulate a realistic request:
“Operations: Tomorrow, 100 learners will bring their own laptops for a training. Please ensure the lab’s local DHCP server automatically provides IP connectivity.”
Assume the lab’s network parameters are as in Table 14‑2.
Table 14-2 Lab network parameters
Parameter | Value |
---|---|
IP range | 192.168.10.50–192.168.10.150 |
Subnet mask | 255.255.255.0 |
Gateway | 192.168.10.1 |
DNS server | 192.168.10.1 |
Table 14‑3 lists the server and client setup.
Table 14-3 DHCP server and client configuration
Host type | OS | IP address |
---|---|---|
DHCP server | RHEL 10 | 192.168.10.1 |
DHCP client | Windows 11 | Obtain via DHCP |
Scopes are usually full subnets; the address pool is the portion actually handed to clients, so the pool is less than or equal to the scope. Because VMware Workstation includes its own DHCP service, I disable it to avoid conflicts with Kea (Figures 14‑2 and 14‑3).
Figure 14-2 Open “Virtual Network Editor”
Figure 14-3 Turn off VMware’s built‑in DHCP
I power on a few client VMs to test (1–3 is sufficient). I ensure both server and clients use Host‑only networking; otherwise they’ll be isolated and won’t obtain addresses.
After confirming the server’s IP is correct, I configure Kea. First, I edit lines 1–5 to specify the NIC name:
root@linuxprobe:/etc/kea# vim kea-dhcp4.conf
1 {
2 "Dhcp4": {
3 "interfaces-config": {
4 "interfaces": [ "ens160" ]
5 },
Lines 6–9 define a control socket used to talk to the server daemon. I don’t need it here; I delete these lines:
6 "control-socket": {
7 "socket-type": "unix",
8 "socket-name": "/tmp/kea4-ctrl-socket"
9 },
Lines 10–13 define the lease database. Not required for this exercise; I delete:
10 "lease-database": {
11 "type": "memfile",
12 "lfc-interval": 3600
13 },
Lines 14–21 set parameters for processing expired leases. I delete them as well:
14 "expired-leases-processing": {
15 "reclaim-timer-wait-time": 10,
16 "flush-reclaimed-timer-wait-time": 25,
17 "hold-reclaimed-time": 3600,
18 "max-reclaim-leases": 100,
19 "max-reclaim-time": 250,
20 "unwarned-reclaim-cycles": 5
21 },
Lines 22–24 set renew, rebind, and lifetime timers. Kea defaults to RFC 2131 values if omitted, so I delete these too:
22 "renew-timer": 900,
23 "rebind-timer": 1800,
24 "valid-lifetime": 3600,
Lines 25–29 define global client DNS. I keep and modify per Table 14‑2:
25 "option-data": [
26 {
27 "name": "domain-name-servers",
28 "data": "192.168.10.1"
29 },
Lines 30–46 set default search domain and other extras. I don’t need them; I delete:
30 {
31 "code": 15,
32 "data": "example.org"
33 },
34 {
35 "name": "domain-search",
36 "data": "mydomain.example.com, example.com"
37 },
38 {
39 "name": "boot-file-name",
40 "data": "EST5EDT4\,M3.2.0/02:00\,M11.1.0/02:00"
41 },
42 {
43 "name": "default-ip-ttl",
44 "data": "0xf0"
45 }
46 ],
Lines 47–55 define client classes and vendor‑specific options. I don’t need them; I delete:
47 "client-classes": [
48 {
49 "name": "voip",
50 "test": "substring(option[60].hex,0,6) == 'Aastra'",
51 "next-server": "192.0.2.254",
52 "server-hostname": "hal9000",
53 "boot-file-name": "/dev/null"
54 }
55 ],
Lines 56–60 define the scope and pool. I fill them in per Table 14‑2:
56 "subnet4": [
57 {
58 "id": 1,
59 "subnet": "192.168.10.0/24",
60 "pools": [ { "pool": "192.168.10.50 - 192.168.10.150" } ],
Lines 61–66 set the default gateway:
61 "option-data": [
62 {
63 "name": "routers",
64 "data": "192.168.10.1"
65 }
66 ],
Lines 67–113 show reservations (MAC↔IP bindings). I’ll use these in the next section; I delete them for now:
67 "reservations": [
68 {
69 "hw-address": "1a:1b:1c:1d:1e:1f",
70 "ip-address": "192.0.2.201"
71 },
72 {
73 "client-id": "01:11:22:33:44:55:66",
74 "ip-address": "192.0.2.202",
75 "hostname": "special-snowflake"
76 },
77 {
78 "duid": "01:02:03:04:05",
79 "ip-address": "192.0.2.203",
80 "option-data": [ {
81 "name": "domain-name-servers",
82 "data": "10.1.1.202, 10.1.1.203"
83 } ]
84 },
85 {
86 "client-id": "01:12:23:34:45:56:67",
87 "ip-address": "192.0.2.204",
88 "option-data": [
89 {
90 "name": "vivso-suboptions",
91 "data": "4491"
92 },
93 {
94 "name": "tftp-servers",
95 "space": "vendor-4491",
96 "data": "10.1.1.202, 10.1.1.203"
97 }
98 ]
99 },
100 {
101 "client-id": "01:0a:0b:0c:0d:0e:0f",
102 "ip-address": "192.0.2.205",
103 "next-server": "192.0.2.1",
104 "server-hostname": "hal9000",
105 "boot-file-name": "/dev/null"
106 },
107 {
108 "flex-id": "'s0mEVaLue'",
109 "ip-address": "192.0.2.206"
110 }
111 ]
112 }
113 ],
Lines 114–125 configure logging. Optional here; I delete them too:
114 "loggers": [
115 {
116 "name": "kea-dhcp4",
117 "output-options": [
118 {
119 "output": "/var/log/kea-dhcp4.log"
120 }
121 ],
122 "severity": "INFO",
123 "debuglevel": 0
124 }
125 ]
After trimming, the effective configuration is just 26 lines—the truly useful part:
1 {
2 "Dhcp4": {
3 "interfaces-config": {
4 "interfaces": [ "ens160" ]
5 },
6 "option-data": [
7 {
8 "name": "domain-name-servers",
9 "data": "192.168.10.1"
10 },
11 ],
12 "subnet4": [
13 {
14 "id": 1,
15 "subnet": "192.168.10.0/24",
16 "pools": [ { "pool": "192.168.10.50 - 192.168.10.150" } ],
17 "option-data": [
18 {
19 "name": "routers",
20 "data": "192.168.10.1"
21 }
22 ],
23 }
24 ],
25 }
26 }
In exams and production alike, I enable services at boot so they start automatically after a reboot:
root@linuxprobe:/etc/kea# systemctl restart kea-dhcp4
root@linuxprobe:/etc/kea# systemctl enable kea-dhcp4
Created symlink '/etc/systemd/system/multi-user.target.wants/kea-dhcp4.service' → '/usr/lib/systemd/system/kea-dhcp4.service'.
Now I flip a Windows 11 client to Host‑only networking (Figure 14‑4) and set its NIC to obtain an address automatically. After a short wait, the client should display the assigned network info as in Figure 14‑5.
Figure 14-4 NIC mode
Figure 14-5 IP obtained automatically
In production, the firewall may block DHCP. I open it if needed:
root@linuxprobe:~# firewall-cmd --permanent --add-service=dhcp
success
root@linuxprobe:~# firewall-cmd --reload
success
Typically, DHCP proceeds through four stages: discover, offer, request, and acknowledge. After a client receives an IP, it broadcasts an ARP probe. Devices—including the Kea server—listen; when Kea hears a probe for one of its assigned addresses, it marks that IP as in use so it won’t be offered to others, preventing conflicts at the source.
14.4 Reserving fixed IP addresses
A reservation ensures that a particular device always gets the same IP. Think of it as a “reserved table” at a restaurant: the DHCP server holds that address for a specific client.
To bind an IP to a host, I need the host’s MAC address—a unique identifier on the NIC. Figures 14‑6 and 14‑7 show how to view it on Linux and Windows, respectively.
Figure 14-6 Viewing the NIC MAC on Linux
Figure 14-7 Viewing the NIC MAC on Windows
In Kea’s configuration, I bind MAC and IP using the following structure:
MAC to IP binding code | |||
---|---|---|---|
"reservations": [ | |||
{ | |||
"hw-address": | "MAC" | , | |
"ip-address": | "IP" | , | |
"hostname": | "HostName" | ||
} | |||
] |
A common pitfall I’ve seen in classes: some learners perform the binding test on Windows hosts, where older versions (Windows 7/10) display MAC addresses with hyphens (e.g., 00-0C-29-16-3F-EF
). In Linux and Windows 11, the delimiter is a colon (:
).
root@linuxprobe:/etc/kea# vim kea-dhcp4.conf
{
"Dhcp4": {
"interfaces-config": {
"interfaces": [ "ens160" ]
},
"option-data": [
{
"name": "domain-name-servers",
"data": "192.168.10.1"
},
],
"subnet4": [
{
"id": 1,
"subnet": "192.168.10.0/24",
"pools": [ { "pool": "192.168.10.50 - 192.168.10.150" } ],
"option-data": [
{
"name": "routers",
"data": "192.168.10.1"
}
],
"reservations": [
{
"hw-address": "00:0C:29:16:3F:EF",
"ip-address": "192.168.10.88",
"hostname": "Windows11"
}
]
}
],
}
}
After confirming parameters are correct, I save and restart Kea:
root@linuxprobe:/etc/kea# systemctl restart kea-dhcp4
If I just assigned this host an IP, the lease may not have expired yet, so it won’t switch to the reserved IP immediately. To see the effect right away, I restart the client’s network (Figure 14‑8).
Figure 14-8 Restart the NIC
I then see the reserved address in effect (Figure 14‑9).
Figure 14-9 Verifying the reservation
Review Questions
-
What is DHCP used for?
Answer: Automatically distributing IP configuration to devices on a LAN. -
Which network resources can DHCP hand out?
Answer: IP address, subnet mask, default gateway, and DNS servers. -
Which range is actually handed to users—the scope or the pool?
Answer: The address pool (because a scope can include excluded addresses). -
What’s the role of a lease?
Answer: Define how long a client may use its address; expired leases are reclaimed to avoid waste. -
What’s a reservation?
Answer: Binding a host’s MAC to a fixed IP so it always receives the same address. -
What does an exclusion range do?
Answer: Ensures those IPs are never allocated to clients. -
Binding which piece of host information guarantees a fixed IP?
Answer: The NIC’s MAC address. -
Can a MAC as shown by Windows 10 be used directly?
Answer: Not as‑is—convert hyphens to colons. -
Without checking the client, how can I learn its MAC and assigned IP?
Answer: Check the server’s logs (e.g.,/var/log/messages
). -
If Kea is running but clients still get no address, what are common causes?
Answer: The server and clients are on different network modes (physically isolated), or the firewall is blocking DHCP.