How to Configure DHCP Relay (ip helper-address) on Cisco (Step by Step)
A DHCP client that has no address yet can only shout. Its DHCP Discover is a broadcast (destination 255.255.255.255, UDP port 67), and a router will not forward broadcasts between subnets — that boundary is the whole point of a router. So the moment your DHCP server lives on a different subnet or VLAN than your clients, DHCP silently breaks: the Discover dies at the first router and no offer ever comes back. DHCP relay fixes this. You put `ip helper-address` on the router interface that faces the clients, and that interface becomes a relay agent: it catches the client broadcast and re-sends it as a unicast to your DHCP server, tagging it so the server knows which subnet the request came from. This guide walks the full path — how relay actually works, where the command goes and why, what the server needs on its end, and how to verify a real lease — then closes with the handful of mistakes that account for almost every broken relay.
Part of the DHCP learning hub
Step 1 — Understand what DHCP relay actually does
DHCP leasing (DORA: Discover, Offer, Request, Ack) starts with the client broadcasting because it has no IP address and no idea where the server is. The Discover goes to 255.255.255.255 on UDP 67. A router receiving that broadcast drops it — routers do not forward Layer 2/Layer 3 broadcasts, by design, so one chatty host can't flood the whole network. That is exactly why a client on VLAN 10 cannot reach a DHCP server sitting on the 10.20.20.0/24 network across a routed hop.
`ip helper-address` turns the receiving interface into a DHCP relay agent. When a client broadcast lands on that interface, the router rewrites it as a unicast IP packet aimed at the server address you configured and forwards it across the routed network like any normal traffic. The reply comes back to the relay, which hands it to the client.
The load-bearing detail is the giaddr (gateway IP address) field. When the relay forwards the Discover, it stamps giaddr with the IP address of the interface that received the broadcast — i.e., the client's default gateway. The server uses giaddr for two things: (1) to pick the pool whose network matches that subnet, and (2) to know where to send the Offer back. Keep giaddr in mind — every one of the common failures below is really a giaddr problem in disguise.
Step 2 — Lay out the topology and addressing
Use a clear split so the relay is obvious. In this lab:
- Clients live on VLAN 10 = 10.10.10.0/24. Their default gateway is the Layer 3 device's SVI at 10.10.10.1. This is the client-facing interface — the one that gets the helper.
- The DHCP server is at 10.20.20.10 on the 10.20.20.0/24 network, reachable across a routed hop (its gateway is 10.20.20.1).
- The relay (R1) routes between the two and is the clients' gateway (10.10.10.1). The server can be a Cisco router running the IOS DHCP server, or a real DHCP server host — the relay config is identical either way.
This is a clean Cisco Modeling Labs (CML) lab: IOSv/IOL for the routers or L3 switch, and either an IOS router with `ip address dhcp` or a small Linux host as the client. Note that CML is a virtual appliance (OVA/ISO) you run under a hypervisor such as VMware — it is not a desktop app, and VirtualBox is not a supported CML host; check Cisco's current CML page for version and node specifics. Packet Tracer will accept `ip helper-address` too, but it is a simulator, not real IOS.
Step 3 — Give the client-facing interface an IP (it is the default gateway)
The interface that faces the clients must be a Layer 3 interface with an address in the client subnet, because it is both the clients' default gateway and the source of the giaddr the server will key on. On a Layer 3 switch that is an SVI; make sure the VLAN exists and that the box is actually routing.
If you are doing router-on-a-stick instead of an L3 switch, the equivalent client-facing interface is the 802.1Q subinterface — put the address (and, in the next step, the helper) there.
! --- Option A: SVI on a Layer 3 switch ---
Switch(config)# ip routing
Switch(config)# vlan 10
Switch(config-vlan)# exit
Switch(config)# interface vlan 10
Switch(config-if)# ip address 10.10.10.1 255.255.255.0
Switch(config-if)# no shutdown
! --- Option B: router-on-a-stick subinterface ---
R1(config)# interface GigabitEthernet0/0/1.10
R1(config-subif)# encapsulation dot1Q 10
R1(config-subif)# ip address 10.10.10.1 255.255.255.0Step 4 — Add ip helper-address on the client-facing interface
Put the helper on the same interface you just addressed — the one clients broadcast into (their gateway). This is the single most common thing people get wrong, so be deliberate: the helper goes on the CLIENT side, never on the server-facing link.
You can list more than one `ip helper-address` on the interface for redundancy or to relay to multiple DHCP servers; the relay forwards the Discover to each. Be aware that `ip helper-address` is not DHCP-only — it relays a set of UDP broadcasts by default: TIME (37), TACACS (49), DNS (53), BOOTP/DHCP server (67), BOOTP/DHCP client (68), TFTP (69), and NetBIOS name/datagram (137/138). If you only want DHCP, you can trim the rest globally with `no ip forward-protocol udp <port>`; to relay an extra service, add `ip forward-protocol udp <port>`.
R1(config)# interface vlan 10
R1(config-if)# ip helper-address 10.20.20.10
! Optional: a second server for redundancy
R1(config-if)# ip helper-address 10.20.20.11
! Optional: relay ONLY DHCP, drop the other default UDP forwards
R1(config)# no ip forward-protocol udp 37
R1(config)# no ip forward-protocol udp 49
R1(config)# no ip forward-protocol udp 53
R1(config)# no ip forward-protocol udp 69
R1(config)# no ip forward-protocol udp 137
R1(config)# no ip forward-protocol udp 138Step 5 — Create a DHCP pool for the CLIENT subnet on the server
The server must have a pool/scope whose network matches the client subnet, not its own local subnet. This is the giaddr match: the relay stamps giaddr = 10.10.10.1, the server looks for a pool whose `network` covers that address, and if none exists it stays silent. So the pool's `network` statement is 10.10.10.0/24, even though the server itself sits on 10.20.20.0/24.
Set `default-router` to the CLIENT-side gateway (the SVI, 10.10.10.1) — that is the address clients will use, not the server. Exclude the gateway and any statically assigned addresses so the server never hands them out. The example below is the Cisco IOS DHCP server; a Windows/Linux DHCP server needs the same idea — a scope for 10.10.10.0/24 with the gateway option pointing at 10.10.10.1.
R2(config)# ip dhcp excluded-address 10.10.10.1 10.10.10.10
R2(config)# ip dhcp pool VLAN10-CLIENTS
R2(dhcp-config)# network 10.10.10.0 255.255.255.0
R2(dhcp-config)# default-router 10.10.10.1
R2(dhcp-config)# dns-server 10.20.20.10
R2(dhcp-config)# domain-name lab.local
R2(dhcp-config)# lease 0 8Step 6 — Give the server a route back to the client subnet
The server builds its Offer and sends it to giaddr — 10.10.10.1, on the 10.10.10.0/24 network. If the server has no route to that subnet, the Offer is generated and then dropped on the way out, and the client waits forever. This is the quietest failure in the whole chain because everything on the relay looks correct.
Give the server a route to the client subnet, either a static route or via your IGP. Confirm the reverse path too: the relay (R1) needs a route to the server subnet, but as the clients' gateway it usually already has one (directly connected or learned). Both directions must resolve.
! On the DHCP server: route back to the client subnet
R2(config)# ip route 10.10.10.0 255.255.255.0 10.20.20.1
! (or advertise it via your routing protocol instead of a static)Step 7 — Verify the relay and confirm a real lease
First confirm the helper is where you think it is. `show ip interface <int>` prints a 'Helper address is ...' line for each configured server; filter it to keep the output short.
Then confirm the server is actually leasing. `show ip dhcp binding` lists handed-out addresses, and `debug ip dhcp server events` on the server shows the request arriving with the giaddr and the pool being selected — that debug is the fastest way to see whether the relayed packet is reaching the server at all.
Finally, prove it end to end from a client. On an IOS device acting as a DHCP client, set `ip address dhcp`, then read the leased address and gateway. A Linux host in CML gets the same result with `udhcpc` / `ip addr`. Success looks like: an address inside 10.10.10.0/24, gateway 10.10.10.1, and a matching binding on the server.
! On the relay: is the helper present?
R1# show ip interface vlan 10 | include Helper
Helper address is 10.20.20.10
! On the server: is it leasing, and is the relay reaching it?
R2# show ip dhcp binding
R2# show ip dhcp pool VLAN10-CLIENTS
R2# debug ip dhcp server events
! On an IOS client: request and confirm a lease
PC(config)# interface GigabitEthernet0/0
PC(config-if)# ip address dhcp
PC(config-if)# no shutdown
PC# show ip interface brief
PC# show dhcp leaseCommon problems (and the fix)
Helper on the wrong interface. If you put `ip helper-address` on the server-facing link (or the uplink) instead of the client-facing SVI/subinterface, the client's broadcast is never caught and never relayed. Symptom: nothing on the server, no binding, clean-looking config. Fix: the helper must live on the interface the clients broadcast into — their default gateway.
No pool for the relayed subnet. The server has a scope only for its own subnet (10.20.20.0/24), so the relayed giaddr of 10.10.10.1 matches no pool and the server stays silent. Fix: create a pool whose `network` is the CLIENT subnet (10.10.10.0/24).
No return route to the client subnet. The relay forwards the Discover, the server logs the request, but the client never gets an address — the Offer can't route back to giaddr. Fix: add a static route (or IGP) on the server for the client subnet.
Wrong default-router / missing exclusions. Clients lease an address but can't reach anything, because `default-router` points at the server or at the wrong gateway; or the server hands out the gateway's own IP because you didn't exclude it. Fix: set `default-router` to the client-side SVI (10.10.10.1) and exclude the gateway plus any static IPs.
Wrong server IP or a blocking ACL. The helper points at an address that isn't the server, the server is unreachable, or an ACL on the path drops the relayed unicast (UDP 67) or the reply (UDP 68). Fix: correct the helper IP and make sure no ACL between relay and server blocks bootps/bootpc.
! Fix 1 — move the helper to the CLIENT-facing interface
R1(config)# interface vlan 10 ! (was on the server-facing link)
R1(config-if)# ip helper-address 10.20.20.10
! Fix 2 — add a pool for the RELAYED (client) subnet on the server
R2(config)# ip dhcp pool VLAN10-CLIENTS
R2(dhcp-config)# network 10.10.10.0 255.255.255.0
R2(dhcp-config)# default-router 10.10.10.1
! Fix 3 — return route to the client subnet on the server
R2(config)# ip route 10.10.10.0 255.255.255.0 10.20.20.1
! Fix 4 — correct gateway option + exclusions
R2(config)# ip dhcp excluded-address 10.10.10.1 10.10.10.10
R2(config)# ip dhcp pool VLAN10-CLIENTS
R2(dhcp-config)# default-router 10.10.10.1
! Fix 5 — verify the helper target is the real, reachable server
R1# show ip interface vlan 10 | include HelperFrequently asked questions
Can I configure ip helper-address on a Layer 3 switch SVI instead of a router?
Yes. On a multilayer or Layer 3 switch the relay goes on the SVI (interface vlan X) that serves as the client VLAN's default gateway, not on a physical switchport. The behavior is identical to a router interface: the SVI stamps its own IP into giaddr and unicasts the request to the server, so this is actually the most common real-world relay placement.
Does ip helper-address forward only DHCP, or does it relay other broadcasts too?
It relays more than DHCP. The command enables UDP flooding, which by default forwards eight broadcast services, including DHCP/BOOTP (ports 67 and 68), DNS (53), TFTP (69), time (37), TACACS (49), and NetBIOS name and datagram (137 and 138). If you only want DHCP relayed, disable the others with the no ip forward-protocol udp command for each unwanted port.
How does the DHCP server know which subnet's pool to hand out when the request is relayed?
The relay writes its client-facing interface IP into the packet's giaddr (gateway IP address) field before unicasting it to the server. The server matches that giaddr against its configured subnets to select the correct pool, then sends the Offer and Ack back to the giaddr for the relay to deliver. This is exactly why the client-facing interface must have an address inside the client subnet.
How do I use two DHCP servers for redundancy with relay?
Add one ip helper-address line per server on the same client-facing interface; the relay sends a copy of each Discover and Request to every listed address. The client uses whichever Offer arrives first, so configure non-overlapping or split-scope pools across the two servers to avoid handing out duplicate leases.
What is the difference between DHCP relay and DHCP snooping?
DHCP relay (ip helper-address) is a Layer 3 forwarding function that carries DHCP across subnets when the server and clients are in different networks. DHCP snooping is a Layer 2 security feature that inspects DHCP on a VLAN and drops rogue-server replies arriving on untrusted ports. They solve different problems and are frequently deployed together: relay to reach the server, snooping to protect the clients.
Practice this on graded Cisco labs
Reading is step one — build DHCP on real Cisco IOS and grade your own config, or try a free sample lab first.