CCIE Pursuit Blog

October 7, 2007

ip virtual-reassembly

While configuring NAT, I will sometimes see “ip virtual-reassembly” added to the NAT interfaces’ configurations:

ip nat inside source list 99 interface Serial0/0 overload
!
access-list 99 permit 10.0.0.0 0.0.0.255
!
interface FastEthernet0/0
 description ->sw1 fa0/1
 ip address 10.0.0.1 255.255.255.0
 ip nat inside
 ip virtual-reassembly
 duplex auto
 speed auto
!
interface Serial0/0
 ip address 100.0.0.1 255.255.255.0
 ip nat outside
 ip virtual-reassembly
 encapsulation frame-relay
 frame-relay map ip 100.0.0.2 102 broadcast
 no frame-relay inverse-arp

IOS throws that on automatically.  Here’s what it does:

A buffer overflow attack can occur when an attacker continuously sends a large number of incomplete IP fragments, causing the firewall to lose time and memory while trying to reassemble the fake packets.

The max-reassemblies number option and the max-fragments number option allow you to configure maximum threshold values to avoid a buffer overflow attack and to control memory usage.

In addition to configuring the maximum threshold values, each IP datagram is associated with a managed timer. If the IP datagram does not receive all of the fragments within the specified time (which can be configured via the timeout seconds option), the timer will expire and the IP datagram (and all of its fragments) will be dropped.

Here’s why it does it:

VFR is designed to work with any feature that requires fragment reassembly (such as Cisco IOS Firewall and NAT). Currently, NAT enables and disables VFR internally; that is, when NAT is enabled on an interface, VFR is automatically enabled on that interface.


Cisco Documentation:

ip virtual-reassembly

Hits and Misses In IP NAT Statistics

I did some NAT labs a week or so ago and the two best verification commands are “show ip nat translations” and “show ip nat statistics“.  The output of the “show ip nat statistics” command includes a line with “hits” and “misses”.  I was noticing “misses” during my labs and thought that these were errors.  I didn’t look into them too hard because I was doing a lot of configuration changes and attributed these errors to them.

I am working (more slowly than I had planned) through the Cisco CCIE Written Exam Guide and in a section describing the basics of NAT, I came across an explanation for NAT hits and misses:

Hits occur when NAT looks for a mapping, and finds one. Misses occur when NAT looks for a NAT table entry, does not find one, and then needs to dynamically add one.

Ah!  That makes sense.  It also comforted me that the misses are not actually errors.  I decided to quickly lab up a simple NAT translation and then check out the hits and misses.

I configured r1 to translate 10.0.0.0/24 addresses to use the s0/0 address (100.0.0.1) with PAT:

ip nat inside source list 99 interface Serial0/0 overload
!
access-list 99 permit 10.0.0.0 0.0.0.255
!
interface FastEthernet0/0
 description ->sw1 fa0/1
 ip address 10.0.0.1 255.255.255.0
 ip nat inside
 ip virtual-reassembly
 duplex auto
 speed auto
!
interface Serial0/0
 ip address 100.0.0.1 255.255.255.0
 ip nat outside
 ip virtual-reassembly
 encapsulation frame-relay
 frame-relay map ip 100.0.0.2 102 broadcast
 no frame-relay inverse-arp

So I should be able to ping r2’s serial interface (100.0.0.2) and since the IP NAT translation table will be empty, I should record 1 miss and then 4 hits (assuming 5 ping packets):

r1#clear ip nat trans *
r1#clear ip nat stat
r1#sh ip nat trans

r1# [note: IP NAT translation table is empty]

Pings to 100.0.0.2 will use the directly connected serial interface (100.0.0.1) by default, so we need to set the ping source to the fa0/0 interface (10.0.0.1):

r1#ping 100.0.0.2 source 10.0.0.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 100.0.0.2, timeout is 2 seconds:
Packet sent with a source address of 10.0.0.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/5/9 ms

r1#sh ip nat trans
Pro Inside global      Inside local       Outside local      Outside global
icmp 100.0.0.1:18      10.0.0.1:18        100.0.0.2:18       100.0.0.2:18

r1#sh ip nat stat
Total active translations: 1 (0 static, 1 dynamic; 1 extended)
Outside interfaces:
  Serial0/0
Inside interfaces:
  FastEthernet0/0
Hits: 10  Misses: 0
CEF Translated packets: 5, CEF Punted packets: 0
Expired translations: 0
Dynamic mappings:
— Inside Source
[Id: 3] access-list 99 interface Serial0/0 refcount 1
Queued Packets: 0

Hmmmm…two things:

1) The number of hits is 10, not 5.  This makes sense because pings are ROUND TRIP so NAT translates the outbound packets to an inside global address (10.0.0.1:18) and then translates the inbound packets from the outside global address (100.0.0.2:18) back into the local inside address (10.0.0.1:18).
2) More importantly, why the hell didn’t I register a miss?  Because the NAT translation table was empty, the first packet should have required a tranlation be permformed and added to the table thereby generating a miss.

I mucked about with clearing the IP NAT stats and the table as well as attempting different protocols, but I still could not generate a miss.  Slowly (but much quicker than usual – maybe I am developing a “Cisco Sense”) it dawned on me that the issue may be due to the packets being generated on the router.  I quickly created a routed port on the switch off of r1’s fa0/0 interface along with a static route:

interface FastEthernet0/1
 description ->r1 fa0/0
 no switchport
 ip address 10.0.0.2 255.255.255.0

!
ip route 100.0.0.0 255.255.255.0 10.0.0.1

Tracing the route to 100.0.0.2

  1 10.0.0.1 0 msec 0 msec 9 msec    <-r1
  2 100.0.0.2 8 msec *  0 msec          <-r2

Now let’s try pinging 100.0.0.2 (r2) from the switch (after clearing the IP NAT statistics and translations on r1):

sw1#ping 100.0.0.2 re 2

Type escape sequence to abort.
Sending 2, 100-byte ICMP Echos to 100.0.0.2, timeout is 2 seconds:
!!
Success rate is 100 percent (2/2), round-trip min/avg/max = 8/8/9 ms

If everything works correctly, we should see 1 miss and 3 hits (2 round trip ping packets – 1 packet for the miss) on r1:

r1#sh ip nat trans
Pro Inside global      Inside local       Outside local      Outside global
icmp 100.0.0.1:3       10.0.0.2:3         100.0.0.2:3        100.0.0.2:3

r1#sh ip nat stat
Total active translations: 1 (0 static, 1 dynamic; 1 extended)
Outside interfaces:
  Serial0/0
Inside interfaces:
  FastEthernet0/0
Hits: 3  Misses: 1
CEF Translated packets: 4, CEF Punted packets: 0
Expired translations: 0
Dynamic mappings:
— Inside Source
[Id: 3] access-list 99 interface Serial0/0 refcount 1
Queued Packets: 0

Sweet.  That’s more like it. 

While this was just a simple exercise to verify how the hits and misses work in NAT, it does highlight an important point: your verification output may be different based on whether you are actually originating a packet from a subnet or just sourcing it on a router to emulate it.

Blog at WordPress.com.