Files
dhcp-wireshark-course/modules/02-dhcp-message-flow.md

27 KiB

Module 2: DHCP Message Flow (DORA)

Nav: ← Module 1 | Course Home | Module 3 →


Overview

Every time a device connects to a network and receives an IP address "automatically," a precisely choreographed four-message exchange takes place behind the scenes. This exchange — Discover, Offer, Request, Acknowledge — is the DORA process, and it is the beating heart of DHCP (Dynamic Host Configuration Protocol, RFC 2131).

Most engineers know that DHCP "gives out IP addresses." Far fewer can open a packet capture, identify each DORA message, trace the transaction ID across all four packets, and explain exactly which fields changed between the Request and the Acknowledge. That gap is what separates a technician who reboots things from an engineer who fixes them.

In this module, you will build a dedicated CML lab topology with a Cisco IOS DHCP server and a Linux client, capture a complete DORA exchange in Wireshark, and dissect every field in every packet. You will also examine what happens after the initial lease — the T1 and T2 renewal timers, the rebinding process, and the DHCP Release message. By the end, you will be able to read a DHCP capture the way a cardiologist reads an EKG: with precision and confidence.

Estimated time: ~2 hours (reading + labs)

Prerequisites: Module 1 completed. Wireshark installed. CML lab environment accessible.


2.1 — The DORA Process: Conceptual Overview

DHCP uses a client-server model carried over UDP. The client transmits on port 68, and the server listens on port 67. Because the client starts with no IP address, the first two messages are broadcast at Layer 3 (255.255.255.255) and Layer 2 (ff:ff:ff:ff:ff:ff).

The four messages form a predictable sequence:

Step Message Direction Source IP Destination IP UDP Ports
1 DHCP Discover Client → Broadcast 0.0.0.0 255.255.255.255 68 → 67
2 DHCP Offer Server → Broadcast/Unicast Server IP 255.255.255.255 67 → 68
3 DHCP Request Client → Broadcast 0.0.0.0 255.255.255.255 68 → 67
4 DHCP Acknowledge Server → Broadcast/Unicast Server IP 255.255.255.255 67 → 68

Why is the Request broadcast? The client may have received Offers from multiple DHCP servers. By broadcasting its Request (which includes the chosen server's identifier), it simultaneously accepts one Offer and implicitly declines all others. Every server on the segment sees the Request and knows whether it was selected.

Transaction ID (xid) — The Thread That Ties DORA Together

Every DORA exchange is correlated by a 32-bit Transaction ID (xid). The client generates a random xid in the Discover message, and all four packets in that exchange carry the same value. When you are troubleshooting in a busy capture with dozens of clients, filtering on xid is how you isolate a single client's conversation. We will do exactly this in Lab 2.2.


2.2 — CML Lab Setup

Topology

Build the following topology in Cisco Modeling Labs. This is the same base topology from Module 1, with DHCP-specific configuration added.

┌─────────────────┐          ┌──────────────┐          ┌─────────────────┐
│   DHCP-Server   │──────────│   Switch-1   │──────────│   Linux-Client  │
│  (IOSv / CSR)   │  Gi0/1   │  (IOSvL2)    │  Gi0/2   │  (Ubuntu/Alpine)│
│  10.1.1.1/24    │          │              │          │  DHCP Client    │
└─────────────────┘          └──────────────┘          └─────────────────┘
                                    │
                              (SPAN / Mirror
                               to Wireshark)

You need three nodes:

  1. DHCP-Server — An IOSv or CSR1000v router acting as the DHCP server.
  2. Switch-1 — An IOSvL2 switch connecting server and client.
  3. Linux-Client — An Ubuntu or Alpine Cloud node configured to use DHCP.

Wireshark capture point: Configure a SPAN session on Switch-1, or run Wireshark directly on the Linux client's interface. In CML, the simplest method is capturing on the Linux client's ens2 (or eth0) interface using tcpdump, then opening the .pcap in Wireshark.

DHCP Server Configuration (IOSv)

! Enter global config
configure terminal

! Define the DHCP pool
ip dhcp pool LAB-POOL
 network 10.1.1.0 255.255.255.0
 default-router 10.1.1.1
 dns-server 8.8.8.8 8.8.4.4
 lease 0 2 0
 ! Lease: 0 days, 2 hours, 0 minutes (short for lab observation)

! Exclude the server's own address from the pool
ip dhcp excluded-address 10.1.1.1 10.1.1.10

! Assign the server interface
interface GigabitEthernet0/1
 ip address 10.1.1.1 255.255.255.0
 no shutdown

end
write memory

Lab tip: We set a 2-hour lease intentionally. Short leases let you observe renewal behavior (T1 at 50% = 1 hour, T2 at 87.5% = 1 hour 45 minutes) within a single lab session.

Linux Client Configuration

On the Ubuntu/Alpine client, release any existing lease and force a new DORA exchange:

# Release current lease (if any)
sudo dhclient -r ens2

# Request a new lease (triggers full DORA)
sudo dhclient -v ens2

The -v (verbose) flag prints each DHCP message as it is sent/received — useful for correlating CLI output with your Wireshark capture.

Starting the Capture

On the Linux client (or via CML's packet capture feature):

# Start capture on the client interface, write to file
sudo tcpdump -i ens2 -w /tmp/dhcp-dora.pcap port 67 or port 68

Then trigger the DORA by running dhclient. Stop the capture with Ctrl+C and transfer the .pcap to your workstation for analysis in Wireshark.


2.3 — DHCP Packet Structure: Field-by-Field Breakdown

Every DHCP message rides inside a UDP datagram, which rides inside an IP packet, which rides inside an Ethernet frame. The DHCP payload itself follows the BOOTP message format (DHCP is built on top of BOOTP, RFC 951). Here is the structure:

BOOTP/DHCP Header Fields

Field Size Description Example Value (Discover)
op 1 byte Operation code. 1 = BOOTREQUEST (client → server), 2 = BOOTREPLY (server → client) 1
htype 1 byte Hardware address type. 1 = Ethernet (10 Mb) 1
hlen 1 byte Hardware address length. 6 for MAC addresses 6
hops 1 byte Relay agent hop count. Set to 0 by client, incremented by each relay agent 0
xid 4 bytes Transaction ID. Random value chosen by client, used to match requests and replies 0x3903F326
secs 2 bytes Seconds elapsed since client began the address acquisition process 0
flags 2 bytes Bit 0 = Broadcast flag. If set, server must broadcast its reply 0x0000
ciaddr 4 bytes Client IP address. Only filled if client is in BOUND, RENEW, or REBINDING state 0.0.0.0
yiaddr 4 bytes "Your" IP address. The address the server is assigning to the client 0.0.0.0
siaddr 4 bytes Next server IP address (used in BOOTP/PXE boot scenarios) 0.0.0.0
giaddr 4 bytes Relay agent IP address. Set by relay agents, not by clients or servers directly 0.0.0.0
chaddr 16 bytes Client hardware (MAC) address. Padded with zeros to 16 bytes 00:50:79:66:68:01
sname 64 bytes Optional server hostname (empty)
file 128 bytes Boot filename (PXE). Often empty in standard DHCP (empty)
options Variable DHCP options (Option 53 = message type, Option 55 = parameter request list, etc.) See Section 2.4

Key insight for captures: In a Discover, ciaddr, yiaddr, siaddr, and giaddr are all 0.0.0.0. Watch these fields change as you move through Offer → Request → Acknowledge. The yiaddr in the Offer is the server's proposed address. The yiaddr in the ACK is the confirmed assignment.


2.4 — Dissecting Each DORA Message in Wireshark

Open your dhcp-dora.pcap in Wireshark. Apply this display filter to isolate DHCP traffic:

dhcp || bootp

Filter note: In older Wireshark versions (< 3.0), DHCP traffic is decoded under the bootp protocol name. In modern Wireshark (3.x+), the dissector is labeled dhcp, but bootp still works as an alias. Throughout this course, we use both interchangeably, and we will call out version-specific filters where they differ.

You should see exactly four packets. Let's walk through each one.


Message 1: DHCP Discover

What the client is saying: "I need an IP address. Is anyone out there?"

Wireshark display filter:

dhcp.option.dhcp == 1

Key fields to examine:

Field Value Why It Matters
Ethernet Dst ff:ff:ff:ff:ff:ff Layer 2 broadcast — client has no idea where the server is
IP Src 0.0.0.0 Client has no IP address yet
IP Dst 255.255.255.255 Layer 3 limited broadcast
UDP Src Port 68 DHCP client port
UDP Dst Port 67 DHCP server port
op 1 (BOOTREQUEST) Client-to-server direction
xid 0x3903F326 (example) Note this value — it ties all four packets together
ciaddr 0.0.0.0 Client has no current address
yiaddr 0.0.0.0 Server hasn't proposed one yet
chaddr 00:50:79:66:68:01 Client's MAC address
Option 53 1 (DHCP Discover) Message type identifier
Option 55 1, 3, 6, 15, 28, 51 Parameter Request List — what the client wants
Option 61 Client MAC Client identifier (used by server to track leases)

In the Wireshark packet detail pane, expand Dynamic Host Configuration Protocol (Discover) and inspect each option. Option 55 tells the server which parameters the client is requesting (subnet mask, default gateway, DNS servers, domain name, broadcast address, lease time).


Message 2: DHCP Offer

What the server is saying: "I have 10.1.1.11 available for you. Here are the details."

Wireshark display filter:

dhcp.option.dhcp == 2

Key fields to examine:

Field Value Why It Matters
Ethernet Dst ff:ff:ff:ff:ff:ff Broadcast (unless Broadcast flag = 0 and server supports unicast to MAC)
IP Src 10.1.1.1 The DHCP server's address
IP Dst 255.255.255.255 Broadcast reply
op 2 (BOOTREPLY) Server-to-client direction
xid 0x3903F326 Same xid as the Discover — confirms this is a response to our request
yiaddr 10.1.1.11 The IP address being offered to the client
siaddr 10.1.1.1 Next server (DHCP server address in this case)
Option 53 2 (DHCP Offer) Message type
Option 1 255.255.255.0 Subnet Mask
Option 3 10.1.1.1 Default Gateway (Router)
Option 6 8.8.8.8, 8.8.4.4 DNS Servers
Option 51 7200 (seconds) Lease Time (2 hours = 7200 seconds)
Option 54 10.1.1.1 Server Identifier — critical for the Request message

Important: The client has NOT accepted this address yet. The Offer is a proposal. The client must explicitly Request it in the next step.


Message 3: DHCP Request

What the client is saying: "I accept the offer from 10.1.1.1. Please confirm 10.1.1.11 for me."

Wireshark display filter:

dhcp.option.dhcp == 3

Key fields to examine:

Field Value Why It Matters
IP Src 0.0.0.0 Client still does not own the address — not until the ACK
IP Dst 255.255.255.255 Broadcast — so all DHCP servers see this
op 1 (BOOTREQUEST) Client-to-server direction
xid 0x3903F326 Same transaction ID
ciaddr 0.0.0.0 Client still has no confirmed address
Option 53 3 (DHCP Request) Message type
Option 50 10.1.1.11 Requested IP Address — the address from the Offer
Option 54 10.1.1.1 Server Identifier — which server's Offer the client is accepting

Why Option 54 matters: If multiple DHCP servers sent Offers, the Server Identifier in the Request tells every server on the segment whether it was selected. Non-selected servers return their offered addresses to their pools.


Message 4: DHCP Acknowledge (ACK)

What the server is saying: "Confirmed. 10.1.1.11 is yours for 7200 seconds. Here is your full configuration."

Wireshark display filter:

dhcp.option.dhcp == 5

Key fields to examine:

Field Value Why It Matters
IP Src 10.1.1.1 Server's IP
IP Dst 255.255.255.255 Broadcast (or unicast if Broadcast flag was not set)
op 2 (BOOTREPLY) Server-to-client
xid 0x3903F326 Same transaction — all four match
yiaddr 10.1.1.11 The confirmed IP address assignment
Option 53 5 (DHCP ACK) Message type
Option 51 7200 Lease Time
Option 58 3600 T1 Renewal Time (50% of lease)
Option 59 6300 T2 Rebinding Time (87.5% of lease)
Option 1 255.255.255.0 Subnet Mask
Option 3 10.1.1.1 Default Gateway
Option 6 8.8.8.8, 8.8.4.4 DNS Servers

After receiving the ACK, the client applies the IP configuration to its interface and transitions to the BOUND state. The lease clock starts ticking.


2.5 — Essential Wireshark Display Filters for DHCP

Mastering filters is the difference between drowning in packets and finding the needle in the haystack. Here are the filters you need for DHCP analysis:

Core Filters

Filter Expression What It Shows
dhcp All DHCP traffic
bootp Same as above (legacy alias)
udp.port == 67 || udp.port == 68 DHCP by port number (works even if dissector fails)
dhcp.option.dhcp == 1 Discover messages only
dhcp.option.dhcp == 2 Offer messages only
dhcp.option.dhcp == 3 Request messages only
dhcp.option.dhcp == 5 ACK messages only
dhcp.option.dhcp == 6 NAK messages only
dhcp.option.dhcp == 7 Release messages only
dhcp.option.dhcp == 8 Inform messages only

Targeted Analysis Filters

Filter Expression Use Case
dhcp.id == 0x3903F326 Isolate a single DORA exchange by transaction ID
dhcp.hw.mac_addr == 00:50:79:66:68:01 All DHCP traffic for a specific client (by MAC)
dhcp.option.requested_ip_address == 10.1.1.11 Requests for a specific IP address
dhcp.option.dhcp_server_id == 10.1.1.1 Traffic involving a specific DHCP server
dhcp.option.ip_address_lease_time Packets containing lease time information
bootp.option.type == 53 Filter by the presence of the DHCP Message Type option
dhcp.option.dhcp == 6 DHCP NAK — something went wrong

Combination Filters

# Show only Discover and Offer (first half of DORA)
dhcp.option.dhcp == 1 || dhcp.option.dhcp == 2

# Show all traffic for a specific client's full DORA exchange
dhcp.hw.mac_addr == 00:50:79:66:68:01 && (dhcp.option.dhcp == 1 || dhcp.option.dhcp == 2 || dhcp.option.dhcp == 3 || dhcp.option.dhcp == 5)

# Show NAKs and Declines (trouble indicators)
dhcp.option.dhcp == 6 || dhcp.option.dhcp == 4

2.6 — Lease Lifecycle: Renewal, Rebinding, and Release

The DORA exchange is only the beginning of a lease's life. After the client enters the BOUND state, three timers govern what happens next.

The Three Timers

Timer Default Trigger Behavior
T1 (Renewal) 50% of lease Client enters RENEWING state Client sends unicast Request directly to the leasing server
T2 (Rebinding) 87.5% of lease Client enters REBINDING state Client broadcasts Request to any server (original may be down)
Lease Expiration 100% of lease Lease dies Client must stop using the IP and restart with Discover

For our 2-hour (7200s) lab lease:

  • T1 fires at 1 hour (3600s) → client unicasts a renewal Request to 10.1.1.1
  • T2 fires at 1h 45m (6300s) → if T1 renewal failed, client broadcasts a Request
  • Lease expires at 2 hours (7200s) → client releases the address and goes back to Discover

Renewal (T1) in Wireshark

When T1 fires, you will see a two-packet exchange (not four):

  1. DHCP Request (unicast from client to server)
  2. DHCP ACK (unicast from server to client)

Key difference from the initial DORA Request:

  • ciaddr is now populated with the client's current IP (10.1.1.11) — because the client is in BOUND state and already owns the address.
  • The Request is unicast, not broadcast.
  • There is no Discover or Offer — the client already knows which server it wants.

Filter to isolate renewals:

dhcp.option.dhcp == 3 && ip.dst != 255.255.255.255

This catches Request messages sent as unicast — which are renewals, not initial requests.

Rebinding (T2) in Wireshark

If the T1 renewal fails (server down, unreachable), the client enters the REBINDING state at T2. The rebinding Request looks identical to a renewal Request, except:

  • It is broadcast (255.255.255.255), not unicast.
  • ciaddr is still populated (client still holds the lease).
  • Any DHCP server on the segment can respond.

DHCP Release

When a client gracefully disconnects (shutdown, dhclient -r, ipconfig /release), it sends a DHCP Release message:

dhcp.option.dhcp == 7
Field Value
op 1 (BOOTREQUEST)
ciaddr 10.1.1.11 (the address being released)
Option 53 7 (Release)
Option 54 10.1.1.1 (which server granted the lease)

The Release is unicast directly to the server. After sending it, the client immediately deconfigures its interface. The server returns the address to the pool.

Troubleshooting note: Not all clients send a Release on disconnect. If a laptop is closed or a VM is destroyed, the lease simply expires at the server after the full lease duration. This is normal behavior, not a bug.

DHCP NAK (Negative Acknowledge)

If the server cannot honor a Request — for example, the client is requesting an address from a different subnet after being moved — the server responds with a DHCP NAK (Option 53 = 6). The client must discard its current address and restart the DORA process from Discover.

Filter:

dhcp.option.dhcp == 6

Seeing NAKs in a capture is always worth investigating. Common causes:

  • Client moved to a different subnet but is requesting its old address.
  • DHCP pool has been reconfigured or deleted.
  • Lease was manually cleared from the server.

2.7 — Verifying DHCP on the Server (IOS CLI)

After completing the DORA exchange, verify the lease on the server side:

! Show all active DHCP bindings
show ip dhcp binding

! Expected output:
! IP address       Client-ID/              Lease expiration        Type
!                  Hardware address
! 10.1.1.11        0100.5079.6668.01       Mar 01 2026 04:00 PM   Automatic

! Show DHCP server statistics
show ip dhcp server statistics

! Show pool configuration
show ip dhcp pool LAB-POOL

! Debug DHCP events in real time (use carefully)
debug ip dhcp server events

Cross-reference the show ip dhcp binding output with your Wireshark capture. The MAC address in the binding table should match the chaddr in your DORA packets.


Hands-On Labs

Lab 2.1 — Capture a Full DORA Exchange

Objective: Capture all four DORA messages and verify the transaction ID is consistent.

Steps:

  1. Start Wireshark (or tcpdump) on the Linux client's network interface.
  2. Release any existing lease:
    sudo dhclient -r ens2
    
  3. Request a new lease:
    sudo dhclient -v ens2
    
  4. Stop the capture.
  5. Open the capture in Wireshark and apply the filter: dhcp
  6. Verify you see exactly four packets: Discover → Offer → Request → ACK.
  7. For each packet, expand the DHCP layer and note the xid value. Confirm all four share the same xid.

Deliverable: Screenshot of the Wireshark packet list showing all four DORA messages with the xid column visible.

Adding the xid column: Right-click any column header → Column Preferences → Add → Title: Transaction ID, Fields: dhcp.id, Type: Custom. This adds a permanent column that makes DORA correlation effortless.


Lab 2.2 — Transaction ID Correlation

Objective: Use the transaction ID to isolate one client's exchange in a noisy capture.

Steps:

  1. If you have multiple clients in your lab, start captures on all of them simultaneously and request DHCP leases on each.
  2. Open the merged capture file. You will see interleaved DORA exchanges.
  3. Click on any DHCP Discover packet. In the packet detail pane, find Transaction ID under the DHCP section. Note the hex value (e.g., 0x3903F326).
  4. Apply the display filter:
    dhcp.id == 0x3903F326
    
  5. Verify that only four packets remain — the complete DORA exchange for that one client.
  6. Repeat with a different xid to isolate another client's exchange.

Deliverable: Two filtered views, each showing a clean four-packet DORA sequence for different clients.


Lab 2.3 — Field Comparison Across DORA Messages

Objective: Build a comparison table showing how key fields change across the four DORA messages.

Steps:

  1. Using your DORA capture, fill in the following table by inspecting each packet:
Field Discover Offer Request ACK
op ? ? ? ?
xid ? ? ? ?
ciaddr ? ? ? ?
yiaddr ? ? ? ?
siaddr ? ? ? ?
giaddr ? ? ? ?
chaddr ? ? ? ?
Option 53 ? ? ? ?
Option 50 ? ? ? ?
Option 54 ? ? ? ?
  1. Answer these questions:
    • In which message does yiaddr first get populated?
    • Which messages have op = 1 and which have op = 2?
    • Why is ciaddr still 0.0.0.0 in the Request?
    • When does the client first have a usable IP address?

Expected answers:

  • yiaddr is first populated in the Offer (message 2).
  • op = 1 in Discover and Request (client → server). op = 2 in Offer and ACK (server → client).
  • ciaddr is 0.0.0.0 in the Request because the client does not yet own the address — the ACK has not been received.
  • The client can use the IP address only after receiving the ACK (message 4).

Lab 2.4 — Observe a Lease Renewal

Objective: Capture the T1 renewal exchange.

Steps:

  1. With the 2-hour lease from Lab 2.1, start a long-running capture:
    sudo tcpdump -i ens2 -w /tmp/dhcp-renewal.pcap port 67 or port 68
    
  2. Wait approximately 1 hour (or set a shorter lease, e.g., lease 0 0 10 for a 10-minute lease with T1 at 5 minutes).
  3. After the renewal triggers, stop the capture.
  4. Open in Wireshark and apply:
    dhcp.option.dhcp == 3 && ip.dst != 255.255.255.255
    
  5. You should see the unicast renewal Request. Find the matching ACK.
  6. Compare the renewal Request to the initial DORA Request:
    • Is ciaddr populated?
    • Is the packet unicast or broadcast?
    • Is Option 50 (Requested IP) present?

Shortcut for lab environments: To avoid waiting, set the lease to 10 minutes: lease 0 0 10. T1 will fire at 5 minutes, giving you a quick capture cycle.


Lab 2.5 — Trigger and Capture a DHCP Release

Objective: Capture and analyze a DHCP Release message.

Steps:

  1. Start a capture on the client interface.
  2. Release the lease:
    sudo dhclient -r ens2
    
  3. Stop the capture and open in Wireshark.
  4. Apply the filter: dhcp.option.dhcp == 7
  5. Inspect the Release packet:
    • What is ciaddr?
    • What is Option 54 (Server Identifier)?
    • Is this packet unicast or broadcast?
  6. Verify on the server:
    show ip dhcp binding
    
    The released address should no longer appear (or will show as expired).

DHCP State Machine Summary

The client moves through these states during and after DORA:

        ┌──────────┐
        │   INIT   │ ─── Client starts, sends Discover
        └────┬─────┘
             │
             ▼
      ┌──────────────┐
      │  SELECTING   │ ─── Waiting for Offers; picks one, sends Request
      └──────┬───────┘
             │
             ▼
      ┌──────────────┐
      │  REQUESTING  │ ─── Sent Request, waiting for ACK/NAK
      └──────┬───────┘
             │ ACK received
             ▼
      ┌──────────────┐
      │    BOUND     │ ─── Client has a valid lease. Timers running.
      └──┬───────┬───┘
         │       │
    T1   │       │ T2
         ▼       ▼
   ┌──────────┐  ┌─────────────┐
   │ RENEWING │  │ REBINDING   │
   │ (unicast)│  │ (broadcast) │
   └────┬─────┘  └──────┬──────┘
        │ ACK           │ ACK
        └──────┬────────┘
               ▼
        ┌──────────┐
        │  BOUND   │ ─── Lease renewed, timers reset
        └──────────┘

If no ACK is received by lease expiration → back to INIT → full DORA restart.


Module Summary

Concept Key Takeaway
DORA sequence Discover → Offer → Request → ACK. Always in this order for new leases.
Transaction ID (xid) Links all four messages. Use dhcp.id == 0xVALUE to filter.
op code 1 = client → server, 2 = server → client.
yiaddr Empty in Discover/Request, populated in Offer/ACK.
ciaddr Empty during initial DORA, populated during renewals.
T1 / T2 timers Renewal at 50%, rebinding at 87.5%. Key to understanding lease lifecycle.
Release Unicast message from client to server. Not always sent (ungraceful disconnects).
NAK Server rejects the Request. Client must restart with Discover.

What's Next

In Module 3: DHCP Options, we go deeper into the options field — the most powerful and flexible part of the DHCP message. You will learn how to decode Option 43 (vendor-specific), Option 82 (relay information), Option 150 (TFTP server for IP phones), and how to use Wireshark to identify misconfigured or missing options that cause real-world failures.


Nav: ← Module 1 | Course Home | Module 3 →