Posts Tagged ‘nat’

Jul
15

Look at the following NAT scenario (thanks to Huan Pham on Groupstudy for the example). R2 is configured to translate R1 Loopback0 IP address to one of it’s own Loopback0 IP addresses:

R2:
ip nat inside source static 150.1.1.1 150.1.2.100
!
interface Serial 0/1
 ip nat inside
!
inerface FastEthernet 0/0
 ip nat outside

All hosts behind Ethernet segment can reach R1 using the IP address “150.1.2.100”. Now the question is to make a user logged in R2 to telnet to “150.1.2.100” and reach R1 Loopback0. Lets start straight with the final working configuration:

R2:
interface Loopback0
 ip nat outside
!
ip nat inside source static 150.1.1.1 150.1.2.100
ip nat outside source static 150.1.2.2 155.1.23.22

!
! Route returning packets from R1 over Loopback0
!
ip route 155.1.23.22 255.255.255.255 150.1.2.254

To verify it, enable the following debugging and telnet to 150.1.2.100 from R2:

Rack1R2#debug ip nat detailed
IP NAT detailed debugging is on

Rack1R2#telnet 150.1.2.100
Trying 150.1.2.100 ... Open

User Access Verification

Password: 

!
! NAT on the outside direction
!
NAT: o: tcp (150.1.2.2, 39064) -> (150.1.2.100, 23) [22225]
NAT: s=150.1.2.2->155.1.23.22, d=150.1.2.100 [22225]
NAT: s=155.1.23.22, d=150.1.2.100->150.1.1.1 [22225]

!
! NAT on the inside direction
!

NAT: i: tcp (150.1.1.1, 23) -> (155.1.23.22, 39064) [0]
NAT: s=150.1.1.1->150.1.2.100, d=155.1.23.22 [0]
NAT: s=150.1.2.100, d=155.1.23.22->150.1.2.2 [0]

As we can see from this output, the packet leaving Loopback0 is looped back and uses the both static NAT translation: first, to translate it’s source from “150.1.2.2” to “155.1.23.22” and the second to translate it’s destination from “150.1.2.100” to “150.1.1.1”. The resulting packet has src=”155.1.23.22” and dst=”150.1.1.1”.

Then a packet from R1 (src=”150.1.1.1”, dst=”155.1.23.22”) comes back. Since this packet enters NAT inside interface, a routing lookup is performed first, and the static route configured is used to route incoming packet to Loopback0 interface. Without the static route, R2 will attempt to route the packet either to itself (by default) or back to R3 (with no-alias keyword configured for NAT entry). So the static route saves the day, and packet source is translated using NAT inside rule (from “150.1.1.1” to “150.1.2.100”). After that, packet loops back to R2 and has it’s destination translated using NAT outside rule (from “155.1.23.22” to “150.1.2.2”). Looks fine.

Now what would happen if we remove the static route?

R2:
access-list 100 permit tcp any any eq telnet
access-list 100 permit tcp any eq telnet any

Rack1R2#debug ip packet detail 100
IP packet debugging is on (detailed) for access list 100
Rack1R2#debug ip nat detailed
IP NAT detailed debugging is on
Rack1R2#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
Rack1R2(config)#no ip route 155.1.23.22 255.255.255.255 150.1.2.254
Rack1R2(config)#^Z

Rack1R2#telnet 150.1.2.100
Trying 150.1.2.100 ...
!
! TCP SYN packet leaves R2, destination/source translated
!
NAT: o: tcp (150.1.2.2, 45879) -> (150.1.2.100, 23) [14437]
NAT: s=150.1.2.2->155.1.23.22, d=150.1.2.100 [14437]
NAT: s=155.1.23.22, d=150.1.2.100->150.1.1.1 [14437]

IP: tableid=0, s=155.1.23.22 (local), d=150.1.1.1 (Serial0/1), routed via FIB
IP: s=155.1.23.22 (local), d=150.1.1.1 (Serial0/1), len 44, sending
    TCP src=45879, dst=23, seq=1022925953, ack=0, win=4128 SYN
IP: tableid=0, s=150.1.1.1 (Serial0/1), d=155.1.23.22 (Serial0/1), routed via RIB

!
! Reply packet comes back from R1, destined to 155.1.23.22. Since we don’t have
! a static route to send this packet for NAT translation, but we have a local alias
! the router accepts the packet. But the destination address if 155.1.23.22, while
! the TCP session was sourced from 150.1.2.2. Therefore, the router sends an RST.
!
IP: s=150.1.1.1 (Serial0/1), d=155.1.23.22 (Serial0/1), len 44, rcvd 3
    TCP src=23, dst=45879, seq=3088708722, ack=1022925954, win=4128 ACK SYN
IP: tableid=0, s=155.1.23.22 (local), d=150.1.1.1 (Serial0/1), routed via FIB

IP: s=155.1.23.22 (local), d=150.1.1.1 (Serial0/1), len 40, sending
    TCP src=45879, dst=23, seq=1022925954, ack=0, win=0 RST

% Connection timed out; remote host not responding

!
! ICMP pings still work! This is because router will accept reply to any of it’s IP addresses
!

Rack1R2#ping 150.1.2.100

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

With the two translations but no static route, the “inside” translation never kicks in (no “NAT: i” message) since the packet is routed to router itself. This is the way inside NAT works, and this breaks TCP connections, but ICMP is still working.

Okay but maybe that special outside translation that changes the IP address of R2 from “150.1.2.2” to “155.1.23.22” is not needed at all? Let’s remove it too, leaving ourselves with just one translation, and test connectivity again:

Rack1R2(config)#no ip nat outside source static 150.1.2.2 155.1.23.22
Rack1R2(config)#^Z
Rack1R2#
NAT: deleting alias for 155.1.23.22
NAT: deleting alias from redundancy list for 155.1.23.22
ipnat_remove_static_cfg: id 35, flag A

Rack1R2#telnet 150.1.2.100
Trying 150.1.2.100 ...
!
! Packet is translated using outside direction.. TCP session to 150.1.2.100
! is redirected to 150.1.1.1
!
NAT: o: tcp (150.1.2.2, 42616) -> (150.1.2.100, 23) [62052]
NAT: s=150.1.2.2, d=150.1.2.100->150.1.1.1 [62052]

IP: tableid=0, s=150.1.2.2 (local), d=150.1.1.1 (Serial0/1), routed via FIB
IP: s=150.1.2.2 (local), d=150.1.1.1 (Serial0/1), len 44, sending
    TCP src=42616, dst=23, seq=874820746, ack=0, win=4128 SYN
IP: tableid=0, s=150.1.1.1 (Serial0/1), d=150.1.2.2 (Loopback0), routed via RIB

!
! A reply arrives.. but it’s sourced from 150.1.1.1 and destined to 150.1.2.2.
! What that means is that R2 attempts to accept packet to it’s own IP address,
! but since it never initiated a connection to 150.1.1.1 (only to 150.1.2.100)
! the response is dropped and RST is sent!
!
IP: s=150.1.1.1 (Serial0/1), d=150.1.2.2, len 44, rcvd 4
    TCP src=23, dst=42616, seq=2431427125, ack=874820747, win=4128 ACK SYN

IP: tableid=0, s=150.1.2.2 (local), d=150.1.1.1 (Serial0/1), routed via FIB
IP: s=150.1.2.2 (local), d=150.1.1.1 (Serial0/1), len 40, sending
    TCP src=42616, dst=23, seq=874820747, ack=0, win=0 RST

% Connection timed out; remote host not responding

!
! Pings still work, since router accepts responses from any IP
!
Rack1R2#ping 150.1.2.100

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

Now you see, that in order to make router perform “loopback NAT” you need two NAT rules and a static route. All this is pretty explainable if you look at the way inside and outside NAT work. And if you want more NAT scenarios, watch out for our soon-to-be released “IP Services” section of IEWB-RS VOL1 v5 Beta.

Tags: , , ,

Feb
15

Quite many people don’t pay attention to the difference in handling packets on interfaces configured for NAT inside and outside. Here is an example to demonstrate how NAT “domains” interact with routing. Consider three routers connected in the following manner:

nat-inside-outside

For this scenario we have no routing configured. Let’s use static NAT to provide connectivity between R1 and R2. R2 would see R1 as a host on local connected segment with the IP address 155.1.23.1 and R1 would see R2 as a host on it’s local segment with the IP address 155.1.13.2. This goal could be achieved with the following configuration:


R3:
!
interface Serial 1/0.301 point-to-point
 ip address 155.1.13.3 255.255.255.0
 ip nat inside
 no ip route-cache
!
interface Serial 1/0.302 multipoint
 ip address 155.1.23.3 255.255.255.0
 frame-relay map ip 155.1.23.2 302
 ip nat outside
 no ip route-cache

!
! Static NAT: translations are effectively bi-directional
!
ip nat inside source static 155.1.13.1 155.1.23.1
ip nat outside source static 155.1.23.2 155.1.13.2

R2:
!
! Add a Frame-Relay mapping for the new IP (representing R1)
! so that R2 would know how to reach the address over multipoint FR interface
!
interface Serial 1/0.203 multipoint
 ip address 155.1.23.2 255.255.255.0
 frame-relay map ip 155.1.23.3 203
 frame-relay map ip 155.1.23.2 203

Let’s see how it’s working. Note that we disabled route-cache on both interfaces to intercept packets via CPU.


Rack1R3#debug ip nat detailed
IP NAT detailed debugging is on

Rack1R3#debug ip packet detail
IP packet debugging is on (detailed)

Rack1R2#ping 155.1.23.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 155.1.23.1, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)

Hmm…it fails. Look at the debugging output on R3:


Rack1R3#
!
! Packet on NAT outside (o - for outside) hits the interface
!
NAT*: o: icmp (155.1.23.2, 16) -> (155.1.23.1, 16) [84]

!
! Source and destination for the packet rewritten according to NAT rules
!
NAT*: s=155.1.23.2->155.1.13.2, d=155.1.23.1 [84]
NAT*: s=155.1.13.2, d=155.1.23.1->155.1.13.1 [84]

!
! The packet is routed after translation (with new source and destination IPs). Note that routing decision
! and the actual forwarding take place only after translation rules were triggered by NAT tables
!
P: tableid=0, s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), routed via RIB
IP: s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), g=155.1.13.1, len 100, forward
    ICMP type=8, code=0
!
! The response packet from R1 comes in - to destination 155.1.13.2 -  routed via RIB (to the same interface)
! But no NAT rules were triggered since the destination interface is the same as input interface!
!
IP: tableid=0, s=155.1.13.1 (Serial1/0.301), d=155.1.13.2 (Serial1/0.301), routed via RIB
IP: s=155.1.13.1 (Serial1/0.301), d=155.1.13.2 (Serial1/0.301), len 100, rcvd 3
    ICMP type=0, code=0

OK hold here for a second.. Now we recall that for inside NAT routing is tried first, and only then the packet is translated according to the NAT rules. This is how the NAT order of operations works on the inside. So now it’s clear: IOS first tries to route packet to 155.1.13.2 – which is the same interface as it came in.. therefore the inside->outside translation never occurs! To fix this, let’s add a static route on R3:


R3:
ip route 155.1.13.2 255.255.255.255 155.1.23.2

Verification:


Rack1R2#ping 155.1.23.1

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

Rack1R3#
!
! Outside: translate & route
!
NAT*: o: icmp (155.1.23.2, 17) -> (155.1.23.1, 17) [89]
NAT*: s=155.1.23.2->155.1.13.2, d=155.1.23.1 [89]
NAT*: s=155.1.13.2, d=155.1.23.1->155.1.13.1 [89]

!
! Routing decision and forwarding
!
IP: tableid=0, s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), routed via RIB
IP: s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), g=155.1.13.1, len 100, forward
    ICMP type=8, code=0
!
! Inside: Routing decision - the packet is routed using our fixup static route
!
IP: tableid=0, s=155.1.13.1 (Serial1/0.301), d=155.1.13.2 (Serial1/0.302), routed via RIB

!
! NAT rule (i - for inside) is triggered by the packet
!
NAT: i: icmp (155.1.13.1, 17) -> (155.1.13.2, 17) [89]     

!
! Source and destination addresses rewritten in the "opposite" direction
!
NAT: s=155.1.13.1->155.1.23.1, d=155.1.13.2 [89]
NAT: s=155.1.23.1, d=155.1.13.2->155.1.23.2 [89]

!
! Packet is sent to R2 (with the new source and destination) - forwarding takes place
!
IP: s=155.1.23.1 (Serial1/0.301), d=155.1.23.2 (Serial1/0.302), g=155.1.23.2, len 100, forward
    ICMP type=0, code=0

Nice. So now we know the difference for sure: packets on the NAT outside are first translated and then routed. On the inside interface routing decision kicks in first and only then translation rules get applied followed by forwarding. Before we finish with that, recall new 12.3T feature called NAT Virtual Interface. With this feature we can now configure any interface as “NAT enabled” an get rid of those “inside” and “outside” domains . All NAT traffic passed through new virtual interface called NVI, in symmetric manner. Let’s reconfigure out task using this new concepts.


R3:
interface Serial 1/0.301 point-to-point
 no ip nat inside
 ip nat enable
!
interface Serial 1/0.302 multipoint
 no ip nat outside
 ip nat enable

!
!  Remove old rules
!
no ip nat inside source static 155.1.13.1 155.1.23.1
no ip nat outside source static 155.1.23.2 155.1.13.2

!
! Add "domainless" rules
!
ip nat source static 155.1.13.1 155.1.23.1
ip nat source static 155.1.23.2 155.1.13.2

no ip route 155.1.13.2 255.255.255.255 155.1.23.2

Verification:


Rack1R2#ping 155.1.23.1                 

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

Rack1R3#
!
! Routing decision it taken: packet classified for NAT, since destination is in NAT table
! Note that no actual forwarding occurs, just routing decision to send packet
!
IP: tableid=0, s=155.1.23.2 (Serial1/0.302), d=155.1.23.1 (Serial1/0.302), routed via RIB

!
! Packet translated according to NAT rules (note "i" for inside NAT)
!
NAT: i: icmp (155.1.23.2, 19) -> (155.1.23.1, 19) [95]
NAT: s=155.1.23.2->155.1.13.2, d=155.1.23.1 [95]
NAT: s=155.1.13.2, d=155.1.23.1->155.1.13.1 [95]

!
! Another routing decision, for translated packet - now actual forwarding occurs
!
IP: tableid=0, s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), routed via RIB
IP: s=155.1.13.2 (Serial1/0.302), d=155.1.13.1 (Serial1/0.301), g=155.1.13.1, len 100, forward
    ICMP type=8, code=0

!
! Response comes in, first routing decision - NAT table entry matched
!
IP: tableid=0, s=155.1.13.1 (Serial1/0.301), d=155.1.13.2 (Serial1/0.301), routed via RIB

!
! Packet translated ("i" - inside NAT)
!
NAT: i: icmp (155.1.13.1, 19) -> (155.1.13.2, 19) [95]
NAT: s=155.1.13.1->155.1.23.1, d=155.1.13.2 [95]
NAT: s=155.1.23.1, d=155.1.13.2->155.1.23.2 [95]

!
! Another routing decision, for post-translated packet, followed by forwarding
!
IP: tableid=0, s=155.1.23.1 (Serial1/0.301), d=155.1.23.2 (Serial1/0.302), routed via RIB
IP: s=155.1.23.1 (Serial1/0.301), d=155.1.23.2 (Serial1/0.302), g=155.1.23.2, len 100, forward
    ICMP type=0, code=0

So what’s the difference with NVI? First, we see that now NAT behaves symmetrically. Next, we see that NAT translation tables are used to take a “routing decision” to send packet to virtual interface. Packet is translated there and then another routing decision takes place, followed by packet forwarding. So the difference from the old model is that now routing decision is taken twice: before and after translation. This allows to get rid of any static routes needed by “legacy” NAT, since lookup is performed after translation.

To summarize: Domain-based NAT uses different orders of operations for inside and outside domain. NVI based NAT is symmetrical and performs routing lookup twice: first to send packet to NVI, second to route packet using the post-translated addresses.

Links:

NAT Order of Operation

Tags: , , , ,

Categories

CCIE Bloggers