DHCP Server Configuration with ISC dhcpd
I deployed an ISC DHCP server with a scoped pool, static reservations for infrastructure hosts, and standard options for gateway and DNS. Centralized addressing eliminated manual IP assignment while keeping servers on fixed, MAC-reserved addresses.
Objective & Context
DHCP automates client addressing through the DORA exchange (Discover, Offer, Request, Acknowledge). This lab balances dynamic pools for clients with reservations for hosts that need stable addresses, complementing the static-config and DNS labs.
Learning Objectives
- Write a dhcpd.conf scope with dynamic ranges, reservations, and DHCP options.
- Validate the configuration with dhcpd -t before starting the service.
- Enable and persist the isc-dhcp-server service across reboots.
- Confirm the DORA exchange by reading server logs for DHCPACK messages.
- Distinguish dynamic leases from MAC-based reservations in the lease database.
Environment & Prerequisites
Prerequisites
- Linux server with isc-dhcp-server; one test client.
- A subnet plan with a defined dynamic range and reservations.
- Gateway and DNS resolver addresses to advertise.
- Ubuntu or Debian server with a static IP on the subnet being served (DHCP servers must not be DHCP clients of themselves).
- Install the server: sudo apt install -y isc-dhcp-server.
- Root or sudo access.
- One test client on the same broadcast domain (or a DHCP relay configured).
- A subnet plan: dynamic range, gateway address, and DNS resolver addresses to advertise.
Step-by-Step Execution
1. Define the scope and a reservation [ROOT REQUIRED]
Config content (place at /etc/dhcp/dhcpd.conf):
default-lease-time 600;
max-lease-time 7200;
subnet 192.168.20.0 netmask 255.255.255.0 {
range 192.168.20.100 192.168.20.200;
option routers 192.168.20.1;
option domain-name-servers 192.168.20.2;
}
host nas { hardware ethernet de:ad:be:ef:00:11; fixed-address 192.168.20.10; }
What this teaches: dhcpd.conf maps pools, reservations, and options to subnets, which is the entire policy of the DHCP service.
Two fresh-system gotchas. First, tell dhcpd which interface to serve in /etc/default/isc-dhcp-server: INTERFACESv4="eth0" (an empty value makes startup fail when a declared subnet matches none of the listening interfaces). Second, keep the reserved address 192.168.20.10 outside the dynamic range, or dhcpd may hand it to a random client.
2. Validate config and start the service
dhcpd -t -cf /etc/dhcp/dhcpd.conf && systemctl enable --now isc-dhcp-serverExpected output:
(dhcpd -t prints nothing when the config parses cleanly)
Created symlink /etc/systemd/system/multi-user.target.wants/isc-dhcp-server.service -> /usr/lib/systemd/system/isc-dhcp-server.service.
What this teaches: syntax-checking before starting the daemon avoids a failed service and a confusing outage.
3. Confirm a lease is issued
journalctl -u isc-dhcp-server | grep DHCPACKExpected output:
DHCPACK on 192.168.20.105 to aa:bb:cc:dd:ee:ff via eth0
What this teaches: DHCPACK lines in the journal are the server-side proof that the DORA exchange completed.
How It Works
DHCP clients obtain addresses through the DORA exchange: Discover (client broadcasts looking for servers), Offer (server proposes an address plus options), Request (client asks for the offered address), Acknowledge (server confirms the lease). The whole exchange normally completes in milliseconds over UDP ports 67 and 68.
Leases have lifetimes. Clients attempt renewal at 50 percent of the lease time (T1) and rebinding at 87.5 percent (T2); if both fail, the lease expires and the address returns to the pool. Reservations bypass the pool: the server always offers the same address to a known MAC address, which is how infrastructure hosts keep stable addresses without static configuration.
Options are how the server pushes more than an address: option routers sets the default gateway, option domain-name-servers sets resolvers, and option domain-name sets the search suffix. Because DHCP is broadcast-based, it does not cross routers unless a relay agent (ip helper-address or dhcrelay) forwards the broadcasts as unicast.
Validation & Testing
Release and renew on the client and confirm it receives a pool address while the reserved host always gets its fixed IP. Pass criteria: successful DORA exchange, correct gateway/DNS options, and reservation honored by MAC.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| isc-dhcp-server fails to start | No subnet declaration matches the server's own interface address | Add a subnet block for the interface's network or remove the interface from INTERFACESv4 in /etc/default/isc-dhcp-server |
| Clients get no offer | Server listening on the wrong interface, or UDP 67/68 blocked | Set INTERFACESv4 to the correct NIC and confirm the firewall allows bootps/bootpc |
| Client receives an address from the wrong scope | Multiple subnet declarations and the relay agent's giaddr matches the wrong one | Check the relay's source address and keep one subnet declaration per served network |
| Reservation never applies | MAC address typo in the host block | Compare the host declaration against the client's actual MAC from ip link |
| A rogue DHCP server answers first | An unauthorized server on the broadcast domain | Find it by its offered gateway/MAC, then use DHCP snooping on managed switches to block it |
| Clients keep an old address after the range changes | Clients renew their existing lease at T1 (50 percent of lease time) instead of asking for a new one | Shorten max-lease-time before changes, or force release/renew on the client (dhclient -r, then dhclient) |
Advanced: Troubleshooting
- No offers: the server interface must be on the same broadcast domain or use a relay (ip-helper).
- Wrong options: confirm scope vs global option precedence.
- Lease conflicts: ensure the dynamic range excludes reserved addresses.
Key Results
- Automated addressing for a /24 client pool of 100 addresses.
- Pinned infrastructure hosts to fixed IPs via MAC reservations.
- Advertised gateway and DNS options to 100% of leased clients.
- Reduced manual IP assignment effort to zero for client subnets.
Key Takeaways
- Always run dhcpd -t after editing the config; a typo takes down the whole service.
- Give the DHCP server itself a static address on every subnet it serves.
- Use reservations for infrastructure and pools for clients, never mix the two casually.
- Read the lease file and journal, not the client, when debugging.
Practice Challenges
Challenge 1: Add a second pool with different options
Goal: Serve a guest VLAN scope with a short 1-hour lease and a different DNS resolver, alongside the existing scope.
Hint: Add a second subnet declaration and restart; confirm with dhcpd -t first.
Challenge 2: Failover pair
Goal: Configure two dhcpd servers in a failover partnership so clients keep getting leases if one server dies.
Hint: Use the failover peer stanza with matching names and split 128 on both servers.