Network Security

Unicast RPF: Strict vs Loose Mode

uRPF strict mode showing 20 verification drops from spoofed source packets
In: Network Security, Labs

Source IP addresses are trivially forged. Nothing in the IP header proves the source is who it claims to be, and a packet with a lie in the source field is the raw material for reflection attacks, spoofed floods, and a whole category of nuisance traffic. Unicast Reverse Path Forwarding (uRPF) is the router feature that calls the bluff: for each arriving packet, it asks "do I actually have a route back to this source?" and drops the ones where the answer is no.

This article configures strict uRPF and proves it by firing spoofed packets at the router and counting the drops. It extends the Infrastructure Security cluster guide.

The Idea in One Sentence

Normal forwarding looks up the destination to decide where a packet goes. uRPF adds a second lookup on the source: it checks the routing table (specifically CEF, the Cisco Express Forwarding table) to see whether the source address is reachable, and if so, whether it is reachable via the interface the packet arrived on. Fail the check, drop the packet.

The intuition: if a packet claiming to be from 8.8.8.8 arrives on your customer-facing interface, but your route to 8.8.8.8 points out your upstream interface, that packet is lying. A real packet from 8.8.8.8 would never arrive on the customer port. uRPF drops it.

Strict vs Loose: The Whole Decision

There are two modes, and choosing wrong either breaks legitimate traffic or fails to catch the spoofing.

Strict mode (reachable-via rx)
The source must be reachable via the exact interface the packet arrived on. Strongest anti-spoofing. Breaks on asymmetric routing.
Use onSingle-homed edges, access ports
Loose mode (reachable-via any)
The source must be reachable via any interface (just present in the routing table). Weaker, but survives asymmetry.
Use onMulti-homed cores, ISP peering

The trade-off is entirely about asymmetric routing, where a packet's return path differs from its arrival path. Strict mode assumes symmetry: it expects traffic from a source to arrive on the same interface you would use to reach that source. On a single-homed customer link that assumption holds, and strict mode is the gold standard. On a multi-homed router where traffic legitimately arrives on one link and leaves on another, strict mode drops perfectly valid packets, and you need loose mode.

Loose mode drops only the truly unroutable: source addresses that appear nowhere in your routing table at all (bogons, unallocated space, obvious garbage). It cannot catch a spoofed source that happens to be a real, routable address arriving on the wrong interface, because it does not care which interface. It is the compromise you make when you cannot guarantee symmetry.

Configuration

uRPF is one line per interface, and it requires CEF (which is on by default). Strict mode on the edge interface facing the untrusted side:

R1(config)# interface Ethernet0/0
R1(config-if)#  ip verify unicast source reachable-via rx

rx is strict (received-interface). any would be loose. That is the entire difference in the config.

Verify it is armed:

R1#show ip interface Ethernet0/0 | include verify|drop
  IP verify source reachable-via RX
   0 verification drops
   0 suppressed verification drops
   0 verification drop-rate

Zero drops so far, because nothing has spoofed yet.

Proof: Spoof It and Count the Drops

The lab sends two batches of packets from a Linux host on R1's edge (192.168.99.0/24). First, 20 spoofed packets with a source of 203.0.113.66, an address R1 has no route to via that interface. Then, as a control, 5 legitimate packets with the host's real source.

j@llmbits:~$ sudo python3 -c "
from scapy.all import IP, ICMP, send
send(IP(src='203.0.113.66', dst='10.0.12.2')/ICMP(), count=20, iface='ens224')
send(IP(src='192.168.99.100', dst='10.0.12.2')/ICMP(), count=5, iface='ens224')
"
sent 20 spoofed 203.0.113.66 -> 10.0.12.2
sent 5 legit 192.168.99.100 -> 10.0.12.2

Now the router:

R1#show ip interface Ethernet0/0 | include verify|drop
  IP verify source reachable-via RX
   20 verification drops
   0 suppressed verification drops
   0 verification drop-rate

R1#show ip traffic | include drop|RPF
         0 no route, 20 unicast RPF, 0 forced drop, 0 unsupported-addr

Exactly 20 drops. Every spoofed packet was caught. And the 5 legitimate packets? They added zero to the drop counter, because 192.168.99.100 is reachable via Ethernet0/0, so strict uRPF let them through. The counter matching the spoof count precisely, with the legitimate traffic untouched, is the feature working exactly as specified.

The 20 unicast RPF line in show ip traffic is the global tally, useful for confirming the drops are uRPF and not something else (a route missing, an ACL). uRPF drops have their own bucket.

This Is BCP 38

uRPF is the practical implementation of BCP 38 (RFC 2827), the internet's long-standing best practice on source-address validation. The idea is simple and the impact is large: if every network filtered packets whose source addresses it could not legitimately originate, entire classes of reflection and amplification DDoS attacks would become far harder to launch.

An ISP applying strict uRPF on its customer access ports guarantees that a customer can only send packets sourced from the address space that customer was assigned. A compromised machine behind that port cannot spoof arbitrary sources for an attack. This is why uRPF on the access edge is one of the highest-leverage security controls a provider can deploy, and why it belongs on enterprise edges too.

The ACL Escape Hatch

Sometimes you need uRPF but with exceptions, DHCP being the classic case. A DHCP client sends its initial DISCOVER with a source of 0.0.0.0, which is not reachable by definition and which strict uRPF will cheerfully drop, breaking DHCP. uRPF accepts an ACL to permit exceptions:

R1(config)# ip access-list extended URPF-ALLOW
R1(config-ext-nacl)#  permit ip host 0.0.0.0 any
R1(config)# interface Ethernet0/0
R1(config-if)#  ip verify unicast source reachable-via rx URPF-ALLOW

Packets that fail the uRPF check are then re-checked against the ACL; a permit overrides the drop. Use this sparingly and specifically. A broad permit ACL defeats the entire purpose.

Where Strict uRPF Bites

  • Multihoming and asymmetry. The number-one cause of strict-mode false drops. If your network has any asymmetric paths, strict mode on the affected interfaces will drop legitimate traffic. Use loose mode there.
  • Default routes and loose mode. If an interface has a default route (0.0.0.0/0), loose uRPF considers every source reachable via that route and becomes a no-op. Loose mode is meaningful only where you carry specific routes.
  • DHCP and 0.0.0.0. As above. Add the ACL exception or DHCP breaks.
  • Placement. uRPF belongs on interfaces facing untrusted or customer networks, checking traffic coming in. Applying it on a core-facing interface toward your own network is usually pointless and occasionally harmful.

FAQ

Strict or loose, if I am not sure?

If the interface is single-homed and faces users or customers, strict. If the router is multi-homed or you have any asymmetric routing, loose. When in doubt on a core box, loose is the safe default; strict on an access edge is the strong choice.

Does uRPF need CEF?

Yes. uRPF does its source lookup in the CEF table. CEF is on by default on modern IOS XE; if it is disabled, uRPF will not function.

Will loose mode stop spoofing?

Only spoofing with unroutable (bogon) sources. A spoof using a real, routable address arriving on the wrong interface passes loose mode. That is the price of surviving asymmetry.

Does uRPF replace anti-spoofing ACLs?

It complements them and scales better. An ACL must be maintained as your address space changes; uRPF follows the routing table automatically. Many networks run both: uRPF for the dynamic check, an ACL for specific known-bad ranges.

Can I see which sources were dropped?

The counters tell you how many. To see which, add logging via an ACL exception with log, or use CoPP/ACL logging alongside. uRPF itself only counts.

Key Takeaways

  • uRPF adds a source lookup to forwarding: is this source reachable, and (in strict mode) via the interface it arrived on?
  • Strict (reachable-via rx) is the strongest anti-spoofing but breaks on asymmetric routing. Loose (reachable-via any) survives asymmetry but only catches unroutable sources.
  • The lab proved it exactly: 20 spoofed packets, 20 verification drops, while 5 legitimate packets passed untouched.
  • uRPF is the implementation of BCP 38 source-address validation. On access edges it stops compromised hosts from spoofing.
  • Watch the traps: multihoming (use loose), default routes (make loose a no-op), and DHCP's 0.0.0.0 source (add an ACL exception).
  • Place it on untrusted-facing interfaces, checking inbound traffic.

Next: Control Plane Policing to protect the CPU, or the Infrastructure Security cluster guide.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.