How DHCP works
Every address that ipconfig or ip addr shows as dynamic or with a Lease Expires came from a DHCP server, almost always your router. Knowing the four-packet conversation behind it makes every DHCP fault, from 169.254 addresses to duplicate IPs, easy to place.
The conversation: DORA
- DISCOVER. The client, with no address yet, broadcasts from 0.0.0.0 to 255.255.255.255 on UDP port 68 → 67: "any DHCP servers here? My MAC is 8c:16:45:3a:9b:2d, I would like 192.168.1.42 back if possible, and I would like options 1, 3, 6, 15, 119…".
- OFFER. Each server that hears it replies (broadcast, or unicast to the MAC) with a proposed address, mask, lease time and the requested options, identifying itself with option 54.
- REQUEST. The client picks one offer (normally the first) and broadcasts a request naming that server and that address, so any other servers know to withdraw.
- ACK. The chosen server confirms. The client does a final duplicate check with ARP (gratuitous ARP or an ARP probe), then configures the interface. If the check finds the address in use it sends DECLINE and starts again.
A NAK from the server at step 4 means "that address is not valid here"; the client restarts from DISCOVER. Total time on a healthy network: well under a second. Windows waits about 60 seconds before giving up and self-assigning a 169.254 address; Linux clients keep retrying with backoff.
sudo tcpdump -i eth0 -n -v port 67 or port 68 # watch the exchange on Linux/macOS
# Windows: pktmon filter add -p 67; pktmon filter add -p 68; pktmon start -c; ... pktmon stop; pktmon etl2pcapng
# Wireshark filter: dhcp (bootp on old versions)10:14:52.011 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 8c:16:45:3a:9b:2d, length 300
Client-Ethernet-Address 8c:16:45:3a:9b:2d
DHCP-Message Option 53: Discover
Requested-IP Option 50: 192.168.1.42
Parameter-Request Option 55: Subnet-Mask, Default-Gateway, Domain-Name-Server, Domain-Name
10:14:52.014 IP 192.168.1.1.67 > 192.168.1.42.68: BOOTP/DHCP, Reply, length 300
DHCP-Message Option 53: Offer
Server-ID Option 54: 192.168.1.1
Lease-Time Option 51: 86400
Subnet-Mask Option 1: 255.255.255.0
Default-Gateway Option 3: 192.168.1.1
Domain-Name-Server Option 6: 192.168.1.1
10:14:52.015 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request ... DHCP-Message Option 53: Request
10:14:52.017 IP 192.168.1.1.67 > 192.168.1.42.68: BOOTP/DHCP, Reply ... DHCP-Message Option 53: ACKLeases, T1 and T2
The ACK carries a lease time (option 51): commonly 24 hours on home routers, 8 days on Windows Server, an hour or less on guest networks. The client sets two timers:
- T1, at 50% of the lease: the client unicasts a REQUEST to the server that granted it, asking to renew. On success the lease restarts. This is invisible;
ipconfig /alljust shows the lease dates move. - T2, at 87.5%: if renewal has failed (server unreachable), the client broadcasts a REQUEST so any server can extend it.
- Expiry: if nothing answers, the client must stop using the address. Windows drops it and self-assigns; Linux clients typically keep retrying and eventually drop it.
So a device that shows a lease expiring in the next hour when leases are 24 hours long has been failing to renew for over twelve hours: the DHCP server has been unreachable since then, even though the network "worked" the whole time. ipconfig /renew forces T1 now. Release and renew in detail →
Reboots do not reset leases. A client that remembers its old address asks for it again (option 50) and normally gets it, which is why /renew "does not change my IP".
The options
| Option | Name | Where you see it |
|---|---|---|
| 1 | Subnet mask | Subnet Mask |
| 3 | Router (default gateway) | Default Gateway |
| 6 | DNS servers | DNS Servers |
| 12 | Host name | The name the client tells the server (shows in the router's client list) |
| 15 | Domain name | Connection-specific DNS Suffix |
| 28 | Broadcast address | ifconfig broadcast |
| 42 | NTP servers | Time sync |
| 43 | Vendor-specific | Wi-Fi controller discovery, phones, PXE |
| 44 / 46 | WINS servers / NetBIOS node type | Node Type in ipconfig /all |
| 50 | Requested IP address | Client asks for its previous address |
| 51 | Lease time | Lease Obtained / Expires |
| 53 | Message type | Discover, Offer, Request, Decline, ACK, NAK, Release, Inform |
| 54 | Server identifier | DHCP Server |
| 55 | Parameter request list | What the client wants; differs by OS and is used for fingerprinting |
| 60 / 61 | Vendor class / client identifier | How the server recognises the client; option 61 defaults to the MAC on most clients |
| 66 / 67 | TFTP server / boot file | PXE network boot |
| 77 | User class | ipconfig /setclassid |
| 81 | Client FQDN | Dynamic DNS registration |
| 119 | Domain search list | DNS Suffix Search List |
| 121 | Classless static routes | Extra routes pushed to clients; overrides option 3 on clients that support it |
| 150 | TFTP servers (Cisco) | IP phones |
| 252 | WPAD proxy URL | Automatic proxy discovery; a classic abuse vector on untrusted networks |
macOS shows every option it received with ipconfig getpacket en0; Linux with dhclient keeps them in /var/lib/dhcp/dhclient.leases; networkctl status and nmcli device show list the important ones; Windows shows only the ones it renders in ipconfig /all, but the full set is in the DHCP client event log.
Reservations vs static addresses
A reservation (static lease) is a server-side rule: this MAC or client ID always gets this address. The device remains a normal DHCP client. A static address is configured on the device, and the server knows nothing about it. Reservations win on almost every count: one place to manage, no conflicts as long as the reserved address is outside (or excluded from) the pool, gateway and DNS changes propagate, and the device still works elsewhere. Static addresses are for the DHCP server itself, the router, and equipment that must work when DHCP is down. How to do either →
Relay agents and VLANs
DISCOVER is a broadcast, so it stays within one VLAN. On a network with several subnets, each router interface runs a DHCP relay (Cisco ip helper-address, Linux dhcrelay, most firewalls) that forwards the broadcast as unicast to a central server, filling in the giaddr field so the server knows which subnet to allocate from. A client that gets an address from the wrong subnet, or none at all, on a corporate network is usually a missing or wrong helper address, or a switch port in the wrong VLAN.
Rogue and duplicate servers
Any device answering DISCOVER can hand out addresses, and clients take the first offer. A consumer router plugged in LAN-to-LAN, a phone's USB tethering, Windows Internet Connection Sharing, a NAS with a "DHCP server" toggle, VMware's VMnet DHCP bridged onto the LAN, or a deliberate attacker all cause the same thing: some devices get the wrong subnet, gateway or DNS. Find it with ipconfig /all (DHCP Server line) and the ARP table, or sudo nmap --script broadcast-dhcp-discover, which lists every server that answers. Managed switches offer DHCP snooping, which drops server replies from untrusted ports. Diagnosis steps →
DHCPv6 and SLAAC
IPv6 has two mechanisms. SLAAC: the router advertises a prefix (Router Advertisement, part of NDP) and each host builds its own address; DNS can come in the RA too (RDNSS option). DHCPv6: a server hands out addresses (stateful) or just options (stateless), on UDP 546/547, identified by DUID rather than MAC. Home routers use SLAAC; enterprises often use stateful DHCPv6 for logging. The RA flags decide: M (managed) = use DHCPv6 for addresses, O (other) = use DHCPv6 for options only. Windows honours both; Android ignores DHCPv6 entirely. Prefix delegation (DHCPv6-PD) is how your router obtains a /56 from the ISP to subdivide. ipconfig /renew6, ipconfig getv6packet en0 and ip -6 addr (look for dynamic) show the DHCPv6 side. IPv6 page →
Running your own DHCP server
| Server | Where | Notes |
|---|---|---|
| Your router | Everywhere | Fine for homes; limited reservations and no logging on cheap models |
| dnsmasq | Linux, OpenWrt, Pi-hole | DHCP and DNS in one small daemon; dhcp-range=192.168.1.100,192.168.1.199,24h, dhcp-host=8c:16:45:3a:9b:2d,printer,192.168.1.20 |
| Kea | Linux | ISC's modern server; JSON config, hooks, HA. ISC DHCP (dhcpd) reached end of life in 2022 |
| Windows Server DHCP role | Windows Server | Integrated with AD and DNS; PowerShell Get-DhcpServerv4Lease, Add-DhcpServerv4Reservation |
| pfSense / OPNsense | Firewalls | Kea or ISC underneath with a GUI |
| Windows ICS / Hyper-V / VMware | Desktops | Built-in mini servers for virtual networks; a common source of rogue offers if bridged |
Whichever you run, the rules are the same: one server per subnet (or a deliberate split scope), reservations outside the pool, lease times that match how transient the clients are (hours for guests, days for offices), and a log you can read when someone asks "who had 192.168.1.77 at 3 pm yesterday".