Part V — Host configuration
19. DHCP, from DISCOVER to lease renewal
19.1 The DORA exchange (IPv4)
DHCP runs over UDP: client port 68, server port 67. Before it has an
address, the client uses source 0.0.0.0 and destination 255.255.255.255
(limited broadcast).
Client Server(s)
| DHCPDISCOVER (bcast) ------------>| "anyone? my MAC is aa:bb:.., xid=0x1f2e"
|<------------ DHCPOFFER (bcast/uni) | "you can have 192.168.1.50, mask /24,
| | gw .1, dns .1, lease 86400s, from me"
| DHCPREQUEST (bcast) ------------->| "I accept 192.168.1.50 from server X"
|<------------- DHCPACK | "confirmed; here are all options"
| |
| (client runs ARP/NS for its new |
| address = duplicate detection) |
- DISCOVER is broadcast because the client has no address and no idea who the server is.
- Multiple servers may OFFER; the client picks one (usually the first) and names it in the REQUEST via the Server Identifier option; the others withdraw.
- DHCPNAK = "that address isn't valid (any more) on this segment" → client restarts from DISCOVER. Common after moving between networks.
- DHCPDECLINE = client's post-assignment ARP/DAD found the address already in use → back to DISCOVER, server marks it bad.
- DHCPRELEASE = graceful give-back (many clients skip it).
- DHCPINFORM = "I have a static IP, just give me options (DNS, etc.)."
19.2 The lease timers: T1, T2, and expiry
0 T1 (50%) T2 (87.5%) Lease end (100%)
|---------------------------|---------------|---------------|
normal use | | |
| RENEW (unicast to same server)
| REBIND (broadcast to ANY server)
| address released,
back to DISCOVER
- At T1 (default 50% of lease) the client renews by unicasting a REQUEST to its server. Usually silent and instant.
- If that fails, at T2 (87.5%) it rebinds — broadcasts a REQUEST to any server.
- If nothing answers by lease end, the client must stop using the address.
A well-behaved client then falls to
169.254.x.xlink-local (APIPA) — the "I have limited connectivity / self-assigned IP" state.
19.3 Key options (the numbers show up in captures)
| Option | Name | Notes |
|---|---|---|
| 1 | Subnet mask | |
| 3 | Router (default gateway) | |
| 6 | DNS servers | |
| 12 / 15 | Hostname / Domain name | |
| 42 | NTP servers | |
| 51 | Lease time | |
| 53 | DHCP message type | 1=DISCOVER 2=OFFER 3=REQUEST 5=ACK 6=NAK … |
| 54 | Server identifier | which server this is from |
| 55 | Parameter Request List | the client's wishlist; also an OS fingerprint |
| 82 | Relay Agent Information | inserted by the relay; carries the ingress port/circuit — used for IP-per-port policy and DHCP snooping |
| 119 | Domain search list | |
| 121 / 249 | Classless static routes | push extra routes via DHCP (249 = MS variant) |
19.4 DHCP across subnets: the relay
The DHCP server is usually not on the client's broadcast domain. The router runs
a DHCP relay (ip helper-address on Cisco, dhcp-relay elsewhere): it
catches the broadcast DISCOVER, rewrites it as unicast to the real server, stamps
the giaddr (gateway IP) so the server knows which subnet/pool to use, and
relays the answer back. This is why one central DHCP server can serve 200 VLANs.
19.5 Failure modes
- Rogue DHCP server (someone plugs in a home router): hands out its own IP as gateway → MITM or black hole. Defense: DHCP snooping on switches (only "trusted" ports may send OFFER/ACK) + option 82.
- Pool exhaustion: short leases + churn (conference Wi-Fi) or a client requesting many addresses. Symptom: new clients get APIPA. Fix: bigger pool, shorter lease, or per-MAC limits.
- Lease/identity mismatch after cloning a VM: two VMs with the same MAC fight over one lease → flapping. Regenerate MACs.
- DHCPv6 uses DUID, not MAC: a re-imaged host presents a new DUID and gets a new address, orphaning your reservation.
19.6 War story
Every Monday, a branch office's laptops took 5 minutes to get online. The DHCP lease was 8 days and the pool was sized for the ~40 daily devices; over a busy week ~90 distinct devices (visitors, phones) consumed leases that didn't expire until after the weekend. Monday's staff hit an exhausted pool and fell to APIPA until leases aged out. Fix: 8-hour lease for the guest VLAN, separate pool. Lesson: lease time × device churn must be ≤ pool size, with margin.
Try it yourself
sudo tcpdump -i eth0 -n -v 'udp port 67 or udp port 68' # watch DORA
# Linux (systemd):
networkctl status eth0
# dhclient with verbose lease info:
sudo dhclient -v eth0
cat /var/lib/dhcp/dhclient.leases # or /var/lib/NetworkManager/*.lease
nmcli -f DHCP4 con show "Wired connection 1"