Not to be confused with RPF (Reverse Path Forwarding) which is a multicast feature, Unicast RPF is a Unicast feature, which allows a router to verify an incoming packets source IP address by ensuring it is reachable.

To do this, it uses the FIB (Forwarding Information Base) to perform this check. To accomplish this “ip cef” (Cisco Express Forwarding) must be running, which can be done by issuing the following:

R1(config)#ip cef

Bam, that easy, and verification that it is running is just as easy:
R1(config)#do sh ip cef
Prefix              Next Hop             Interface
0.0.0.0/0           drop                 Null0 (default route handler entry)
0.0.0.0/32          receive
1.1.1.1/32          receive
172.12.15.0/24      attached             FastEthernet0/1
172.12.15.0/32      receive
172.12.15.1/32      receive
172.12.15.255/32    receive
172.12.123.0/24     attached             Serial0/0
172.12.123.0/32     receive
172.12.123.1/32     receive
172.12.123.2/32     172.12.123.2         Serial0/0
172.12.123.3/32     172.12.123.3         Serial0/0
172.12.123.255/32   receive
224.0.0.0/4         drop
224.0.0.0/24        receive
255.255.255.255/32  receive
R1(config)#

Here we see our directly connected routers that R1 knows about, which are the two spokes R2 / R3, as well as R5 directly connected over FastEthernet. An important note is you can tell there is no default route set on the router because 0.0.0.0’s network interface is Null0 (trash can). There is no routing at all configured at this time as my NBMA network acts almost like an MPLS with L3 reachability at Layer 2 as can be seen with a test ping to make sure its rockin:

R1(config)#do ping 172.12.123.2

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.12.123.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 64/65/69 ms
R1(config)#

So once CEF is enabled, there is no more configuration of CEF itself for that for Unicast RFP to work, you just need to configure Unicast RFP to be in one of two modes:

  • Loose mode – Verifies the source IP address of the incoming packet is reachable by any means, it doesn’t matter how
  • Strict mode – Verifies that the source IP address is reachable on the same interface that in came in on – THIS IS THE BIG DIFFERENCE BETWEEN THE TWO!

The command is almost the same, long and complex for both with slight variations for the different modes at the end, and configured on the interface level:

R1(config)#int s0/0
R1(config-if)#ip verify unicast source reachable-via ?
  any  Source is reachable via any interface
  rx   Source is reachable via interface on which packet was received

That is correct, “ip verify unicast source reachable-via …” Easy enough to remember right? As seen above, “any” is for Loose mode, and “rx” is to configure Strict mode.

** One thing to note, a variation of the command on older routers is “ip verify unicast reverse-path to be backwards compatible as seen here, it even shows in IOS help that it is in old command format so it must be ancient:

R1(config-if)#ip verify unicast ?
  reverse-path  Reverse path validation of source address (old command format)
  source        Validation of source address

So back to business, I wanted to see if there were further modifiers, so I ? after both any and rx and this is what I got for either:

R1(config-if)#ip verify unicast source reachable-via rx ?
  <1-199>          A standard IP access list number
  <1300-2699>      A standard IP expanded access list number
  allow-default    Allow default route to match when checking source address
  allow-self-ping  Allow router to ping itself (opens vulnerability in
                   verification)
  <cr>

R1(config-if)#ip verify unicast source reachable-via any ?
  <1-199>          A standard IP access list number
  <1300-2699>      A standard IP expanded access list number
  allow-default    Allow default route to match when checking source address
  allow-self-ping  Allow router to ping itself (opens vulnerability in
                   verification)
  <cr>

So some good things to note from the above output:

  • Only standard ACL’s are being allowed as modifiers
  • There is a <cr> indicating none of the above modifiers must be used
  • There is also something about allowing default routes
  • “allow-self-ping” is marked by the IOS as opening vulnerabilities with verification

Now one gotcha about this command, you have to make sure the return router it will be sending Unicast RPF’s to has a return route, so on that note I will also demonstrate the output of “sh ip cef” after configuring it and a default route on R2:

R2(config)#ip route 0.0.0.0 0.0.0.0 172.12.123.1
R2(config)#ip cef
R2(config)#do show ip cef
Prefix              Next Hop             Interface
0.0.0.0/0           172.12.123.1         Serial0/0
0.0.0.0/32          receive
2.2.2.2/32          receive
172.12.23.0/24      attached             FastEthernet0/0
172.12.23.0/32      receive
172.12.23.2/32      receive
172.12.23.255/32    receive
172.12.123.0/24     attached             Serial0/0
172.12.123.0/32     receive
172.12.123.1/32     172.12.123.1         Serial0/0
172.12.123.2/32     receive
172.12.123.3/32     172.12.123.3         Serial0/0
172.12.123.255/32   receive
224.0.0.0/4         drop
224.0.0.0/24        receive
255.255.255.255/32  receive
R2(config)#

So it does still have a ‘receive’ line in there, however the default route now is defined.

So back to R1 I will actually put the config for verification on S0/0 and demonstrate another verification command that verification is running (ironic?):

R1(config)#int s0/0
R1(config-if)#ip verify unicast source reachable-via any

Now it is configured, and to verify it’s configured, you can use “sh cef int (int)” :
R1(config-if)#do sh cef int s0/0
Serial0/0 is up (if_number 6)
  Corresponding hwidb fast_if_number 6
  Corresponding hwidb firstsw->if_number 6
  Internet address is 172.12.123.1/24
  ICMP redirects are always sent
  Per packet load-sharing is disabled
  IP unicast RPF check is enabled
  Inbound access list is not set
  Outbound access list is not set
  Hardware idb is Serial0/0
  Fast switching type 5, interface type 60
  IP CEF switching enabled
  IP CEF Feature Fast switching turbo vector
  Input fast flags 0x4000, Input fast flags2 0x0, Output fast flags 0x0, Output fast flags2 0x0
  ifindex 3(3)
  Slot 0 Slot unit 0 Unit 0 VC -1
  Transmit limit accumulator 0x0 (0x0)
  IP MTU 1500
R1(config-if)#

Lots of other output, but to verify specifically for Unicast RPF, that is the command to commit to memory… like everything.

One thing that needs it’s own bold red look at me is the “sh int s0/0” vs “sh ip int s0/0” as the initial command will give you more interface configurations and errors, while the latter command shows you the IP services running on the interface like IP CEF, BGP Mapping, and IP verify verification drops! I want to show both here to examplify:

“sh int s0/0”:

R1(config-if)#do sh int s0/0
Serial0/0 is up, line protocol is up
  Hardware is PowerQUICC Serial
  Internet address is 172.12.123.1/24
  MTU 1500 bytes, BW 1544 Kbit, DLY 20000 usec,
     reliability 255/255, txload 1/255, rxload 1/255
  Encapsulation FRAME-RELAY, loopback not set
  Keepalive set (10 sec)
  CRC checking enabled
  LMI enq sent  557, LMI stat recvd 557, LMI upd recvd 0, DTE LMI up
  LMI enq recvd 0, LMI stat sent  0, LMI upd sent  0
  LMI DLCI 1023  LMI type is CISCO  frame relay DTE
  FR SVC disabled, LAPF state down
  Broadcast queue 0/64, broadcasts sent/dropped 156/0, interface broadcasts 79
  Last input 00:00:00, output 00:00:00, output hang never
  Last clearing of “show interface” counters 01:34:13
  Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
  Queueing strategy: weighted fair
  Output queue: 0/1000/64/0 (size/max total/threshold/drops)
     Conversations  0/1/256 (active/max active/max total)
     Reserved Conversations 0/0 (allocated/max allocated)
     Available Bandwidth 1158 kilobits/sec
  5 minute input rate 0 bits/sec, 0 packets/sec
  5 minute output rate 0 bits/sec, 0 packets/sec
     721 packets input, 59837 bytes, 0 no buffer
     Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
     1 input errors, 0 CRC, 1 frame, 0 overrun, 0 ignored, 0 abort
     720 packets output, 59580 bytes, 0 underruns
     0 output errors, 0 collisions, 2 interface resets
     0 output buffer failures, 0 output buffers swapped out
     4 carrier transitions
     DCD=up  DSR=up  DTR=up  RTS=up  CTS=up
“sh ip int s0/0”:
R1(config-if)#do sh ip int s0/0
Serial0/0 is up, line protocol is up
  Internet address is 172.12.123.1/24
  Broadcast address is 255.255.255.255
  Address determined by setup command
  MTU is 1500 bytes
  Helper address is not set
  Directed broadcast forwarding is disabled
  Outgoing access list is not set
  Inbound  access list is not set
  Proxy ARP is enabled
  Local Proxy ARP is disabled
  Security level is default
  Split horizon is disabled
  ICMP redirects are always sent
  ICMP unreachables are always sent
  ICMP mask replies are never sent
  IP fast switching is enabled
  IP fast switching on the same interface is enabled
  IP Flow switching is disabled
  IP CEF switching is enabled
  IP CEF Feature Fast switching turbo vector
  IP multicast fast switching is enabled
  IP multicast distributed fast switching is disabled
  IP route-cache flags are Fast, CEF
  Router Discovery is disabled
  IP output packet accounting is disabled
  IP access violation accounting is disabled
  TCP/IP header compression is disabled
  RTP/IP header compression is disabled
  Policy routing is disabled
  Network address translation is disabled
  BGP Policy Mapping is disabled
  WCCP Redirect outbound is disabled
  WCCP Redirect inbound is disabled
  WCCP Redirect exclude is disabled
  IP verify source reachable-via ANY
  5 verification drops
  0 suppressed verification drops
R1(config-if)#

As can be seen, the second command lists more IP services that statistics for the interface.

Also on the note of that terribly long output, if you are looking for one piece of info in a monster pile of info, you can put ” | i (word)” at the end of the command to only see lines that include that word as shown here:

R1(config-if)#do sh ip int s0/0 | i verify
  IP verify source reachable-via ANY
R1(config-if)#do sh ip int s0/0 | i verification
  5 verification drops
  0 suppressed verification drops

R1(config-if)#

Notice I got burned there on the first one because that just shows me my verify criteria, but what I was actually looking for was the drop count from R2 because it’s using that default route.

Also to note, that WILL ONLY INCREMENT FROM INCOMING PACKETS ! It is verifying the source of incoming packets, so any outgoing traffic WILL NOT increment the verification drops! That is very important to note as it’s so easy to forget!

One more show command to verify a lot of different things, is “sh ip traffic”, and so you have been warned this output is another monster but a TON of good info:

R1#sh ip traffic
IP statistics:
  Rcvd:  396 total, 391 local destination
         0 format errors, 0 checksum errors, 0 bad hop count
         0 unknown protocol, 0 not a gateway
         0 security failures, 0 bad options, 0 with options
  Opts:  0 end, 0 nop, 0 basic security, 0 loose source route
         0 timestamp, 0 extended security, 0 record route
         0 stream ID, 0 strict source route, 0 alert, 0 cipso, 0 ump
         0 other
  Frags: 0 reassembled, 0 timeouts, 0 couldn’t reassemble
         0 fragmented, 0 fragments, 0 couldn’t fragment
  Bcast: 381 received, 317 sent
  Mcast: 0 received, 0 sent
  Sent:  317 generated, 0 forwarded
  Drop:  5 encapsulation failed, 0 unresolved, 0 no adjacency
         0 no route, 5 unicast RPF, 0 forced drop
         0 options denied
  Drop:  0 packets with source IP address zero
  Drop:  0 packets with internal loop back IP address

ICMP statistics:
  Rcvd: 0 format errors, 0 checksum errors, 0 redirects, 0 unreachable
        5 echo, 5 echo reply, 0 mask requests, 0 mask replies, 0 quench
        0 parameter, 0 timestamp, 0 timestamp replies, 0 info request, 0 other
        0 irdp solicitations, 0 irdp advertisements
  Sent: 0 redirects, 0 unreachable, 21 echo, 5 echo reply
        0 mask requests, 0 mask replies, 0 quench, 0 timestamp, 0 timestamp replies
        0 info reply, 0 time exceeded, 0 parameter problem
        0 irdp solicitations, 0 irdp advertisements

TCP statistics:
  Rcvd: 0 total, 0 checksum errors, 0 no port
  Sent: 0 total

BGP statistics:
  Rcvd: 0 total, 0 opens, 0 notifications, 0 updates
        0 keepalives, 0 route-refresh, 0 unrecognized
  Sent: 0 total, 0 opens, 0 notifications, 0 updates
        0 keepalives, 0 route-refresh

IP-EIGRP statistics:
  Rcvd: 0 total
  Sent: 0 total

PIMv2 statistics: Sent/Received
  Total: 0/0, 0 checksum errors, 0 format errors
  Registers: 0/0 (0 non-rp, 0 non-sm-group), Register Stops: 0/0,  Hellos: 0/0
  Join/Prunes: 0/0, Asserts: 0/0, grafts: 0/0
  Bootstraps: 0/0, Candidate_RP_Advertisements: 0/0
  Queue drops: 0
  State-Refresh: 0/0

IGMP statistics: Sent/Received
  Total: 0/0, Format errors: 0/0, Checksum errors: 0/0
  Host Queries: 0/0, Host Reports: 0/0, Host Leaves: 0/0
  DVMRP: 0/0, PIM: 0/0
  Queue drops: 0

UDP statistics:
  Rcvd: 381 total, 0 checksum errors, 381 no port
  Sent: 312 total, 0 forwarded broadcasts

OSPF statistics:
  Rcvd: 0 total, 0 checksum errors
        0 hello, 0 database desc, 0 link state req
        0 link state updates, 0 link state acks

  Sent: 0 total
        0 hello, 0 database desc, 0 link state req
        0 link state updates, 0 link state acks

ARP statistics:
  Rcvd: 0 requests, 0 replies, 92 reverse, 0 other
  Sent: 0 requests, 4 replies (0 proxy), 162 reverse
R1#

It includes a TON of great stats, but lets go a step further with the | (pipe) in the command, because this is a monster output that we can cut down by a lot:

R1# sh ip traffic | i rpf
R1# sh ip traffic | i RPF
         0 no route, 5 unicast RPF, 0 forced drop
R1#

So it is case sensitive because it is looking to match an exact word in the output, so you could also put unicast and probably get some more info along with RPF, but this can also be used for whole sections:

R1#sh ip traffic | ?
  append    Append redirected output to URL (URLs supporting append operation
            only)
  begin     Begin with the line that matches
  exclude   Exclude lines that match
  include   Include lines that match
  redirect  Redirect output to URL
  section   Filter a section of output
  tee       Copy output to URL

R1#sh ip traffic | s OSPF
OSPF statistics:
  Rcvd: 0 total, 0 checksum errors
        0 hello, 0 database desc, 0 link state req
        0 link state updates, 0 link state acks
R1#

So you can use include to match a single word (but it will only show you that single line that includes the word), you can use begin to begin viewing output at your defined criteria, or like I used was section to just see a section that may be relevant to me.

I feel it’s very important to know you can use the | (above enter key called pipe) to dig straight to your info you need both for the exam but also real world network troubleshooting.

One last thing to wrap up, as seen there were 5 drops on there, and that was from testing from R2 because I had to test that verification on incoming packets that then get verify response sent back to the source:

R2# ping 172.12.123.1 source 2.2.2.2

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.12.123.1, timeout is 2 seconds:
Packet sent with a source address of 2.2.2.2
…..

Success rate is 0 percent (0/5)

This fails because by default, a default route is not a valid verification source for Unicast RFP, and was actually in the configuration options just below the ACL modifiers:

R1(config-if)#ip verify unicast source reachable-via any ?
  <1-199>          A standard IP access list number
  <1300-2699>      A standard IP expanded access list number
  allow-default    Allow default route to match when checking source address
  allow-self-ping  Allow router to ping itself (opens vulnerability in
                   verification)
  <cr>

So as best practice, I will remove the entire command and re-apply it with “allow-default” in the command, and give it another go here:

R1(config-if)#no ip verify unicast source reachable-via any
R1(config-if)#ip verify unicast source reachable-via any allow-default
R1(config-if)#
ASR#2
[Resuming connection 2 to r2 … ]

R2(config)#do ping 172.12.123.1 source 2.2.2.2

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.12.123.1, timeout is 2 seconds:
Packet sent with a source address of 2.2.2.2
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 64/66/69 ms
R2(config)#

And that is about all I have to say about that. I start these posts thinking easy topic, should be a short post, and end up with half a book written. Next up will be some useful security commands, so it will be a shorter post hopefully (famous last words).