Skip to main content
RunBook Academy

VyOSXLVI · DHCP ServicesDHCP

DHCPv4 relay — forwarding across segments, giaddr, the relay loop failure mode

Advanced⏱ ~20 minset service dhcp-relayshow dhcp relay statustcpdump -i eth0 port 67 or port 68 -vvvyos

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

Not yet marked complete on this device.

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.10 and listen-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 sets giaddr to its own IP on the upstream-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 eth0 as unicast to 203.0.113.53 with giaddr set
  • DHCPOFFER arriving on eth0 unicast from the server
  • DHCPOFFER leaving on eth1.10 unicast (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), not 0.0.0.0 (the client).
  • Destination IP is 203.0.113.53 (the server), not 255.255.255.255 (broadcast).
  • giaddr is 203.0.113.1 (the relay).
  • Option 82 carries Circuit-Id eth1.10 and Remote-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 giaddr does 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 eth0 instead of eth1.10. Hosts on eth1.10 broadcast 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.10 and 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-Firewall covers 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

  1. Q1. What does the `giaddr` field in a DHCP relay-forwarded packet identify?

  2. Q2. A DHCPv4 relay loop terminates naturally because the relay drops packets after 16 hops.

  3. 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.

  4. 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.