Guide

How to Configure DHCP Snooping and Dynamic ARP Inspection (Step by Step)

DHCP snooping and Dynamic ARP Inspection (DAI) are the two access-edge features that turn a switch from a passive forwarder into an enforcer of who is allowed to hand out addresses and claim them. DHCP snooping stops a rogue DHCP server — whether it's a malicious laptop or a misconfigured home router someone plugged into a wall jack — from answering client requests, becoming the default gateway, and quietly man-in-the-middling the subnet. As it works, snooping records a trusted table of "this MAC, with this IP, learned on this port, in this VLAN." DAI then reuses that table to validate every ARP packet on the VLAN, dropping the forged ARP replies that ARP-poisoning attacks depend on. The two are deliberately coupled: DAI has no idea what a legitimate MAC-to-IP mapping looks like until snooping tells it, so you always build snooping first. The entire design hinges on one idea — the trust boundary. The single port (or trunk) facing your real DHCP server is trusted; every access port a user could sit on stays untrusted. Get that boundary right and these features are nearly invisible to users while shutting down two of the most common Layer-2 attacks on the CCNA and CCNP blueprint. Get it backwards and you either trust an attacker or black-hole your own network. This guide walks the exact IOS command order and the verification you should never skip.

Step 1 — Map the trust boundary before you touch the CLI

Everything downstream depends on one decision: which ports face the real DHCP server, and which ports face users. On a Cisco switch, both DHCP snooping and DAI default every port to UNTRUSTED. That default is correct and deliberate — an untrusted port drops server-sourced DHCP messages (OFFER, ACK, NAK) and validates ARP against the binding table. You only relax that on the uplink that legitimately carries server traffic.

Write it down first: the access ports (say Gi1/0/1–23) where hosts, phones, and printers live stay untrusted. The uplink toward the distribution switch or router that reaches your DHCP server (say Gi1/0/24) becomes trusted. If you have a chain of switches, the inter-switch link that points toward the server is the trusted side on each switch; the link pointing toward users is not. Trusting the wrong port is the single most common way these features get misconfigured, so decide this before you enable anything.

Step 2 — Enable DHCP snooping globally and per VLAN

Snooping takes two commands to actually run. The global `ip dhcp snooping` arms the feature, but it inspects nothing until you also name the VLANs to watch. Enabling the global command alone is a classic 'I configured it but it does nothing' trap — the per-VLAN statement is what puts snooping on the wire.

Enable it on every VLAN that carries DHCP clients. You can list or range VLANs, for example `ip dhcp snooping vlan 10,20,30` or `ip dhcp snooping vlan 10-30`. From this moment, snooping starts building its binding table — but only from DHCP exchanges it actually sees. Hosts that already hold a lease won't appear until they renew, so bindings populate over time or after you bounce a port.

Switch# configure terminal
Switch(config)# ip dhcp snooping
Switch(config)# ip dhcp snooping vlan 10
! For multiple VLANs:
Switch(config)# ip dhcp snooping vlan 10,20,30

Step 3 — Trust the uplink toward the DHCP server

Right now every port, including your uplink, is untrusted — which means the switch is dropping the OFFER and ACK coming back from your real DHCP server. Clients can't get a lease until you trust the port that server traffic arrives on. Trust ONLY that uplink (or the inter-switch trunk pointing toward the server).

Leave all access/host ports untrusted. That asymmetry is the whole mechanism: a rogue DHCP server plugged into an untrusted access port has its OFFER silently dropped, while your legitimate server's OFFER passes because it enters on the trusted uplink.

Switch(config)# interface GigabitEthernet1/0/24
Switch(config-if)# description UPLINK-toward-DHCP-server
Switch(config-if)# ip dhcp snooping trust
Switch(config-if)# end

Step 4 — (Optional) Rate-limit untrusted access ports

A DHCP starvation attack floods the server with spoofed DISCOVER messages to exhaust the address pool. You can blunt it by capping how many DHCP packets per second an untrusted port accepts. If a port exceeds the limit, the switch places it in err-disabled state, so keep the value comfortably above what a normal host generates — a handful of packets per second is plenty for a single client.

Apply this only to untrusted host ports, never the trusted uplink (the uplink legitimately aggregates DHCP traffic from many clients and would trip instantly). Because a violation err-disables the port, pair this with automatic recovery in Step 8 so a transient burst doesn't require a manual bounce. Exact maximum rate varies by platform; check your switch's current configuration guide rather than assuming a ceiling.

Switch(config)# interface range GigabitEthernet1/0/1 - 23
Switch(config-if-range)# ip dhcp snooping limit rate 15
Switch(config-if-range)# end

Step 5 — Verify the binding table before adding DAI

Do not move on until snooping is actually populating bindings — DAI is only as good as this table. `show ip dhcp snooping` confirms the feature is on, which VLANs are watched, and which interfaces are trusted. `show ip dhcp snooping binding` shows the live table: MAC address, leased IP, lease time, VLAN, and the port it was learned on.

If the table is empty, that's expected until clients do a fresh DHCP exchange while snooping is active. Force it by having a test host release/renew or by bouncing its access port, then re-check. Remember that a binding is only created for dynamically leased hosts — statically addressed devices (a server, a printer with a hard-coded IP) will never appear here, which is why Step 7 handles them separately. If you want the table to survive a reload, point snooping at a database file with `ip dhcp snooping database`.

Switch# show ip dhcp snooping
Switch# show ip dhcp snooping binding

! Example output:
! MacAddress          IpAddress     Lease(sec)  Type           VLAN  Interface
! ------------------  ------------  ----------  -------------  ----  --------------------
! 00:11:22:33:44:55   10.10.10.101  86312       dhcp-snooping  10    GigabitEthernet1/0/5

Step 6 — Enable Dynamic ARP Inspection on the same VLANs

With a populated binding table, turn on DAI for the same VLANs snooping is protecting. DAI intercepts every ARP request and reply on those VLANs and checks the sender's MAC/IP pair against the snooping binding table. If an ARP packet claims a MAC-to-IP mapping that snooping never recorded, DAI drops it and logs it — which is exactly how it defeats ARP poisoning, where an attacker forges 'I am the gateway' ARP replies.

Match the VLAN list to your snooping configuration. Enabling DAI on a VLAN where snooping isn't running (or hasn't built bindings yet) will drop legitimate host ARP, because there is nothing to validate against — see the Common Problems section.

Switch(config)# ip arp inspection vlan 10
! For multiple VLANs:
Switch(config)# ip arp inspection vlan 10,20,30

Step 7 — Trust the uplink for DAI and handle static hosts

DAI keeps its own trust state, completely separate from snooping's. Trusting the uplink for DHCP snooping in Step 3 did NOT make it trusted for DAI — you must trust it again with `ip arp inspection trust`. A trusted DAI port forwards ARP without validation, which is what you want on the uplink where the gateway's and server's ARP legitimately originate. Every access port stays untrusted so user-sourced ARP is checked against the bindings.

Statically addressed devices need special handling because they have no DHCP binding to validate against. Define an `arp access-list` that permits the exact IP/MAC pair, then bind it to the VLAN with `ip arp inspection filter`. Without this, DAI will drop ARP from your hard-coded server or default gateway even though nothing is wrong.

Switch(config)# interface GigabitEthernet1/0/24
Switch(config-if)# ip arp inspection trust
Switch(config-if)# exit

! Permit statically addressed (non-DHCP) hosts:
Switch(config)# arp access-list STATIC-HOSTS
Switch(config-arp-nacl)# permit ip host 10.10.10.50 mac host 0011.2233.4455
Switch(config-arp-nacl)# exit
Switch(config)# ip arp inspection filter STATIC-HOSTS vlan 10

Step 8 — (Optional) Tighten DAI with validation checks and recovery

By default DAI validates the sender against the binding table but does not deeply inspect the ARP packet's fields. `ip arp inspection validate` adds checks: `src-mac` compares the Ethernet source against the ARP sender MAC, `dst-mac` checks the target MAC on replies, and `ip` checks for invalid or unexpected IP addresses (0.0.0.0, broadcasts). Note that this command is entered as ONE line with all the keywords you want — re-entering it with a subset replaces the previous set rather than adding to it, so always specify the full list.

DAI also rate-limits untrusted ports by default (a low packets-per-second ceiling) and err-disables a port that exceeds it; trusting a port removes that limit, which is another reason not to leave your uplink untrusted. Because both snooping and DAI can err-disable ports, enable automatic recovery so a brief burst doesn't strand a user offline until you intervene.

Switch(config)# ip arp inspection validate src-mac dst-mac ip

! Optional per-port ARP rate limit on access ports:
Switch(config)# interface range GigabitEthernet1/0/1 - 23
Switch(config-if-range)# ip arp inspection limit rate 15
Switch(config-if-range)# exit

! Auto-recover err-disabled ports:
Switch(config)# errdisable recovery cause arp-inspection
Switch(config)# errdisable recovery cause dhcp-rate-limit

Step 9 — Verify Dynamic ARP Inspection

Confirm DAI is enforcing on the right VLANs and trusting only the right ports. `show ip arp inspection` gives the global picture, including which validation checks are active. `show ip arp inspection vlan 10` shows whether DAI is enabled and which ARP ACL (if any) is filtering static hosts on that VLAN. `show ip arp inspection interfaces` lists each port's trust state and configured rate limit — this is your fastest sanity check that the uplink is trusted and access ports are not.

Watch the forwarded/dropped counters in `show ip arp inspection` as you test. Legitimate hosts should forward; a test that spoofs a mapping not in the binding table should increment the drop counter and log a message. If everything DAI-eligible is being dropped, jump straight to the binding table — the problem is almost always upstream in snooping.

Switch# show ip arp inspection
Switch# show ip arp inspection vlan 10
Switch# show ip arp inspection interfaces

Common problems (and the fix)

Trusting a host/access port. If you put `ip dhcp snooping trust` or `ip arp inspection trust` on a port a user can reach, you've handed an attacker a trusted seat — their rogue DHCP offers and forged ARP now pass unchecked. Fix: remove trust from access ports (`no ip dhcp snooping trust`, `no ip arp inspection trust`); trust only the uplink or the inter-switch link pointing toward the DHCP server.

Forgetting to trust the uplink. The most common outage: snooping/DAI is on, but the server-facing port is still untrusted, so the switch drops the real server's DHCP OFFER/ACK and the gateway's ARP. Clients can't get leases and can't reach the gateway. Fix: trust the uplink for BOTH features — remember they hold separate trust state, so you need `ip dhcp snooping trust` AND `ip arp inspection trust` on that interface.

Running DAI without snooping (or before bindings exist). DAI validates ARP against the snooping binding table; if snooping isn't enabled on the VLAN, or you enabled DAI before hosts obtained leases, there are no bindings and DAI drops all dynamic-host ARP. Fix: enable and verify snooping first, let clients acquire leases so `show ip dhcp snooping binding` is populated, then enable DAI. Cover statically addressed devices with an `arp access-list` and `ip arp inspection filter`.

DHCP breaks after snooping is on, even though trust looks right. On a pure Layer-2 access switch, snooping inserts DHCP Option 82 with a giaddr of 0.0.0.0, and an upstream relay or server may reject that as invalid — so DHCP silently fails. Fix: on the L2 access switch use `no ip dhcp snooping information option`, or trust Option 82 upstream (e.g., `ip dhcp relay information trust-all` on the relay); the exact remedy depends on where relay lives, so confirm against your current platform guide.

Ports stuck in err-disabled. A DHCP or ARP rate limit that's set too low — or a trusted uplink accidentally left untrusted and subject to DAI's default rate limit — will err-disable ports under normal load. Fix: trust the uplink (which removes DAI's rate limit there), set access-port limits above real client behavior, and enable `errdisable recovery cause arp-inspection` and `errdisable recovery cause dhcp-rate-limit` so recovery is automatic.

Frequently asked questions

Why did DHCP stop working for clients right after I enabled DHCP snooping?

Two causes are typical. First, the port or trunk facing the DHCP server (or relay) is still untrusted, so the switch drops the server's DHCPOFFER and DHCPACK replies until you trust that uplink. Second is Option 82: snooping inserts it by default, and an upstream server or relay commonly discards those requests because the giaddr is 0.0.0.0, which you resolve with 'no ip dhcp snooping information option' or by trusting the relay information.

Does the DHCP snooping binding table survive a switch reboot?

No. By default the table lives only in RAM, so a reload wipes it and DAI then drops legitimate hosts until each one renews or re-acquires its DHCP lease. Configure the snooping database agent with 'ip dhcp snooping database' to persist the bindings to flash or a TFTP URL so they are reloaded after a reboot.

What is the difference between DHCP snooping, Dynamic ARP Inspection, and IP Source Guard?

All three read the same DHCP snooping binding table, but each enforces a different layer. Snooping builds the table and blocks rogue DHCP servers, DAI validates ARP packets so nobody can forge an IP-to-MAC mapping, and IP Source Guard filters actual data traffic so a host can only send using its leased IP (and optionally MAC). You typically layer all three on the same untrusted access ports for full spoofing protection.

Do I need to configure DHCP snooping and DAI on the trunks between switches too?

Yes. A switch only builds bindings for DHCP exchanges it directly observes, so it cannot validate ARP for a host learned on a neighboring switch. Trust the inter-switch trunks for both features and do it on both ends; a trunk left untrusted for DAI is a classic source of intermittent drops once traffic crosses switches.

If an attacker gets a valid DHCP lease, can they still run an ARP-poisoning attack?

No. DAI checks each ARP packet's sender IP and MAC against the snooping binding, so the attacker can only claim the exact IP-to-MAC pair it was actually leased and cannot spoof the default gateway or impersonate another host to man-in-the-middle it. That dependency is why DAI needs snooping first: without the binding table it has no trusted mapping to compare against.

Practice this on graded Cisco labs

Reading is step one — build Device Security & SSH on real Cisco IOS and grade your own config, or try a free sample lab first.