DHCPv4 relay — forwarding across segments, giaddr, the relay loop failure mode
What you'll learn
- Explain the DHCP relay mechanism: giaddr, hop count, option 82
- Configure `service dhcp-relay` on VyOS to forward DHCP across segments
- Recognise the production failure modes: relay loops, giaddr mismatches, server unreachable
- Validate the relay with packet captures and DHCP relay statistics
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15
A DHCP relay forwards DHCP broadcasts from a client segment to a DHCP server on a different segment. DHCP is a broadcast protocol, but broadcasts do not cross routers; a relay agent on the router intercepts the broadcast, replaces the broadcast destination with the configured server’s unicast IP, and forwards the message.
This lesson is the canonical reference for the DHCPv4 relay on VyOS 1.5 LTS. It covers the relay mechanism, the giaddr field, the option 82 insertion, the configuration tree under service dhcp-relay, and the production failure modes — most importantly the relay loop where two routers forward DHCP to each other indefinitely.
The relay problem
flowchart LR
C["Client<br/>broadcasts DHCPDISCOVER"] --> R1["Router 1<br/>no DHCP server"]
R1 -.->|broadcast dropped at L3| BROADCAST["Broadcasts do not<br/>cross routers"]
R1 -->|relay as unicast| S["DHCP server<br/>different segment"]
S -->|unicast DHCPOFFER| R1
R1 -->|unicast| C
The diagram shows why a relay is necessary: DHCP clients broadcast because they have no IP address. Routers drop broadcasts at L3 by default. Without a relay, a host on a remote LAN cannot reach the central DHCP server. The relay intercepts the broadcast on the LAN interface, encapsulates it as unicast, and forwards it to the server.
How the relay works — the giaddr field
The relay’s role is to make the broadcast look like a unicast request from a known IP. The relay sets the giaddr (gateway IP address) field in the BOOTP/DHCP packet to its own IP address on the relay interface. The server uses giaddr to identify the relay and the subnet:
sequenceDiagram
autonumber
participant C as Host
participant R as Relay
participant S as Server
C->>R: DHCPDISCOVER (broadcast)
Note over R: relay sets giaddr = R-on-LAN<br/>relay sets hop count = 1<br/>relay optionally adds option 82
R->>S: DHCPDISCOVER (unicast to server)
Note over S: server selects subnet<br/>based on giaddr<br/>server inserts option 82
S-->>R: DHCPOFFER (unicast to giaddr)
R-->>C: DHCPOFFER (unicast or broadcast)
C->>R: DHCPREQUEST
R->>S: DHCPREQUEST
S-->>R: DHCPACK
R-->>C: DHCPACK
The server uses giaddr to identify the relay and the source subnet. When the server replies, the reply is unicast to giaddr (the relay’s address), not to the client (which still has no IP). The relay then forwards the reply to the client.
Configuring the relay on VyOS
configure
set service dhcp-relay listen-interface eth1.10
set service dhcp-relay listen-interface eth1.20
set service dhcp-relay upstream-interface eth0
set service dhcp-relay upstream-interface eth0 address '203.0.113.53'
set service dhcp-relay relay-agents-packets 'forward'
commit
save
The configuration declares:
listen-interface eth1.10andlisten-interface eth1.20— the interfaces where client broadcasts arrive. The relay listens on these interfaces.upstream-interface eth0— the interface the relay uses to reach the server. The relay setsgiaddrto its own IP on theupstream-interface.upstream-interface eth0 address '203.0.113.53'— the server’s unicast IP. Multiple addresses can be configured for redundancy.relay-agents-packets forward— relay-agent option 82 packets are forwarded (not dropped).
After commit, the relay is active on eth1.10 and eth1.20. Hosts on those VLANs broadcast; the relay picks up the broadcasts, sets giaddr to its address on eth0, and forwards to 203.0.113.53.
Option 82 — Relay Agent Information
Option 82 (RFC 3046) is the relay’s information about the circuit the request arrived on. The relay inserts option 82 with two sub-options:
- Sub-option 1 (circuit ID) — identifies the interface or VLAN the request arrived on (e.g.,
eth1.10) - Sub-option 2 (remote ID) — identifies the relay (e.g., the relay’s hostname or IP)
set service dhcp-relay listen-interface eth1.10 option 82 circuit-id 'eth1.10'
set service dhcp-relay listen-interface eth1.10 option 82 remote-id 'R1-EDGE'
The server uses option 82 to distinguish requests from different relays on different circuits, even when both relays are on the same upstream segment. The server can apply per-circuit DHCP policies (different leases for different VLANs, for example).
How the result is validated
show dhcp relay status
show dhcp relay statistics
tcpdump -i eth0 -n port 67 or port 68 -vv
tcpdump -i eth1.10 -n port 67 or port 68 -vv
show dhcp relay status shows the configured interfaces, the upstream addresses, and the relay state. show dhcp relay statistics shows the message counters. The two tcpdumps show the relay’s view of the world: the LAN side shows client broadcasts; the WAN side shows unicast to the server.
A working relay has:
- Client DHCPDISCOVER arriving on
eth1.10 - DHCPDISCOVER leaving on
eth0as unicast to203.0.113.53withgiaddrset - DHCPOFFER arriving on
eth0unicast from the server - DHCPOFFER leaving on
eth1.10unicast (or broadcast) to the client
vyos@R1:~$ show dhcp relay status
Interface State Server
--------------- ------- ----------------
eth1.10 active 203.0.113.53
eth1.20 active 203.0.113.53
eth0 upstream
Capturing the relayed exchange
A packet capture on the upstream interface shows the relay in action:
vyos@R1:~$ tcpdump -i eth0 -n port 67 or port 68 -vv
12:00:01.234 IP 203.0.113.1.67 > 203.0.113.53.67: BOOTP/DHCP, Request
giaddr 203.0.113.1
Option 53, length 1: DHCP Discover
Option 82, length 18: Relay-Agent-Information
Circuit-Id eth1.10
Remote-Id R1-EDGE
12:00:01.245 IP 203.0.113.53.67 > 203.0.113.1.67: BOOTP/DHCP, Reply
Option 53, length 1: DHCP Offer
yiaddr 192.0.2.50
12:00:01.256 IP 203.0.113.1.67 > 203.0.113.53.67: BOOTP/DHCP, Request
giaddr 203.0.113.1
Option 53, length 1: DHCP Request
12:00:01.267 IP 203.0.113.53.67 > 203.0.113.1.67: BOOTP/DHCP, Reply
Option 53, length 1: DHCP ACK
Notice:
- Source IP is
203.0.113.1(the relay), not0.0.0.0(the client). - Destination IP is
203.0.113.53(the server), not255.255.255.255(broadcast). giaddris203.0.113.1(the relay).- Option 82 carries
Circuit-Id eth1.10andRemote-Id R1-EDGE.
The client never appears on the wire at the upstream side; the relay encapsulates the client’s broadcast as a unicast from its own IP.
How it fails
The production failure modes a routing engineer must recognise:
- Server unreachable. The configured server IP does not respond. The relay forwards DHCPDISCOVER to a black hole. Clients never receive DHCPOFFER.
- giaddr mismatch. The server receives the relay’s request but the
giaddrdoes not match any subnet on the server. The server silently drops the request. - Relay loop. Two routers are configured to relay to each other. Each relay’s request is forwarded to the other relay, which forwards it back. Hop count increments on each loop; the request eventually hits the hop-count limit (16 by default) and is dropped.
- Option 82 dropped by server. The relay inserts option 82, but the server drops it. The server sends DHCPOFFER but the client doesn’t recognise it (option 82 was malformed or stripped).
- Wrong listen interface. The relay is bound to
eth0instead ofeth1.10. Hosts oneth1.10broadcast but no relay listens. - Upstream firewall blocks UDP 67. A firewall between the relay and the server blocks UDP 67. The relay’s packets never reach the server.
Rollback
The recovery from a broken DHCP relay:
- Wrong server address:
delete service dhcp-relay upstream-interface eth0 address '203.0.113.53'and re-add the correct address. - Wrong listen interface:
delete service dhcp-relay listen-interface eth1.10and bind to the correct interface. - Relay loop: identify the second relay and break the loop by removing the upstream from one of them.
- Option 82 problem: drop option 82 at the relay with
set service dhcp-relay relay-agents-packets 'discard'or fix the server to accept it.
The VyOS configuration rollback (rollback N) restores the previous revision if the change breaks production.
Production discipline
Cross-course references
XLVI-VyOS-DHCP(vyos-xlvi-01-dhcp-server) covers the server-side DHCP configuration this lesson extends with the relay.XV-VyOS-VRFs(vyos-xv-02-vrf-config) covers the VRF configuration that may isolate the relay’s upstream traffic.XXXVII-VyOS-Firewallcovers the firewall rules that may affect the relay’s traffic.LII-VyOS-Troubleshoot(vyos-lii-04-subsystem-by-subsystem) covers the diagnostic methodology for relay failures.
Quiz
Knowledge check · 4 questions
Q1. What does the `giaddr` field in a DHCP relay-forwarded packet identify?
Q2. A DHCPv4 relay loop terminates naturally because the relay drops packets after 16 hops.
Q3. An operator configures a DHCPv4 relay on R1 with listen-interface eth1.10 and upstream-interface eth0 address 203.0.113.53. Hosts on eth1.10 broadcast DHCPDISCOVER. R1 forwards the relay's unicast to 203.0.113.53, but the server never replies with DHCPOFFER. tcpdump on eth0 shows the relay's packets leaving R1 with giaddr set correctly. What is the most likely cause?
The relay is correctly forwarding the client's DHCPDISCOVER to the server's unicast IP. The packets leave R1 with giaddr set correctly. The server never replies. The most likely cause is a firewall between R1 and the server that blocks UDP port 67, OR the server's IP address is wrong (typo), OR the server is unreachable on the routed path. The relay's job is done; the issue is on the path or at the server.
Q4. Two routers, R1 and R2, are connected via a transit segment. R1 has a DHCP relay on its LAN side with upstream pointing to R2's IP. R2 has a DHCP relay on its LAN side with upstream pointing to R1's IP. Clients on either LAN see no DHCP leases. What is happening and what is the fix?
R1 and R2 are configured as relays with upstreams pointing to each other. Client DHCPDISCOVER on R1's LAN is forwarded to R2 as a relay-forward; R2 receives it, sees it as a relay request, and forwards it back to R1 (because R2's upstream is R1). The packets loop, hop count increments, and after 16 hops the packets are dropped. Clients see no lease; operators see no DHCPOFFER.
Passing score: 75%. Answers are checked in this browser.