# Network Address Translation (NAT) #

Network Address Translation (NAT) it’s a feature that – raw speaking – works translating an IP address x.x.x.x into another and different IP address y.y.y.y. Approaching NAT for the first time may be confusing due to its terminology and working technology. In my opinion, first things to be cleared when playing with NAT are the concept of INSIDE/OUTSIDE and NAT ORDER of OPERATIONS.

In many documents describing what NAT can be used for, you will see INSIDE it’s your local network, OUTSIDE it’s the INTERNET or something external to your network. This type of definitions are not the best IMHO, these definitions derive from the use you can do of NAT, but it is only a limited vision.

First thing you should think about when you use NAT should be:

1] NAT ==> I’m configuring my device to TRANSLATE an IP Address x.x.x.x to an IP Address y.y.y.y when some conditions are satisfied.

Second thing to remember should be:

2] A NAT Translation can happen only if the packet flows from an INSIDE INTERFACE through an OUTSIDE INTERFACE, in other words, NAT works if packet it’s received on an INSIDE INTERFACE and is ROUTED OUT an OUTSIDE INTERFACE and/or VICEVERSA

3] Defining an interface as INSIDE or OUTSIDE it’s completely arbitrary, you can define as INSIDE the interface that faces your INTERNET connection, INSIDE and OUTSIDE definitions have impact only on what you are trying to implement with NAT service, you router doesn’t know where INTERNET is.

4] NAT has some naming convention you have to learn to understand and troubleshoot NAT when you use some debugs or other shows.

LOCAL ADDRESS: A local address is any address that appears on the INSIDE portion of the network.

GLOBAL ADDRESS: A global address is any address that appears on the OUTSIDE portion of the network.

Then, first thing to know is: How can I define the INSIDE and OUTSIDE portion of the network? Answer it’s rather simple. In NAT words we have two subinterface commands to define which is the INSIDE network and which is the OUTSIDE networks, these two commands are:

==> IP NAT INSIDE
==> IP NAT OUTSIDE

Following Picture shows the concept:

nat-pic1

Inside network is the portion of network attached to the interface configured with ‘ip nat inside’ command, outside network is the portion of network attached to the interface configured with ‘ip nat outside’ command, we can see that definition of INSIDE/OUTSIDE exists before knowing where INTERNET is.

Now, putting together INSIDE/OUTSIDE and LOCAL/GLOBAL all NAT documents will refer to:

==> INSIDE LOCAL ADDRESS
==> INSIDE GLOBAL ADDRESS
==> OUTSIDE LOCAL ADDRESS
==> OUTSIDE GLOBAL ADDRESS

The four definitions have some meaning considering them with some sort of interpretation. For example consider the case below where no NAT is in place, and where we are using PUBLIC IP ADDRESS to connect a network to another, one network is My-Small-Office and other network is the ISP (MyISP) giving me IP connectivity to the rest of the world.

nat-pic2

Here INSIDE and OUTSIDE are two words that have sense based on who is looking the two connecting networks. If I’m the network manager of My-Small-Office, INSIDE it’s what is internal to my office and OUTSIDE it’s all external to my small office. If instead I look at the same diagram from ISP’s network manager point of view, INSIDE it’s what is internal to the ISP and OUTSIDE is what is external to the ISP network; then, when you are defining NAT operations, DEFINE first who you are and from which point of view you are looking at the world.

Now, being an ISP’s network manager is a complicated stuff, so here let’s think of us as being owner of our little Small Office. When I look at the whole scenario I see two parts:

INSIDE it’s everything I see as connected to my office, and internally to my office I see IP addresses that are assigned to my pc, IP addresses that are assigned to devices on the ISP network and on ohter rest of the world.

Now consider the case we are pinging from source IP 151.5.0.2 to IP 151.5.0.10:

151.5.0.2 it’s INSIDE (because I’m looking at the world from my office and this address is connected to the inside world)
and it’s LOCAL (because it is an address that APPEARS, in other words, I can see on my local/inside network)
This address can answer the question: Which address can a host on the INSIDE world use to reach that host on the same INSIDE world?

151.5.0.10 it’s OUTSIDE (because I’m looking at the world from my office and this address is connected to the outside world)
– and it’s LOCAL (because it is an address that APPEARS, in other words, I can see it on MY LOCAL/INSIDE network and I can use it to reach a device OUTSIDE my network, it’s a representation of an outside device into my network)
This address can answer the question: Which address can a host on the INSIDE world use to reach that host on the OUTSIDE world?

NOTE: 151.5.0.2 and 151.5.0.10 have two roles in the showed ping, both are SOURCE and DESTINATION addresses based on the fact that the packet is leaving or entering MY INSIDE network but their definition in NAT terms don’t change, they are still LOCAL ADDRESSES (151.5.0.2 inside, 151.5.0.10 outside)

When icmp-echo-request APPEARS on the OUTSIDE network:

151.5.0.2 it’s INSIDE (because I’m looking at the world from my office and this address is connected to the inside world)
– and it’s GLOBAL (because it APPEARS on the OUTSIDE world coming from the INSIDE world, this address represents an inside host to hosts resident in the OUTSIDE world).
This address can answer the question: Which address can a host on the OUTSIDE world use to reach that host on the INSIDE world?

151.5.0.10 it’s OUTSIDE (because I’m looking at the world from my office and this address is connected to the outside world)
– and it’s GLOBAL (because it is an address that APPEARS, in other words, I can see on the OUTSIDE network)
This address can answer the question: Which address can a host on the OUTSIDE world use to reach that host on the same OUTSIDE world?

NOTE: 151.5.0.2 and 151.5.0.10 have two roles in the showed ping, both are SOURCE and DESTINATION addresses based on the fact that the packet is leaving or entering OUTSIDE network
but their definition in NAT terms don’t change, they are still GLOBAL ADDRESSES (151.5.0.2 inside, 151.5.0.10 outside)

To understand better the above concepts, that could be confusing, look at this other picture:

nat-pic3

Now, the game using NAT is translating some IP address in a different IP address. Doing this we are changing how hosts are represented on the INSIDE and/or OUTSIDE network.

Core operations we can do using NAT are:

==> Translating a source address from INSIDE to OUTSIDE
==> Translating a destination address from INSIDE to OUTSIDE
==> Translating a source address from OUTSIDE to INSIDE

Before understanding how this works in terms of configuration commands we need to know about how NAT operations are triggered and at the same time which is the NAT ORDER of operations. NAT is a feature that interacts with other normal router’s operations (e.g. ip routing) so it’s important to know when NAT process, once triggered, starts to work.

FIRST STEP to activate a NAT operation is TO DEFINE INSIDE AND OUTISIDE ZONES.

To do that we must select an INSIDE INTERFACE with the command ‘ip nat inside’ and an OUTSIDE INTERFACE with the command ‘ip nat outside’

The first trigger to NAT Operations it’s a packet belonging to INTERESTING TRAFFIC (Traffic to be translated) that hits an interface configured for NAT.

At this step, routers decides what to do based on which direction NAT is to be performed ==> below is the relevant NAT ORDER OF OPERATION:

WHEN a NAT router performs NAT INSIDE-TO-OUTSIDE Translation, the following operations occur in order:

01. If IPSec is implemented, check input access-list
02. Decryption
03. Check Input Access List
04. Check Input Rate Limit
05. Input Accounting
06. Redirect to Web Cache
07. POLICY ROUTING
08. ROUTING
09. NAT INSIDE-TO-OUTSIDE translation

10. Check Crypto map and mark for encryption
11. Check Output Access List
12. Inspect Context-Based Access Control (CBAC)
13. TCP Intercept
14. Encryption
15. Queueing

Conversely, when a NAT router performs NAT OUTSIDE-TO-INSIDE Translations, the following operations occur in order:

01. If IPSec is implemented, check input access-list
02. Decryption
03. Check Input Access List
04. Check Input Rate Limit
05. Input Accounting
06. Redirect to Web Cache
07. NAT OUTSIDE-TO-INSIDE TRANSLATIONS
08. POLICY ROUTING
09. ROUTING

10. Check Crypto map and mark for encryption
11. Check Output Access List
12. Inspect Context-Based Access Control (CBAC)
13. TCP Intercept
14. Encryption
15. Queueing

As this list shows if INSIDE-TO-OUTSIDE translation is performed:

1] ==> Router MUST HAVE A VALID ROUTING INFORMATION for the DESTINATION OF THE PACKET BEFORE IT CAN START THE NAT TRANSLATION.

This condition is NECESSARY but IS NOT ENOUGH to complete the translation, to condition 1] we MUST ADD this other condition:

2] ==> ROUTING FOR THE PACKET TO BE TRANSLATED MUST DIRECT THE PACKET OUT AN INTERFACE CONFIGURED FOR NAT OUTSIDE

In other words putting 1] and 2] together, if router has not a valid route for the packet’s destination it drops the packet before making any NAT operations; if a valid route exists, it must point to an outgoing interface configured for NAT OUTSIDE, in other words, packet MUST CROSS the ROUTER entering and exiting interfaces configured for NAT.

Conversely, if OUTSIDE-TO-INSIDE Translations must be performed, Router DOES THE TRANSLATION BEFORE ANY ROUTING DECISION.

This interaction between NAT and ROUTING is very important to know and must be remembered.

When the above conditions are met we can set a router to do NAT operations. NAT operations are essentially divided in three main types:

A] STATIC ADDRESS TRANSLATION (STATIC NAT)
==> This type of NAT is used when a SINGLE address needs to be translated to another SINGLE address.
==> This translation can be done in both directions INSIDE ==> OUTSIDE and OUTSIDE ==> INSIDE

B] DYNAMIC ADDRESS TRANSLATION (DYNAMIC NAT)
==> This type of NAT is used when a SINGLE or MORE ADDRESSES need to be translated to a POOL OF ADDRESSES

C] OVERLOADING (PORT ADDRESS TRANSLATION – PAT)
==> This type of NAT is a variation of Dynamic NAT, this variation allows a set of addresses to be translated to a SINGLE address, instead of a pool of addresses (like in Dynamic NAT).

In Dynamic NAT there is always a one-to-one mapping between the address and its translated IP, when the pool of translated IP is exhausted no more translations are possible. With PAT MANY IP addresses are translated to a SINGLE Address (OVERLOAD) and separation between the original IP addresses is provided using a different PORT NUMBER associated with the translated same IP Address.

Again, the above A,B,C sound much more like NAT definitions, but each one has specific mechanism and implications, so to understand better how NAT works, some examples follow.

§§§ STATIC NAT EXAMPLES §§§

Consider the following scenario:

nat-pic4

Here we have a local server at IP 10.0.0.100 that should communicate with a public server on the OUTSIDE/GLOBAL network with IP address 151.5.1.25. First problem we have is that private address are not ROUTABLE on the OUTSIDE/GLOBAL network, NAT solve this problem translating SOURCE ADDRESS of packets originating from my local server into a ROUTABLE ADDRESS on the OUTSIDE portion of the network.

NOTE: Example shows a translation between a Private Address and a Public Address, but this is not mandatory, in other words, NAT doesn’t know if an IP is Public or Private, translation can be done between class of private address too. What must be present is ROUTING between the original and translated address to destinations to be reached. ROUTABLE means we have a valid route not simply a Public Address.

Here the simple test network:

nat-pic5

First we need to define NAT zones:

NAT-ROUTER#sh run int e0/0 | b interface
interface Ethernet0/0
ip address 10.0.0.254 255.255.255.0
ip nat inside

NAT-ROUTER#sh run int e0/1 | b interface
interface Ethernet0/1
ip address 151.5.0.9 255.255.255.252
 ip nat outside

To define NAT static we simple need to map the address that need to be translated to the translated addrees, STATIC NAT is a ONE-TO-ONE MAPPING, before doing that, let’s verify routing on NAT-ROUTER:

Local LAN connectivity to the Local Server is ok:

NAT-ROUTER#ping 10.0.0.100
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.0.0.100, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 2/6/10 ms

Point-to-point Link to ISP-R1 is ok:

NAT-ROUTER#ping 151.5.0.10
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.0.10, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/6/9 ms

Connectivity to the OUSTIDE SERVER

NAT-ROUTER#sh ip route 151.5.1.25
% Subnet not in table

NOTE: NAT-ROUTER has no route to the server

NAT COMMANDS:

NAT-ROUTER(config)#ip nat inside ?
destination  Destination address translation
source       Source address translation

On the inside portion of the network I have two options: SOURCE and DESTINATION.

When SOURCE Keyword is specified we are telling router to do this:

– When a packet arrives at your interface configured with ‘ip nat inside’ command,
— If conditions for NAT operations are satisfied ==> Translate SOURCE IP ADDRESS OF INCOMING PACKET INTO THE SPECIFIED ADDRESS

Conditions for NAT operations, as specified above, are dependent on NAT ORDER of OPERATIONS, since we are doing INSIDE-TO-OUTSIDE we need:

– Routing for the destination
– Routing path must cross interface configured for NAT

As verified above NAT-ROUTER has no route to the destination server, so NAT will fail before router tries to translate the source address. Let’s add translation command and verify this.

NAT-ROUTER(config)#ip nat inside source ?
list       Specify access list describing local addresses
route-map  Specify route-map
static     Specify static local->global mapping

Choose STATIC option:

NAT-ROUTER(config)#ip nat inside source static ?
A.B.C.D  Inside local IP address
esp      IPSec-ESP (Tunnel mode) support
network  Subnet translation
tcp      Transmission Control Protocol
udp      User Datagram Protocol

Choose IP address (A.B.C.D) to translate:

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 ?
A.B.C.D    Inside global IP address
interface  Specify interface for global address

Choose IP address (A.B.C.D) after translation:

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 151.5.0.9 ?
extendable  Extend this translation when used
forced      Delete this entry and its children, even if in use
no-alias    Do not create an alias for the global address
no-payload  No translation of embedded address/port in the payload
redundancy  NAT redundancy operation
route-map   Specify route-map
vrf         Specify vrf
<cr>

We can see that we have many option, but at the most basic level a static translation will be configured with:

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 151.5.0.9

Here we are telling router, when a packet with source address 10.0.0.100 hits your e0/0 interface (configured for nat inside) translate that address into 151.5.0.9

When we configure NAT commands, NAT-ROUTER creates NAT-TABLE in a dynamic (when traffic comes) or static (permanently before any packet comes) based on which type of NAT translation we
are using.
In these tables router keeps mapping between original and translated address.

In this case of STATIC NAT we have:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 151.5.0.9          10.0.0.100         —                —

Here things to review are:

1] Table is created automatically as soon as we enter the command “ip nat inside source static…” before any packet is transmitted from local server (10.0.0.100)

2] Note the naming convention ==> 10.0.0.100 is INSIDE LOCAL, 151.5.0.9 is INSIDE GLOBAL (refer to the previous pictures)

==> INSIDE LOCAL is the address of my local server that other host on my local network can use to reach it locally.

==>INSIDE GLOBAL is the representation of my LOCAL SERVER’s address as it appears on the OUTSIDE/GLOBAL network, hosts on OUTSIDE world can use that address to reach my server from the GLOBAL world.

Let’s turn on debug for NAT and let’s try to nat the address of local server:

NAT-ROUTER#debug ip nat
IP NAT debugging is on

S100#debug ip icmp
ICMP packet debugging is on

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

S100#
*Mar 25 15:13:08.457: ICMP: dst (10.0.0.100) host unreachable rcv from 10.0.0.254
*Mar 25 15:13:08.459: ICMP: dst (10.0.0.100) host unreachable rcv from 10.0.0.254
*Mar 25 15:13:08.462: ICMP: dst (10.0.0.100) host unreachable rcv from 10.0.0.254
*Mar 25 15:13:08.463: ICMP: dst (10.0.0.100) host unreachable rcv from 10.0.0.254
*Mar 25 15:13:08.466: ICMP: dst (10.0.0.100) host unreachable rcv from 10.0.0.254

S100 server try to reach S25 server, since NAT-ROUTER has no route to it, it drops the packet before trying to do any translation because doing INSIDE-TO-OUTSIDE translation router
evaluates routing info before doing NAT, so the debug on NAT-ROUTER shows nothing.

Then, next step it’s to add routing for the remote server on NAT-ROUTER, before doing that I add another link on NAT-ROUTER connecting it to ISP-R3, see here the new topology:

nat-pic6

Now NAT-ROUTER has two physical paths via e0/1 and e0/2 to reach server S25. Nat is configured on e0/1 and not on e0/2:

NAT-ROUTER#sh run int e0/1 | b interface
interface Ethernet0/1
ip address 151.5.0.9 255.255.255.252
ip nat outside

NAT-ROUTER#sh run int e0/2 | b interface
interface Ethernet0/2
ip address 151.5.0.21 255.255.255.252

I add a static route to remote server S25 via e0/2 interface:

NAT-ROUTER(config)#ip route 151.5.1.25 255.255.255.255 151.5.0.22

Now NAT-ROUTER has a valid route to S25:

NAT-ROUTER#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/3/12 ms

Let’s try to do NAT again originating a new ping from S100:

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

Ping is unsuccessful so NAT-ROUTER again is not doing any NAT, debug nat returns no logs, we can verify this on ISP-R4 router:

ISP-R4#
*Mar 25 15:51:43.874: ICMP: dst (10.0.0.100) host unreachable sent to 151.5.1.25
ISP-R4#
*Mar 25 15:51:45.878: ICMP: dst (10.0.0.100) host unreachable sent to 151.5.1.25
ISP-R4#
*Mar 25 15:51:47.877: ICMP: dst (10.0.0.100) host unreachable sent to 151.5.1.25
ISP-R4#
*Mar 25 15:51:49.877: ICMP: dst (10.0.0.100) host unreachable sent to 151.5.1.25
ISP-R4#
*Mar 25 15:51:51.883: ICMP: dst (10.0.0.100) host unreachable sent to 151.5.1.25

We can see that S100 is trying to answer to the original untranslated address 10.0.0.100 since this network is not known outside ISP-R4 drops the packet.

Look instead at what happen if NAT-ROUTER routes packet out the interface configured for NAT (int e0/1):

NAT-ROUTER(config)#no ip route 151.5.1.25 255.255.255.255 151.5.0.22
NAT-ROUTER(config)#ip route 151.5.1.25 255.255.255.255 151.5.0.10

NAT-ROUTER(config)#
*Mar 25 16:22:17.148: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [30]
*Mar 25 16:22:17.158: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [30]
*Mar 25 16:22:17.166: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [31]
*Mar 25 16:22:17.174: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [31]
*Mar 25 16:22:17.176: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [32]
*Mar 25 16:22:17.178: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [32]
*Mar 25 16:22:17.180: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [33]
*Mar 25 16:22:17.181: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [33]
*Mar 25 16:22:17.183: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [34]
*Mar 25 16:22:17.184: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [34]

Now translation works and the NAT table becomes:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 151.5.0.9:7       10.0.0.100:7       151.5.1.25:7       151.5.1.25:7
— 151.5.0.9          10.0.0.100         —                —

Things to underline are:

1] we must have both elements: routing and packet must cross inside and outside interface

2] An entry is created with mapping between translated and original address – Note that 151.5.1.25 is both OUTSIDE LOCAL and OUTSIDE GLOBAL, this means that from my LOCAL Network I can use that address to reach server S25 and that the same address can be used OUTSIDE because that address is GLOBALLY VALID.

3] Two types of translations are performed:
==> Source Address 10.0.0.100 is translated into 151.5.0.9 when it hits INSIDE INTERFACE AFTER ROUTING DECISION
==> Destination Address 151.5.0.9 is translated into 10.0.0.100 when packet comes back onto OUTSIDE INTERFACE BEFORE ROUTING DECISION

4] Only Inside Address are translated

Now, we saw that the entry on the nat table is permanently present until configuration of the ‘ip nat inside source static…’ command is active:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 151.5.0.9          10.0.0.100         —                —

What happens if it’s S25 server to initiate the traffic to server S100? S25 knows that S100 server is reachable on the INSIDE GLOBAL ADDRESS that represent it on OUTSIDE portion of the network. This address is 151.5.0.9, note that this address is kept permanently in the NAT table of NAT-ROUTER, let’s try to ping that address from S25:

S25#ping 151.5.0.9
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.0.9, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/15/34 ms

NAT-ROUTER#
*Mar 25 17:05:26.249: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [0]
*Mar 25 17:05:26.255: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [0]
*Mar 25 17:05:26.289: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [1]
*Mar 25 17:05:26.292: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [1]
*Mar 25 17:05:26.313: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [2]
*Mar 25 17:05:26.315: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [2]
*Mar 25 17:05:26.317: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [3]
*Mar 25 17:05:26.319: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [3]
*Mar 25 17:05:26.321: NAT*: s=151.5.1.25, d=151.5.0.9->10.0.0.100 [4]
*Mar 25 17:05:26.323: NAT*: s=10.0.0.100->151.5.0.9, d=151.5.1.25 [4]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 151.5.0.9:0       10.0.0.100:0       151.5.1.25:0       151.5.1.25:0
— 151.5.0.9          10.0.0.100         —                —

S100#
*Mar 25 17:05:26.252: ICMP: echo reply sent, src 10.0.0.100, dst 151.5.1.25, topology BASE, dscp 0 topoid 0
*Mar 25 17:05:26.291: ICMP: echo reply sent, src 10.0.0.100, dst 151.5.1.25, topology BASE, dscp 0 topoid 0
*Mar 25 17:05:26.314: ICMP: echo reply sent, src 10.0.0.100, dst 151.5.1.25, topology BASE, dscp 0 topoid 0
*Mar 25 17:05:26.318: ICMP: echo reply sent, src 10.0.0.100, dst 151.5.1.25, topology BASE, dscp 0 topoid 0
*Mar 25 17:05:26.322: ICMP: echo reply sent, src 10.0.0.100, dst 151.5.1.25, topology BASE, dscp 0 topoid 0

Note how NAT-Router performs NAT when an outside host initiates the connection too. Above outputs show that when using STATIC NAT we have a ONE-TO-ONE MAPPING and the communication is BIDIRECTIONAL, in other words, communication can be initiated on both side of the network, inside or outside indifferently.

Question that might arise is, how many static entry I can create on a router?

NAT-ROUTER#sh run | s source
ip nat inside source static 10.0.0.100 151.5.0.9

Can I translate the same 10.0.0.100 to another address?

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 151.5.0.10
% 10.0.0.100 already mapped (10.0.0.100 -> 151.5.0.9)

IOS answer is NO.

Can I translate different inside local address to the same IP address?

NAT-ROUTER(config)#ip nat inside source static 10.0.0.1 151.5.0.9
% similar static entry (10.0.0.100 -> 151.5.0.9) already exists

IOS answer is NO.

Can I translate to an address or set of addresses that are not belonging to a subnet connected to the router doing NAT?

IOS answer is YES. Suppose ISP has reserved this subnets to the NAT service for its customer ==> 151.254.0.0/16

Addresses belonging to that network can be considered as virtual addresses that represent some remote customer’s networks somewhere connected to the ISP’s network. On NAT-ROUTER I can
do something like this:

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 151.254.0.100

The INSIDE GLOBAL ADDRESS 151.254.0.100 is not belonging to any of the connected subnets of NAT-ROUTER:

NAT-ROUTER#sh ip route connected | i C
Codes: L – local, C – connected, S – static, R – RIP, M – mobile, B – BGP
C        10.0.0.0/24 is directly connected, Ethernet0/0
C        151.5.0.8/30 is directly connected, Ethernet0/1
C        151.5.0.20/30 is directly connected, Ethernet0/2

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 151.254.0.100      10.0.0.100         —                —

Trying to reach Server S25 from S100 I have:

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

NAT-ROUTER has a valid route for the destination (151.5.1.25) and traffic cross its interfaces configured for NAT, so NAT-ROUTER performs the translation:

NAT-ROUTER#
*Mar 26 14:42:25.622: NAT*: s=10.0.0.100->151.254.0.100, d=151.5.1.25 [0]
NAT-ROUTER#
*Mar 26 14:42:27.623: NAT*: s=10.0.0.100->151.254.0.100, d=151.5.1.25 [1]
NAT-ROUTER#
*Mar 26 14:42:29.625: NAT*: s=10.0.0.100->151.254.0.100, d=151.5.1.25 [2]
NAT-ROUTER#
*Mar 26 14:42:31.628: NAT*: s=10.0.0.100->151.254.0.100, d=151.5.1.25 [3]
NAT-ROUTER#
*Mar 26 14:42:33.644: NAT*: s=10.0.0.100->151.254.0.100, d=151.5.1.25 [4]

We don’t see translation in the reverse direction because in ISP’s network no device has knowledge about IP 151.254.0.100. So here we have a routing problem not a NAT one. To have things working fine we need to add routing info on the ISP’s router connected to the NAT router for that address, for example I can add a static route on ISP-R1 and redistribute it from ISP-R1 to the rest of OUTSIDE network:

ISP-R1(config)#ip route 151.254.0.100 255.255.255.255 151.5.0.9

ISP-R1(config)#router ospf 1
ISP-R1(config-router)#redistribute static subnets

Now the whole outside network knows where 151.254.0.100 is:

ISP-R4#sh ip route ospf | b 151.254
151.254.0.0/32 is subnetted, 1 subnets
O E2     151.254.0.100 [110/20] via 151.5.0.17, 00:01:25, Ethernet0/1
[110/20] via 151.5.0.13, 00:01:25, Ethernet0/0

S100#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/10/26 ms

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 151.254.0.100:1   10.0.0.100:1       151.5.1.25:1       151.5.1.25:1
— 151.254.0.100      10.0.0.100         —                —

Translation works fine.

Let’s modify a little test topology, another ISP router ISP-GW appears and its connected to a shared subnet 151.6.0.8/29 between ISP-R1 and NAT-ROUTER, below the new topology.

nat-pic7

NAT-ROUTER has now a static nat configuration to 151.6.0.12, ISP-R1 is redistributing the shared subnets in OSPF for all other routers. Now we are natting to an IP that is not the address of one of the interface of NAT-ROUTER but is one address belonging to the shared subnet between NAT-ROUTER, ISP-R1 and ISP-GW

NAT-ROUTER#sh run | s ip nat inside source
ip nat inside source static 10.0.0.100 151.6.0.12

Now think about the logic used to ping from S100 to S25, icmp-echo arrives at NAT-ROUTER, it does the translation, packet (s=151.6.0.12, d=151.5.1.25) travel to S25, it comes back via routing to ISP-R1, now ISP-R1 must send the echo-reply to 151.6.0.12 on its shared subnets, to do that it must know which is the MAC Address mapped to 151.6.0.12 so it makes an ARP request, but WHO does answer to this ARP request since 151.6.0.12 is not belonging to any interface?

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

NAT-ROUTER translate the address:

NAT-ROUTER#
*Mar 26 16:59:39.827: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [15]
*Mar 26 16:59:39.833: NAT*: s=151.5.1.25, d=151.6.0.12->10.0.0.100 [15]
*Mar 26 16:59:39.836: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [16]
*Mar 26 16:59:39.839: NAT*: s=151.5.1.25, d=151.6.0.12->10.0.0.100 [16]
*Mar 26 16:59:39.841: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [17]
*Mar 26 16:59:39.843: NAT*: s=151.5.1.25, d=151.6.0.12->10.0.0.100 [17]
*Mar 26 16:59:39.845: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [18]
*Mar 26 16:59:39.848: NAT*: s=151.5.1.25, d=151.6.0.12->10.0.0.100 [18]
*Mar 26 16:59:39.850: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [19]
*Mar 26 16:59:39.853: NAT*: s=151.5.1.25, d=151.6.0.12->10.0.0.100 [19]

and the same NAT-ROUTER replies to the ARP request sent by ISP-R1:

*Mar 26 16:59:39.831: IP ARP: rcvd req src 151.6.0.10 aabb.cc00.0210, dst 151.6.0.12 Ethernet0/1
*Mar 26 16:59:39.831: IP ARP: sent rep src 151.6.0.12 aabb.cc00.0110,
dst 151.6.0.10 aabb.cc00.0210 Ethernet0/1

We can see that NAT-ROUTER WORKS AS A PROXY-ARP FOR THE NATTED IP. As another test I ping ISP-GW:

S100#ping 151.6.0.11
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.6.0.11, timeout is 2 seconds:
.!!!!
Success rate is 80 percent (4/5), round-trip min/avg/max = 3/5/7 ms

Note the first packet lost to resolve ARP request between NAT-ROUTER to ISP-GW

*Mar 26 17:05:54.790: IP ARP: creating incomplete entry for IP address: 151.6.0.11 interface Ethernet0/1
*Mar 26 17:05:54.790: IP ARP: sent req src 151.6.0.9 aabb.cc00.0110,
dst 151.6.0.11 0000.0000.0000 Ethernet0/1
*Mar 26 17:05:54.799: IP ARP: rcvd rep src 151.6.0.11 aabb.cc00.0b00, dst 151.6.0.9 Ethernet0/1

then NAT-ROUTER resolves ARP mapping for 151.6.0.12

*Mar 26 17:05:54.806: IP ARP: rcvd req src 151.6.0.11 aabb.cc00.0b00, dst 151.6.0.12 Ethernet0/1
*Mar 26 17:05:54.806: IP ARP: sent rep src 151.6.0.12 aabb.cc00.0110,
dst 151.6.0.11 aabb.cc00.0b00 Ethernet0/1

We can verifiy that the offered MAC address for IP 151.6.0.12 is the same of interface e0/1 of NAT-ROUTER:

NAT-ROUTER#show ip arp | i aabb.cc00.0110
Internet  151.6.0.9               –   aabb.cc00.0110  ARPA   Ethernet0/1
Internet  151.6.0.12              –   aabb.cc00.0110  ARPA   Ethernet0/1

This happens because when static NAT is configured NAT-ROUTER creates an ip alias for the Natted IP:

NAT-ROUTER#sh ip alias
Address Type             IP Address      Port
Interface                10.0.0.254
Interface                151.5.0.21
Interface                151.6.0.9
Dynamic                  151.6.0.12  ==> Created Alias after NAT configuration

You can choose to not create an ALIAS for the configured INSIDE GLOBAL ADDRESS with the option ‘no-alias’:

NAT-ROUTER(config)#no ip nat inside source static 10.0.0.100 151.6.0.1

NAT-ROUTER(config)#do sh ip alias
Address Type             IP Address      Port
Interface                10.0.0.254
Interface                151.5.0.21
Interface                151.6.0.9

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 151.6.0.12 no-alias

Router doesn’t create alias for IP 151.6.0.12

NAT-ROUTER(config)#do sh ip alias
Address Type             IP Address      Port
Interface                10.0.0.254
Interface                151.5.0.21
Interface                151.6.0.9

Let’s check if NAT works:

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

NAT-ROUTER#debug ip nat
IP NAT debugging is on
NAT-ROUTER#
NAT-ROUTER#debug arp
ARP packet debugging is on

NAT-ROUTER#
*Mar 27 11:07:44.832: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [0]
*Mar 27 11:07:44.835: IP ARP: rcvd req src 151.6.0.10 aabb.cc00.0210, dst 151.6.0.12 Ethernet0/1
NAT-ROUTER#
*Mar 27 11:07:46.833: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [1]
*Mar 27 11:07:46.837: IP ARP: rcvd req src 151.6.0.10 aabb.cc00.0210, dst 151.6.0.12 Ethernet0/1
NAT-ROUTER#
*Mar 27 11:07:48.846: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [2]
*Mar 27 11:07:48.854: IP ARP: rcvd req src 151.6.0.10 aabb.cc00.0210, dst 151.6.0.12 Ethernet0/1
NAT-ROUTER#
*Mar 27 11:07:50.851: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [3]
*Mar 27 11:07:50.854: IP ARP: rcvd req src 151.6.0.10 aabb.cc00.0210, dst 151.6.0.12 Ethernet0/1
NAT-ROUTER#
*Mar 27 11:07:52.852: NAT*: s=10.0.0.100->151.6.0.12, d=151.5.1.25 [4]
*Mar 27 11:07:52.855: IP ARP: rcvd req src 151.6.0.10 aabb.cc00.0210, dst 151.6.0.12 Ethernet0/1

NAT-ROUTER does the translation, but when packet come backs on ISP-R1 this router sends an ARP request for the Natted address, but since we had configured no-alias, NAT-ROUTER cannot works as a proxy-arp and doesn’t reply to this Arp request so ping fails.

If we do:

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 151.6.0.9 no-alias

S100#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 5/6/11 ms

NAT works:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 151.6.0.9:1       10.0.0.100:1       151.5.1.25:1       151.5.1.25:1
— 151.6.0.9          10.0.0.100         —                —

NOTE: the command configuration above that nats to an IP of a connected interface with no-alias option is totally useless because the no-alias keyword does nothing in this case, being the alias already present for the configured interface’s IP. So when no-alias keyword can be used? Consider this other scenario:

nat-pic8

Now we are translating to a not attached subnets’ IP address 192.0.0.100, first thing we must redistribute the route for that address on Outside Network so other devices can get back to it.

NOTE: I changed deafult route on NAT router, so the NAT path will go through e0/0 and e0/2

ISP-R3#show run | s r o
router ospf 1
redistribute static subnets
network 151.5.0.0 0.0.255.255 area 0

ISP-R3(config-router)#ip route 192.0.0.100 255.255.255.255 151.5.0.21

NAT-ROUTER(config)#no ip route 151.5.1.25 255.255.255.255 151.6.0.10
NAT-ROUTER(config)#ip route 151.5.1.25 255.255.255.255 151.5.0.22 –> to ISP-R3

Then adding nat command:

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 192.0.0.100

NAT-ROUTER will create an alias for that INSIDE GLOBAL ADDRESS:

NAT-ROUTER#sh ip alias | i 192
Dynamic                  192.0.0.100

NAT-ROUTER will reply to arp request for that address, but in this case, since address 192.0.0.100 is not belonging to any of the connected subnets of the router performing NAT, when packet comes back to one of the attached routers (via ip routing) no one of these devices will send an ARP request, because they will route to an external (not attached subnet) so the mac they will use will be the one of the next-hop ip for that route. Let’s verify this:

NAT-ROUTER#sh debug
ARP:
ARP packet debugging is on
Generic IP:
IP NAT debugging is on

S100#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 8/10/12 ms

NAT-ROUTER#
*Mar 27 12:28:01.150: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [20]
*Mar 27 12:28:01.152: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [20]
*Mar 27 12:28:01.154: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [21]
*Mar 27 12:28:01.156: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [21]
*Mar 27 12:28:01.162: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [22]
*Mar 27 12:28:01.163: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [22]
*Mar 27 12:28:01.165: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [23]
*Mar 27 12:28:01.166: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [23]
*Mar 27 12:28:01.168: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [24]
*Mar 27 12:28:01.169: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [24]

NAT works perfectly and NAT-ROUTER receive no ARP requests and so doesn’t reply to them. In this case we can use no-alias option to prevent malicious use of ARP reply provide by NAT-ROUTER for the natted address.

NAT-ROUTER#sh run | s ip nat inside source
ip nat inside source static 10.0.0.100 192.0.0.100 no-alias

S100#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 3/4/8 ms

Nat is working:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.100:6     10.0.0.100:6       151.5.1.25:6       151.5.1.25:6
— 192.0.0.100        10.0.0.100         —                —

NOTE: more complex scenario can require the use of no-alias option.

Now, so far I reviewed a simple STATIC NAT Translation from INSIDE-TO-OUTSIDE, mapping an inside local address to an inside global address and creating a bidirectional path between original and translated address; hosts on the outside portion of the network can initiate communication to the inside host using its translated global address to reach it. This is a typical scenario where one internal host works as a server (web, email, file server and son on..) that must be reachable from the outside world.

Static NAT can be used also in a more granular way in this scenario, for example I can use NAT to translate the port to which the application running on the server can be contacted.

nat-pic9

Static NAT configuration becomes:

NAT-ROUTER(config)#ip nat inside source static tcp 10.0.0.100 8888 192.0.0.100 80

NOTE: IOS adds an option to the command when putting it in running config:

NAT-ROUTER#sh run | s extendable
ip nat inside source static tcp 10.0.0.100 8888 192.0.0.100 80 EXTENDABLE

Here is the permanent NAT entry created in the NAT Table:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
tcp 192.0.0.100:80     10.0.0.100:8888    —                —

IOS specifies now tcp ports. Trying to reach the server from host S25:

NOTE: I-m using two routers to simulate simple tcp connections on some ports, so I activate this services:

S100#sh run | s ip http
ip http server
ip http port 8888
ip http authentication local

no ip http secure-server

S100#sh run | s username
username S25 password 0 cisco

S25#sh run | s ip http
no ip http server
no ip http secure-server
ip http client username S25
ip http client password 0 cisco

S25#telnet 192.0.0.100 80
Trying 192.0.0.100, 80 … Open

S100#sh ip http server connection

HTTP server current connections:
local-ipaddress:port  remote-ipaddress:port in-bytes   out-bytes
10.0.0.100:8888       151.5.1.25:50229 0          0

I can open more than one connection to HTTP server, I added a Loopback 25 on S25 and routing for that network:

S25#telnet 192.0.0.100 80 /source e1/0
Trying 192.0.0.100, 80 … Open

S25#telnet 192.0.0.100 80 /source-interface Lo25
Trying 192.0.0.100, 80 … Open

S100#sh ip http server connection

HTTP server current connections:
local-ipaddress:port  remote-ipaddress:port in-bytes   out-bytes
10.0.0.100:8888      25.25.25.25:64514 0          0
10.0.0.100:8888       151.5.1.25:26893 0          0  

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
tcp 192.0.0.100:80     10.0.0.100:8888    25.25.25.25:49154  25.25.25.25:49154
tcp 192.0.0.100:80     10.0.0.100:8888    151.5.1.25:40069   151.5.1.25:40069
tcp 192.0.0.100:80     10.0.0.100:8888    —                —

NOTE: The keyword EXTENDABLE allows static NAT mappings of one INSIDE LOCAL ADDRESS to MULTIPLE INSIDE GLOBAL ADDRESSES

EXTENDABLE keyword lets router to create and EXTENDED version of the NAT TABLE, extended here means the possibility to create entries in the table that have more parameters to associate to the translations so that no ambiguity can cause router to get confused about what to do with a  packet. In the example above the extension are the tcp ports used for the translations.

When doing simple static translations from one address to another router creates a simple entry like this one:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 151.5.0.9          10.0.0.100         —                —

We see at the beginning that is not possible to nat statically to the same local address or to nat statically more different local addresses to the same INSIDE GLOBAL ADDRESS, then look
at this:

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 192.0.0.100 extendable
NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 192.0.0.101 extendable

NAT-ROUTER#sh run | s ip nat inside source
ip nat inside source static 10.0.0.100 192.0.0.100 extendable
ip nat inside source static 10.0.0.100 192.0.0.101 extendable

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 192.0.0.100        10.0.0.100         —                —
— 192.0.0.101        10.0.0.100         —                —

EXTENDABLE gives me the possibility to map statically the same INSIDE LOCAL ADDRESS TO DIFFERENT INSIDE GLOBAL ADDRESS, for example this could be the case where some device on OUTSIDE must reach the same server but with different addresses:

nat-pic10

NAT-ROUTER#sh run | s ip route
ip route 0.0.0.0 0.0.0.0 151.5.0.22
ip route 151.5.1.0 255.255.255.0 151.5.0.22
ip route 151.5.2.0 255.255.255.0 151.6.0.10

S25#ping 192.0.0.100 so 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.0.0.100, timeout is 2 seconds:
Packet sent with a source address of 151.5.1.25
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 3/3/5 ms

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

NAT-ROUTER#
*Mar 30 10:31:30.194: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [5]
*Mar 30 10:31:30.197: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [5]
*Mar 30 10:31:30.199: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [6]
*Mar 30 10:31:30.201: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [6]
*Mar 30 10:31:30.203: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [7]
*Mar 30 10:31:30.206: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [7]
*Mar 30 10:31:30.208: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [8]
*Mar 30 10:31:30.210: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [8]
*Mar 30 10:31:30.211: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.100 [9]
*Mar 30 10:31:30.213: NAT*: s=10.0.0.100->192.0.0.100, d=151.5.1.25 [9]

NAT-ROUTER#
*Mar 30 10:31:40.322: NAT*: s=151.5.2.25, d=192.0.0.101->10.0.0.100 [10]
*Mar 30 10:31:40.324: NAT*: s=10.0.0.100->192.0.0.101, d=151.5.2.25 [10]
*Mar 30 10:31:40.326: NAT*: s=151.5.2.25, d=192.0.0.101->10.0.0.100 [11]
*Mar 30 10:31:40.328: NAT*: s=10.0.0.100->192.0.0.101, d=151.5.2.25 [11]
*Mar 30 10:31:40.331: NAT*: s=151.5.2.25, d=192.0.0.101->10.0.0.100 [12]
*Mar 30 10:31:40.332: NAT*: s=10.0.0.100->192.0.0.101, d=151.5.2.25 [12]
*Mar 30 10:31:40.335: NAT*: s=151.5.2.25, d=192.0.0.101->10.0.0.100 [13]
*Mar 30 10:31:40.337: NAT*: s=10.0.0.100->192.0.0.101, d=151.5.2.25 [13]
*Mar 30 10:31:40.339: NAT*: s=151.5.2.25, d=192.0.0.101->10.0.0.100 [14]
*Mar 30 10:31:40.341: NAT*: s=10.0.0.100->192.0.0.101, d=151.5.2.25 [14]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.100:1     10.0.0.100:1       151.5.1.25:1       151.5.1.25:1
icmp 192.0.0.101:2     10.0.0.100:2       151.5.2.25:2       151.5.2.25:2

— 192.0.0.100        10.0.0.100         —                —
— 192.0.0.101        10.0.0.100         —                —

§§§ DYNAMIC NAT §§§

I saw that with STATIC NAT an entry is created in the NAT table as soon as the configuration is present on NAT router independently from traffic being either present or not. DYNAMIC NAT is  another way to translate from an address(set of addresses) to another address, the keyword Dynamic means that differently from STATIC NAT the translation is present only when INTERESTING TRAFFIC is really flowing through a NAT Router. To configure DYNAMIC NAT we need to:

1] Define INSIDE and OUTSIDE interfaces
2] Define INTERESTING TRAFFIC (Traffic that we would to translate and that will trigger the translation)
3] Define a POOL of ADDRESSES that we use as translated addresses.

To do some tests I added a third PC on the network:

nat-pic11

NAT-ROUTER#sh run int e0/0 | b interface
interface Ethernet0/0
ip address 10.0.0.254 255.255.255.0
 ip nat inside

NAT-ROUTER#sh run int e0/1 | b interface
interface Ethernet0/1
ip address 151.6.0.9 255.255.255.248
 ip nat outside

NAT-ROUTER#sh run int e0/2 | b interface
interface Ethernet0/2
ip address 151.5.0.21 255.255.255.252
ip nat outside

NAT-ROUTER(config)#ip nat inside source list TRAFFIC-TO-NAT pool NAT-POOL

This command tells router to DO TRANSLATIONS FOR TRAFFIC COMING ON THE INSIDE INTERFACE, THE TRANSLATIONS WILL OPERATE ON THE SOURCE IP ADDRESSS OF THE PACKETS MATCHED BY THE ACL NAMED TRAFFIC-TO-NAT, THESE SOURCE ADDRESSES WILL BE TRANSLATED TO A SET OF ADDRESSES DEFINED BY THE POOL NAT-POOL

NOTE: no entry is present yet:

NAT-ROUTER#sh ip nat translations
[empty]

NAT-ROUTER(config)#ip nat pool NAT-POOL ?
A.B.C.D        Start IP address
netmask        Specify the network mask
prefix-length  Specify the prefix length

NAT-ROUTER(config)#ip nat pool NAT-POOL 192.0.0.100 ?
A.B.C.D  End IP address

NAT-ROUTER(config)#ip nat pool NAT-POOL 192.0.0.100 192.0.0.101 ?
netmask        Specify the network mask
prefix-length  Specify the prefix length

NAT-ROUTER(config)#ip nat pool NAT-POOL 192.0.0.100 192.0.0.101 192.0.0.101 prefix-length 24

NOTE: no entry is present yet, also after the pool is defined:

NAT-ROUTER#sh ip nat translations
[empty]

NOTE: The fact that we have no entry after we created the configuration, means that NO DEVICES ON OUTSIDE PORTION OF THE NETWORK CAN ININTIATE A CONNECTION TO THE INSIDE HOSTS, BECAUSE NAT ROUTER DOESN’T KNOW HOW TO HANDLE THE PACKET DIRECTED TO AN INSIDE GLOBAL ADDRESS IF NO NAT ENTRY IS PRESENT. For example if I try to reach one of the PCs from host S25 ping fails:

S25 has a router to the NATTED SPACE 192.0.0.0/24

S25#sh ip route 192.0.0.0
Routing entry for 192.0.0.0/24
Known via “ospf 1”, distance 110, metric 20, type extern 2, forward metric 20
Last update from 151.5.1.4 on Ethernet1/0, 00:21:19 ago
Routing Descriptor Blocks:
* 151.5.2.2, from 1.1.1.1, 00:22:05 ago, via Ethernet0/1
Route metric is 20, traffic share count is 1
151.5.1.4, from 3.3.3.3, 00:21:19 ago, via Ethernet1/0
Route metric is 20, traffic share count is 1

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

S25#traceroute 192.0.0.100
Type escape sequence to abort.
Tracing the route to 192.0.0.100
VRF info: (vrf in name/id, vrf out name/id)
1 151.5.2.2 18 msec
151.5.1.4 7 msec
151.5.2.2 2 msec
2 151.5.0.17 7 msec
151.5.0.1 6 msec
151.5.0.17 7 msec
3 151.6.0.9 8 msec
151.5.0.21 7 msec
151.6.0.9 9 msec
4 151.5.0.21 !H
151.6.0.9 !H
151.5.0.21 !H

Note how the trace stops at NAT-ROUTER interfaces because NAT router has no NAT translation info to use.

NAT-ROUTER(config)#ip access-list extended TRAFFIC-TO-NAT
NAT-ROUTER(config-ext-nacl)#permit ip 10.0.0.0 0.0.0.255 any

The ACL defines the interesting traffic that NAT-ROUTER should translate.

Originating traffic from one of the inside host I have:

PC1#ping 151.5.1.25 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (100/100), round-trip min/avg/max = 2/5/31 ms

NAT-ROUTER#
*Apr 13 10:50:40.572: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.1.25 [0]
*Apr 13 10:50:40.576: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.1 [0]

[….SKIPPED….]
*Apr 13 10:50:41.116: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.1.25 [99]
*Apr 13 10:50:41.117: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.1 [99]

I can see that going from inside to outside NAT-ROUTER does the translations:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.100:0     10.0.0.1:0         151.5.1.25:0       151.5.1.25:0        –> Dynamic NAT entry
— 192.0.0.100        10.0.0.1           —                —                –> Simple NAT entry

After some time the dynamic entry is cleared but the master entry remains in the table:

NAT-ROUTER#
*Apr 13 10:55:34.675: NAT: expiring 192.0.0.100 (10.0.0.1) icmp 1 (1)

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 192.0.0.100        10.0.0.1           —                —

This is the same condition we have wit a static entry, if now I try to ping from a different outside source address (151.5.2.25) the same inside hosts 10.0.0.1 I can do that:

S25#ping 192.0.0.100 so 151.5.2.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.0.0.100, timeout is 2 seconds:
Packet sent with a source address of 151.5.2.25
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 3/6/10 ms

NAT-ROUTER#
*Apr 13 10:57:36.062: NAT*: s=151.5.2.25, d=192.0.0.100->10.0.0.1 [10]
*Apr 13 10:57:36.064: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.2.25 [10]
*Apr 13 10:57:36.070: NAT*: s=151.5.2.25, d=192.0.0.100->10.0.0.1 [11]
*Apr 13 10:57:36.072: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.2.25 [11]
*Apr 13 10:57:36.074: NAT*: s=151.5.2.25, d=192.0.0.100->10.0.0.1 [12]
*Apr 13 10:57:36.076: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.2.25 [12]
*Apr 13 10:57:36.084: NAT*: s=151.5.2.25, d=192.0.0.100->10.0.0.1 [13]
*Apr 13 10:57:36.086: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.2.25 [13]
*Apr 13 10:57:36.089: NAT*: s=151.5.2.25, d=192.0.0.100->10.0.0.1 [14]
*Apr 13 10:57:36.091: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.2.25 [14]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.100:2     10.0.0.1:2         151.5.2.25:2       151.5.2.25:2 
— 192.0.0.100        10.0.0.1           —                —

This is important to understand: When a NAT entry is present in the table Router USES IT if IT NEEDS to use info from that entry. Here no one of the inside address initiated a connection to 151.5.2.25 but 151.5.2.25 can initiate a connection to an already mapped inside host.

Only when the table is EMPTY outside communications is BLOCKED:

NAT-ROUTER#clear ip nat translation *

NAT-ROUTER#sh ip nat translations
[EMPTY]

S25#ping 192.0.0.100 so 151.5.2.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.0.0.100, timeout is 2 seconds:
Packet sent with a source address of 151.5.2.25
UUUUU
Success rate is 0 percent (0/5)

Now the Inside host is Unreachable.

NOTE: By default dynamic translation entry expire after some time of no use (if no OVERLOADING is used), I can change the default timeout of dynamic entry with the command “ip nat translation ‘seconds-value'”. SIMPLE TRANSLATION ENTRY TIMEOUT AFTER 24 HOURS

Another thing to understand with DYNAMIC NAT is that the number of addresses defined in the POOL limits how many inside host can use NAT service, for example here I defined a POOL of
two addresses 192.0.0.100 and 192.0.0.101, if these two addresses are already used, a third host cannot be natted:

PC1#ping 151.5.1.25 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (100/100), round-trip min/avg/max = 2/4/19 ms

PC2#ping 151.5.1.25 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (100/100), round-trip min/avg/max = 2/4/19 ms

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.100:0     10.0.0.1:0         151.5.1.25:0       151.5.1.25:0
— 192.0.0.100        10.0.0.1           —                —
icmp 192.0.0.101:0     10.0.0.2:0         151.5.1.25:0       151.5.1.25:0
— 192.0.0.101        10.0.0.2           —                —

When I try to ping from PC3:

PC3#ping 151.5.1.25 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:

UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU

Success rate is 0 percent (0/100)

Ping fails because translations is not working:

NAT-ROUTER#
*Apr 14 08:28:37.250: NAT: translation failed (A), dropping packet s=10.0.0.3 d=151.5.1.25
*Apr 14 08:28:37.259: NAT: translation failed (A), dropping packet s=10.0.0.3 d=151.5.1.25
*Apr 14 08:28:37.267: NAT: translation failed (A), dropping packet s=10.0.0.3 d=151.5.1.25
*Apr 14 08:28:37.275: NAT: translation failed (A), dropping packet s=10.0.0.3 d=151.5.1.25
[…SKIPPED…]
*Apr 14 08:28:37.974: NAT: translation failed (A), dropping packet s=10.0.0.3 d=151.5.1.25
*Apr 14 08:28:37.986: NAT: translation failed (A), dropping packet s=10.0.0.3 d=151.5.1.25

Translation fails because NAT-ROUTER has no more INSIDE GLOBAL ADDRESSES to use, then when using dynamic NAT the number of inside global addresses defined in the pool sets a limit to the number of possible translations.

To overcome the limitation of Dynamic NAT and to reserve more address space IOS gives me the possibility to use a NAT FEATURE called OVERLOADING. OVERLOADING means using the same INSIDE GLOBAL ADDRESS TO NAT MANY INSIDE LOCAL ADDRESSES.

Configuration is pretty the same used in Dynamic NAT, only one thing that changes is the OVERLOAD Keyword when defining the translation:

Configuration for Dynamic NAT was:

ip nat pool NAT-POOL 192.0.0.100 192.0.0.101 prefix-length 24
ip nat inside source list TRAFFIC-TO-NAT pool NAT-POOL
+ inside and outside interfaces

Configuration for Overloading the Pool is:

NAT-ROUTER(config)#no ip nat inside source list TRAFFIC-TO-NAT pool NAT-POOL
NAT-ROUTER(config)#ip nat inside source list TRAFFIC-TO-NAT pool NAT-POOL overload

New config becomes:

ip nat pool NAT-POOL 192.0.0.100 192.0.0.101 prefix-length 24
ip nat inside source list TRAFFIC-TO-NAT pool NAT-POOL overload

Now when I send concurrent traffic from the 3 PCs I have:

PC1#ping 151.5.1.25 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (100/100), round-trip min/avg/max = 2/7/31 ms

PC2#ping 151.5.1.25 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (100/100), round-trip min/avg/max = 2/7/113 ms

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

And on NAT-ROUTER:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.100:1     10.0.0.1:1         151.5.1.25:1       151.5.1.25:1
icmp 192.0.0.100:0     10.0.0.2:1         151.5.1.25:1       151.5.1.25:0
icmp 192.0.0.100:2     10.0.0.3:1         151.5.1.25:1       151.5.1.25:2

Here we need to notice at least two things:

1) When Overload is used no Simple Nat entry are created only full NAT entry.
2) Router uses only one inside global address and differentiate each translation entry by the value of the ports assigned to each addresses.

We can read the table in this way, each PC sends an icmp packet using udp port number 1, each pc sees the remote server at address 151.5.1.25 on port 1, so packets coming on interface
inside of NAT-ROUTER are:

[S_IP=10.0.0.1,S_PORT=1|D_IP=151.5.1.25,D_PORT=1]
[S_IP=10.0.0.2,S_PORT=1|D_IP=151.5.1.25,D_PORT=1]
[S_IP=10.0.0.3,S_PORT=1|D_IP=151.5.1.25,D_PORT=1]

These packets are translated by NAT-ROUTER:

[S_IP=192.0.0.100,S_PORT=1|D_IP=151.5.1.25,D_PORT=1]
[S_IP=192.0.0.100,S_PORT=0|D_IP=151.5.1.25,D_PORT=0]
[S_IP=192.0.0.100,S_PORT=2|D_IP=151.5.1.25,D_PORT=2]

Using a single address gives me the possibility to translate 64K inside local addresses mapping the id of the translation to 2^16 bit (ports number):

ip nat pool NAT-POOL 192.0.0.100 192.0.0.100 prefix-length 24
ip nat inside source list TRAFFIC-TO-NAT pool NAT-POOL overload

This what happens on NAT-ROUTER:

PC1#ping 151.5.1.25 repeat 5
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/7/19 ms

PC2#ping 151.5.1.25 repeat 5
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/5/10 ms

PC3#ping 151.5.1.25 repeat 5
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/6/11 ms

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.100:3     10.0.0.1:3         151.5.1.25:3       151.5.1.25:3
icmp 192.0.0.100:0     10.0.0.2:3         151.5.1.25:3       151.5.1.25:0
icmp 192.0.0.100:1     10.0.0.3:3         151.5.1.25:3       151.5.1.25:1

NAT-ROUTER# –> 10.0.0.1 to 151.5.1.25
*Apr 14 09:42:47.355: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.1.25 [205]
*Apr 14 09:42:47.357: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.1 [205]
*Apr 14 09:42:47.378: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.1.25 [206]
*Apr 14 09:42:47.380: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.1 [206]
*Apr 14 09:42:47.382: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.1.25 [207]
*Apr 14 09:42:47.384: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.1 [207]
*Apr 14 09:42:47.386: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.1.25 [208]
*Apr 14 09:42:47.388: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.1 [208]
*Apr 14 09:42:47.390: NAT*: s=10.0.0.1->192.0.0.100, d=151.5.1.25 [209]
*Apr 14 09:42:47.392: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.1 [209]

NAT-ROUTER# –> 10.0.0.2 to 151.5.1.25
*Apr 14 09:42:50.123: NAT*: ICMP id=3->0
*Apr 14 09:42:50.123: NAT*: s=10.0.0.2->192.0.0.100, d=151.5.1.25 [205]
*Apr 14 09:42:50.126: NAT*: ICMP id=0->3
*Apr 14 09:42:50.126: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.2 [205]
*Apr 14 09:42:50.133: NAT*: ICMP id=3->0
*Apr 14 09:42:50.133: NAT*: s=10.0.0.2->192.0.0.100, d=151.5.1.25 [206]
*Apr 14 09:42:50.136: NAT*: ICMP id=0->3
*Apr 14 09:42:50.136: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.2 [206]
*Apr 14 09:42:50.138: NAT*: ICMP id=3->0
*Apr 14 09:42:50.138: NAT*: s=10.0.0.2->192.0.0.100, d=151.5.1.25 [207]
*Apr 14 09:42:50.141: NAT*: ICMP id=0->3
*Apr 14 09:42:50.141: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.2 [207]
*Apr 14 09:42:50.143: NAT*: ICMP id=3->0
*Apr 14 09:42:50.143: NAT*: s=10.0.0.2->192.0.0.100, d=151.5.1.25 [208]
*Apr 14 09:42:50.146: NAT*: ICMP id=0->3
*Apr 14 09:42:50.146: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.2 [208]
*Apr 14 09:42:50.148: NAT*: ICMP id=3->0
*Apr 14 09:42:50.148: NAT*: s=10.0.0.2->192.0.0.100, d=151.5.1.25 [209]
*Apr 14 09:42:50.150: NAT*: ICMP id=0->3
*Apr 14 09:42:50.150: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.2 [209]

NAT-ROUTER# –> 10.0.0.3 to 151.5.1.25
*Apr 14 09:42:52.606: NAT*: ICMP id=3->1
*Apr 14 09:42:52.606: NAT*: s=10.0.0.3->192.0.0.100, d=151.5.1.25 [205]
*Apr 14 09:42:52.612: NAT*: ICMP id=1->3
*Apr 14 09:42:52.613: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.3 [205]
*Apr 14 09:42:52.617: NAT*: ICMP id=3->1
*Apr 14 09:42:52.617: NAT*: s=10.0.0.3->192.0.0.100, d=151.5.1.25 [206]
*Apr 14 09:42:52.619: NAT*: ICMP id=1->3
*Apr 14 09:42:52.619: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.3 [206]
*Apr 14 09:42:52.622: NAT*: ICMP id=3->1
*Apr 14 09:42:52.623: NAT*: s=10.0.0.3->192.0.0.100, d=151.5.1.25 [207]
*Apr 14 09:42:52.624: NAT*: ICMP id=1->3
*Apr 14 09:42:52.624: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.3 [207]
*Apr 14 09:42:52.627: NAT*: ICMP id=3->1
*Apr 14 09:42:52.627: NAT*: s=10.0.0.3->192.0.0.100, d=151.5.1.25 [208]
*Apr 14 09:42:52.629: NAT*: ICMP id=1->3
*Apr 14 09:42:52.629: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.3 [208]
*Apr 14 09:42:52.632: NAT*: ICMP id=3->1
*Apr 14 09:42:52.632: NAT*: s=10.0.0.3->192.0.0.100, d=151.5.1.25 [209]
*Apr 14 09:42:52.634: NAT*: ICMP id=1->3
*Apr 14 09:42:52.634: NAT*: s=151.5.1.25, d=192.0.0.100->10.0.0.3 [209]

——————- NOTE ———————-
In the first translation NAT-ROUTER doesn’t need to differentiate, because only one translation is in effect, so the id (port) = 3 is the same in the whole NAT Table (for all inside, outside, local, global addresses)

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.100:3     10.0.0.1:3         151.5.1.25:3       151.5.1.25:3
icmp 192.0.0.100:0     10.0.0.2:3         151.5.1.25:3       151.5.1.25:0
icmp 192.0.0.100:1     10.0.0.3:3         151.5.1.25:3       151.5.1.25:1

Then when packets from other PCs come in, NAT-ROUTER must differentiate the entries that it creates so they are not ambiguous, for the second flow from 10.0.0.2 it translates the LOCAL ID 3 into GLOBAL ID 0, the same for the flow from 10.0.0.3, LOCAL-ID 3 is translated into GLOBAL-ID 1
——————- END NOTE ——————-

NOTE: DYNAMIC NAT WITH OVERLOAD IS KNOWN AS PORT ADDRESS TRANSLATION (PAT)

§§§ ADD-ROUTE Option §§§

I see so far, that to have a fully working nat service routing is an essential piece of the NAT puzzle. Based on the direction we are doing NAT (inside to outisde or viceversa) routing comes first than NAT or viceversa. In the above examples I adjust routing in OSPF so that other routers of the network can know were to send packets to reach the NATTED ADDRESS, for example I added two static routes to two of the GLOBAL ADDRESSES used in NAT examples, then I redistributed them in OSPF:

ISP-R1#show ip route static | b 192.
192.0.0.0/32 is subnetted, 2 subnets
S        192.0.0.100 [1/0] via 151.6.0.9
S        192.0.0.101 [1/0] via 151.6.0.9

ISP-R3#show ip route static | b 192.
192.0.0.0/32 is subnetted, 2 subnets
S        192.0.0.100 [1/0] via 151.5.0.21
S        192.0.0.101 [1/0] via 151.5.0.21
ISP-R3#

S25#sh ip route ospf | i E2
E1 – OSPF external type 1, E2 – OSPF external type 2
O E2     192.0.0.100 [110/20] via 151.5.2.2, 00:11:19, Ethernet0/1
O E2     192.0.0.101 [110/20] via 151.5.2.2, 00:11:19, Ethernet0/1

Instead of controlling routing to the NATTED ADDRESSES on non nat-router, I can use an option on the NAT-ROUTER that generate a static route to the IP Addresses used for NAT:

NAT-ROUTER(config)#no ip nat pool NAT-POOL 192.0.0.100 192.0.0.100 prefix-length 24
NAT-ROUTER(config)#ip nat pool NAT-POOL 192.0.0.100 192.0.0.101 prefix-length 24 add-route

The ADD-ROUTE option installs a static route to the network of addresses defined in the pool, this static route points to a Virtual Interface called NAT VIRTUAL INTERFACE – NVI:

NAT-ROUTER#sh ip int brief | ex una
Interface                  IP-Address      OK? Method Status                Protocol
Ethernet0/0                10.0.0.254      YES NVRAM  up                    up
Ethernet0/1                151.6.0.9       YES NVRAM  up                    up
Ethernet0/2                151.5.0.21      YES NVRAM  up                    up
NVI0                       10.0.0.254      YES unset  up                    up      

NAT-ROUTER#show ip route static | i NVI
S     192.0.0.0/24 [0/0] via 0.0.0.0, NVI0

This static route can be redistributed from the NAT-ROUTER in the routing protocol. This solution helps to keep routing info more stable, if the NAT POOL command is removed, the static route is removed too, avoiding to have bogus routes in the network that point to a service no more present.

NAT-ROUTER#sh run | s r o
router ospf 1
redistribute static subnets
network 151.5.0.0 0.0.255.255 area 0
network 151.6.0.0 0.0.255.255 area 0

S25#sh ip route ospf | i E2
E1 – OSPF external type 1, E2 – OSPF external type 2
O E2  192.0.0.0/24 [110/20] via 151.5.2.2, 00:00:13, Ethernet0/1

§§§ IP NAT OUTSIDE §§§

In the above examples I used only INSIDE TRANSLATION using command IP NAT INSIDE (configured for static or dynamic/overload nat). Another option I have to translate address is using
an OUTSIDE translation using command IP NAT OUTSIDE.

NAT-ROUTER(config)#ip nat outside ?
source  Source address translation

NAT-ROUTER(config)#ip nat outside source ?
list       Specify access list describing global addresses
route-map  Specify route-map
static     Specify static global->local mapping

Again, I can do a Static Outside Nat or a Dynamic Outside Nat. Let’s start from a static NAT.

Suppose that hosts connected to SW1 must not know the real global ip address of server S25, we can use NAT to present this server on the INSIDE portion of the network as it had IP address 192.0.0.25.  Hosts will send packets to address 192.0.0.25, NAT-ROUTER must translate this address to a Global Routable Address, to do that I can use IP NAT OUSTIDE:

NAT-ROUTER(config)#ip nat outside ?
source  Source address translation

NAT-ROUTER(config)#ip nat outside source ?
list       Specify access list describing global addresses
route-map  Specify route-map
static     Specify static global->local mapping

 NAT-ROUTER(config)#ip nat outside source static ?
A.B.C.D  Outside global IP address
network  Subnet translation
tcp      Transmission Control Protocol
udp      User Datagram Protocol

NAT-ROUTER(config)#ip nat outside source static 151.5.1.25 ?
A.B.C.D  Outside local IP address

NAT-ROUTER(config)#ip nat outside source static 151.5.1.25 192.0.0.25

After this configuration NAT-ROUTER creates this NAT TABLE:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— —                —                192.0.0.25         151.5.1.25

We can see a simple entry with IP address 151.5.1.25 mapped to 192.0.0.25. A host connected to SW1 will use 192.0.0.25 as destination IP address to reach S25. Nat configuration is:

NAT-ROUTER#sh run int e0/0
interface Ethernet0/0
ip address 10.0.0.254 255.255.255.0
 ip nat inside
end

NAT-ROUTER#sh run int e0/1
interface Ethernet0/1
ip address 151.6.0.9 255.255.255.248
 ip nat outside
end

NAT-ROUTER#sh run int e0/2
interface Ethernet0/2
ip address 151.5.0.21 255.255.255.252
 ip nat outside
end

NAT-ROUTER#sh run | s source
ip nat outside source static 151.5.1.25 192.0.0.25

Let’s follow a ping packet from PC1 (10.0.0.1) to S25 (151.5.1.25 Known as 192.0.0.25 on INSIDE NETWORK)

packet [S=10.0.0.1, D=192.0.0.5] comes on int e0/0 of NAT-ROUTER, E0/0 is configured for NAT INSIDE so routers check first if a valid route to the destination exists:

NAT-ROUTER#sh ip route 192.0.0.25
Routing entry for 192.0.0.25/32
Known via “static”, distance 1, metric 0
Redistributing via ospf 1
Advertised by ospf 1 subnets
Routing Descriptor Blocks:
* 151.6.0.10
Route metric is 0, traffic share count is 1
151.5.0.22
Route metric is 0, traffic share count is 1

I added two static routes for the /32 address 192.0.0.25 pointing to ISP-R1 and ISP-R3 and I redistributed them in OSPF. Knowing the route for the destination address NAT-ROUTER does the translation. What changes in this example is that I have a NAT OUTSIDE SOURCE STATIC COMMAND, WHEN THIS COMMAND IS CONFIGURED AND THE PACKET IS GOING FROM INSIDE TO OUTSIDE, NAT-ROUTER TRANSLATES DESTINATION IP ADDRESS OF THE PACKET WITH THE MAPPED ADDRESS, in this case address 192.0.0.25 will be translated into 151.5.1.25, so the packet going out from interface e0/1 of NAT-ROUTER will be (after routing decision is made first and then nat translation is done):

[S=10.0.0.1, D=151.5.1.25] –> this packet travels routed at each hop reaching S25, the reply packet from S25 will be:

[S=151.5.1.25, D=10.0.0.1] –> here we have the first problem of routing, because inside network 10.0.0.0/24 is not routed. We can see this doing some debugs:

Ping from PC1 is KO:

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

NAT-ROUTER does the translation:

NAT-ROUTER#
*Apr 16 15:26:58.291: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [0]
NAT-ROUTER#
*Apr 16 15:27:00.296: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [1]
NAT-ROUTER#
*Apr 16 15:27:02.294: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [2]
NAT-ROUTER#
*Apr 16 15:27:04.298: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [3]
NAT-ROUTER#
*Apr 16 15:27:06.300: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [4]

Note that from INSIDE-TO-OUTSIDE is the destination address that is translated (because NAT OUTSIDE SOURCE is configured)

When packet arrives at S25 it uses its default route to reply

S25#sh ip route 0.0.0.0
Routing entry for 0.0.0.0/0, supernet
Known via “static”, distance 1, metric 0, candidate default path
Routing Descriptor Blocks:
* 151.5.1.4
Route metric is 0, traffic share count is 1

but then ISP-R4 discard the packet because it has no route to 10.0.0.0/24:

S25#
*Apr 16 15:26:58.292: ICMP: echo reply sent, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 15:26:58.294: ICMP: dst (151.5.1.25) host unreachable rcv from 151.5.1.4
*Apr 16 15:27:00.300: ICMP: echo reply sent, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 15:27:00.306: ICMP: dst (151.5.1.25) host unreachable rcv from 151.5.1.4
*Apr 16 15:27:02.295: ICMP: echo reply sent, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 15:27:02.301: ICMP: dst (151.5.1.25) host unreachable rcv from 151.5.1.4
*Apr 16 15:27:04.300: ICMP: echo reply sent, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 15:27:04.301: ICMP: dst (151.5.1.25) host unreachable rcv from 151.5.1.4
*Apr 16 15:27:06.305: ICMP: echo reply sent, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 15:27:06.312: ICMP: dst (151.5.1.25) host unreachable rcv from 151.5.1.4

Just as an example I add routing for the subnet 10.0.0.0/24 adding it on OSPF process on NAT-ROUTER:

NAT-ROUTER(config)#router ospf 1
NAT-ROUTER(config-router)#net 10.0.0.0 0.0.0.255 area 1

Fixing routing we have NAT working:

PC1#ping 192.0.0.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.0.0.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/7/18 ms

NAT-ROUTER#
*Apr 16 15:40:17.303: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [5]
*Apr 16 15:40:17.310: NAT*: s=151.5.1.25->192.0.0.25, d=10.0.0.1 [5]
*Apr 16 15:40:17.321: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [6]
*Apr 16 15:40:17.322: NAT*: s=151.5.1.25->192.0.0.25, d=10.0.0.1 [6]
*Apr 16 15:40:17.324: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [7]
*Apr 16 15:40:17.326: NAT*: s=151.5.1.25->192.0.0.25, d=10.0.0.1 [7]
*Apr 16 15:40:17.328: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [8]
*Apr 16 15:40:17.330: NAT*: s=151.5.1.25->192.0.0.25, d=10.0.0.1 [8]
*Apr 16 15:40:17.332: NAT*: s=10.0.0.1, d=192.0.0.25->151.5.1.25 [9]

*Apr 16 15:40:17.335: NAT*: s=151.5.1.25->192.0.0.25, d=10.0.0.1 [9]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— —                —                192.0.0.25         151.5.1.25
icmp 10.0.0.1:1        10.0.0.1:1         192.0.0.25:1       151.5.1.25:1

————- NOTE ————–
When reply packet from S25 comes back on NAT-ROUTER the packet is:

[S=151.5.1.25, D=10.0.0.1] –> this packet hit one of the interface configured with NAT OUTSIDE, so NAT-ROUTER does first the translation reading in its NAT TABLE, and SINCE WE ARE IN OUTSIDE-TO-INSIDE DIRECTION AND OUTSIDE SOURCE IS CONFIGURED IT TRANSLATES THE SOURCE IP OF THE PACKET

*Apr 16 15:40:17.310: NAT*: s=151.5.1.25->192.0.0.25, d=10.0.0.1 [5]

After the translation NAT-ROUTER performs routing for destination ip 10.0.0.1 and sends the packet out of interface e0/0.
———— END NOTE ———–

In a more real scenario network 10.0.0.0/24 will not be routed outside, I can use nat one more time also on the inside part so we have a double translation also for source IP coming on the inside interface of NAT-ROUTER:

NAT-ROUTER(config)#ip nat pool INSIDE-GLOBAL 192.0.0.101 192.0.0.254 prefix-length 24 add-route

The add-route option creates a static route for the network 192.0.0.0/24

NAT-ROUTER#sh ip route static | b 192
192.0.0.0/24 is variably subnetted, 2 subnets, 2 masks
S        192.0.0.0/24 [0/0] via 0.0.0.0, NVI0
S        192.0.0.25/32 [1/0] via 151.6.0.10
[1/0] via 151.5.0.22

NOTE: I left the more specific route to 192.0.0.25/32 otherwise NAT OUTSIDE will never works because when packet comes on E0/0 NAT-ROUTER will not have a valid route and before translating it drops the packet. Really other routers of the network will never use this route because they will never reply to a packet with source address 192.0.0.25 (if other nat inside config is not misconfigured), this route is useful only to let NAT-ROUTER perform the destination translation when going from inside-to-outside due to the “ip nat oustside source..” command. I remove also routing for network 10.0.0.0/24 in OSPF because it is no more useful:

NAT-ROUTER(config)#router ospf 1
NAT-ROUTER(config-router)#no network 10.0.0.0 0.0.0.255 area 1

NAT-ROUTER#show access-lists –> defines inside traffic to translate
Extended IP access list TRAFFIC-TO-NAT
10 permit ip 10.0.0.0 0.0.0.255 any

NAT-ROUTER(config)#ip nat inside source list TRAFFIC-TO-NAT pool INSIDE-GLOBAL

NAT-ROUTER#show run | s ip nat
ip nat inside  –> e0/0
ip nat outside –> e0/1
ip nat outside –> e0/2
ip nat pool INSIDE-GLOBAL 192.0.0.101 192.0.0.254 prefix-length 24 add-route
ip nat inside source list TRAFFIC-TO-NAT pool INSIDE-GLOBAL
ip nat outside source static 151.5.1.25 192.0.0.25

NAT TABLE before doing any translation:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— —                —                192.0.0.25         151.5.1.25

Pinging 192.0.0.25 from PC1:

PC1#ping 192.0.0.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.0.0.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 9/12/18 ms

PC1#
*Apr 16 16:11:35.804: ICMP: echo reply rcvd, src 192.0.0.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 16:11:35.824: ICMP: echo reply rcvd, src 192.0.0.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 16:11:35.837: ICMP: echo reply rcvd, src 192.0.0.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 16:11:35.846: ICMP: echo reply rcvd, src 192.0.0.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 16 16:11:35.855: ICMP: echo reply rcvd, src 192.0.0.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0

NAT-ROUTER does a double translation due to “ip nat inside..” and “ip nat outside…” configurations:

NAT-ROUTER#
*Apr 16 16:11:35.790: NAT*: s=10.0.0.1->192.0.0.101, d=192.0.0.25 [15]
*Apr 16 16:11:35.791: NAT*: s=192.0.0.101, d=192.0.0.25->151.5.1.25 [15]
*Apr 16 16:11:35.796: NAT*: s=151.5.1.25->192.0.0.25, d=192.0.0.101 [15]
*Apr 16 16:11:35.796: NAT*: s=192.0.0.25, d=192.0.0.101->10.0.0.1 [15]
*Apr 16 16:11:35.808: NAT*: s=10.0.0.1->192.0.0.101, d=192.0.0.25 [16]
*Apr 16 16:11:35.808: NAT*: s=192.0.0.101, d=192.0.0.25->151.5.1.25 [16]
*Apr 16 16:11:35.815: NAT*: s=151.5.1.25->192.0.0.25, d=192.0.0.101 [16]
*Apr 16 16:11:35.815: NAT*: s=192.0.0.25, d=192.0.0.101->10.0.0.1 [16]
*Apr 16 16:11:35.826: NAT*: s=10.0.0.1->192.0.0.101, d=192.0.0.25 [17]
*Apr 16 16:11:35.826: NAT*: s=192.0.0.101, d=192.0.0.25->151.5.1.25 [17]
*Apr 16 16:11:35.832: NAT*: s=151.5.1.25->192.0.0.25, d=192.0.0.101 [17]
*Apr 16 16:11:35.832: NAT*: s=192.0.0.25, d=192.0.0.101->10.0.0.1 [17]
*Apr 16 16:11:35.838: NAT*: s=10.0.0.1->192.0.0.101, d=192.0.0.25 [18]
*Apr 16 16:11:35.838: NAT*: s=192.0.0.101, d=192.0.0.25->151.5.1.25 [18]
*Apr 16 16:11:35.840: NAT*: s=151.5.1.25->192.0.0.25, d=192.0.0.101 [18]
*Apr 16 16:11:35.840: NAT*: s=192.0.0.25, d=192.0.0.101->10.0.0.1 [18]
*Apr 16 16:11:35.847: NAT*: s=10.0.0.1->192.0.0.101, d=192.0.0.25 [19]
*Apr 16 16:11:35.847: NAT*: s=192.0.0.101, d=192.0.0.25->151.5.1.25 [19]
*Apr 16 16:11:35.850: NAT*: s=151.5.1.25->192.0.0.25, d=192.0.0.101 [19]
*Apr 16 16:11:35.850: NAT*: s=192.0.0.25, d=192.0.0.101->10.0.0.1 [19]

Look at translation of the first ping packet:

nat-pic12

So from these examples of STATIC INSIDE, DYNAMIC INSIDE, and STATIC OUTSIDE I can recap that:

IP NAT INSIDE SOURCE COMMAND:
[O] TRANSLATES THE SOURCE OF IP PACKETS THAT ARE TRAVELING INSIDE TO OUTSIDE
[O] TRANSLATES THE DESTINATION OF THE IP PACKETS THAT ARE TRAVELING OUTSIDE TO INSIDE

IP NAT OUTSIDE SOURCE COMMAND:
[O] TRANSLATES THE SOURCE OF IP PACKETS THAT ARE TRAVELING OUTSIDE TO INSIDE
[O] TRANSLATES THE DESTINATION OF THE IP PACKETS THAT ARE TRAVELING INSIDE TO OUTSIDE

§§§ IP NAT INSIDE DESTINATION §§§

The “ip nat inside destination…” command can be used in a very specific scenario to load balancing TCP traffic to multiple hosts that appear as only one device to the rest of the network.

To do a simple test I will use this simplified topology:

nat-dest-pic1

Needed NAT configuration is:

NAT-ROUTER#sh run int e1/0 | b interface
interface Ethernet1/0
ip address 10.0.0.254 255.255.255.0
 ip nat inside

NAT-ROUTER#sh run int e1/1 | b interface
interface Ethernet1/1
ip address 60.0.0.1 255.255.255.252
ip nat outside

NAT-ROUTER(config)#ip nat pool LOCAL-SERVERS 10.0.0.1 10.0.0.3 prefix-length 24 type ROTARY
NAT-ROUTER(config)#ip nat inside destination list VIRTUAL-SERVER pool LOCAL-SERVERS

NAT-ROUTER(config)#ip access-list standard VIRTUAL-SERVER
NAT-ROUTER(config-std-nacl)#permit 60.0.0.1

NOTE: The pool that defines the local servers MUST BE OF TYPE ROTARY, this lets NAT-ROUTER to load balance traffic among the different servers. The list permits Global IP address that outside world uses to reach the Server offering the TCP service.

Before traffic flows, no NAT entry is created:

NAT-ROUTER#sh ip nat translations
[EMPTY]

NOTE: THIS TYPE OF TRANSLATION WORKS ONLY IF CONNECTION IS INITIATED ON THE OUTSIDE PART. If I try to reach 30.0.0.1 from Inside:

NAT-ROUTER#debug ip nat
IP NAT debugging is on

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

NOTE: THIS TYPE OF TRANSLATION DOESN’T WORK FOR UDP TRAFFIC, SO IF YOU TEST DOING A PING FROM OUTSIDE NOTHING HAPPENS, IN THIS CASE SINCE WE HAVE ROUTING FROM OUTSIDE TO THE IP ADDRESS 60.0.0.1 WE RECEIVE AN ECHO-REPLY FROM NAT-ROUTER E1/1 INTERFACE, BUT NO TRANSLATION OCCURS, se here:

NAT-ROUTER#sh debug
Generic IP:
IP NAT debugging is on

S1#ping 60.0.0.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 60.0.0.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/4/10 ms

NAT-ROUTER#sh ip nat translations
NAT-ROUTER#

TRANSLATION FOR DESTINATION NAT WORKS ONLY FOR TCP TRAFFIC. I configured S1,S2,S3 as an HTTP server, allowing telnet traffic

S1(config)#ip http server

S1#sh ip http server status
HTTP server status: Enabled

HTTP server port: 80
HTTP server active supplementary listener ports:
HTTP server authentication method: enable
HTTP server digest algorithm: md5
HTTP server access class: 0
HTTP server base path:
HTTP server help root:
Maximum number of concurrent server connections allowed: 5
Server idle time-out: 180 seconds
Server life time-out: 180 seconds
Maximum number of requests allowed on a connection: 1
Server linger time : 60 seconds
HTTP server active session modules: ALL
HTTP secure server capability: Present
HTTP secure server status: Disabled
HTTP secure server port: 443
HTTP secure server ciphersuite: 3des-ede-cbc-sha des-cbc-sha rc4-128-md5 rc4-128-sha
HTTP secure server client authentication: Disabled
HTTP secure server trustpoint:
HTTP secure server active session modules: ALL

S1#sh ip http server statistics
HTTP server statistics:
Accepted connections total: 0

S1(config)#line vty 0 4
S1(config-line)#no login
S1(config-line)#transport input telnet

Trying a telent connection on port 80 of address 60.0.0.1

HOST-1#telnet 60.0.0.1 80
Trying 60.0.0.1, 80 … Open

get
HTTP/1.1 400 Bad Request
Date: Tue, 21 Apr 2015 09:50:39 GMT
Server: cisco-IOS
Accept-Ranges: none

400 Bad Request
[Connection to 60.0.0.1 closed by foreign host]

NAT-ROUTER#
*Apr 21 09:50:36.015: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23097]
*Apr 21 09:50:36.017: NAT*: s=10.0.0.1->60.0.0.1, d=30.0.0.1 [26046]
*Apr 21 09:50:36.024: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23098]
*Apr 21 09:50:36.032: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23099]
*Apr 21 09:50:36.228: NAT*: s=10.0.0.1->60.0.0.1, d=30.0.0.1 [26047]
*Apr 21 09:50:37.819: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23100]
*Apr 21 09:50:38.028: NAT*: s=10.0.0.1->60.0.0.1, d=30.0.0.1 [26048]
*Apr 21 09:50:38.908: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23101]
*Apr 21 09:50:39.066: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23102]
*Apr 21 09:50:39.069: NAT*: s=10.0.0.1->60.0.0.1, d=30.0.0.1 [26049]
*Apr 21 09:50:39.148: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23103]
*Apr 21 09:50:39.360: NAT*: s=10.0.0.1->60.0.0.1, d=30.0.0.1 [26050]
*Apr 21 09:50:39.695: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23104]
*Apr 21 09:50:39.698: NAT*: s=10.0.0.1->60.0.0.1, d=30.0.0.1 [26051]
*Apr 21 09:50:39.698: NAT*: s=10.0.0.1->60.0.0.1, d=30.0.0.1 [26052]
*Apr 21 09:50:39.702: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23105]
*Apr 21 09:50:39.702: NAT*: s=30.0.0.1, d=60.0.0.1->10.0.0.1 [23106]
*Apr 21 09:50:39.710: NAT*: s=10.0.0.1->60.0.0.1, d=30.0.0.1 [26053]

S1#sh ip http server statistics
HTTP server statistics:
Accepted connections total: 1

I can see NAT-ROUTER performing the translation to the inside local servers address. The NAT Table becomes:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
tcp 60.0.0.1:80        10.0.0.1:80        30.0.0.1:27385     30.0.0.1:27385

NAT-ROUTER#
*Apr 21 09:51:40.808: NAT: expiring 60.0.0.1 (10.0.0.1) tcp 80 (80)

If now I try to do 3 concurrent tcp connections to the TCP port 80 of 60.0.0.1:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
tcp 60.0.0.1:80        10.0.0.1:80        30.0.3.3:48039     30.0.3.3:48039
tcp 60.0.0.1:80        10.0.0.2:80        30.0.0.1:35660     30.0.0.1:35660
tcp 60.0.0.1:80        10.0.0.3:80        30.0.2.2:53267     30.0.2.2:53267

Here I can verify how NAT-ROUTER balance the tcp requests among the 3 local servers.

§§§ IP NAT SUPPORT FOR ROUTE-MAP §§§

When doing NAT we see that we can do translation in both directions inside ==> outside and outside ==> inside, translating source ip address or destination ip address based upon the nat rules implemented. When using nat static or dynamic NAT we use ACL to define interesting traffic to nat, in case of static NAT a simple entry will be created in NAT TABLE, and this entry is always present even if traffic to be translated is not present. With Dynamic NAT full entries will be created “on demand”, when needed by NAT-ROUTER to do the translation. We know also that once an entry is present in the NAT TABLE the entry can be used also by device that strictly don’t match NAT ACL, because NAT ACL is checked only when NAT-ROUTER needs first time an entry to be created. To better understand this I added some device to the topology:

nat-pic13

Now, let’s suppose that PC1 must be translated to different Global IP addresses based on the destination IP address it wants to reach, for example:

10.0.0.1 <==> 192.0.0.X when it sends traffic to network 151.5.1.0/24
10.0.0.1 <==> 193.0.0.Y when it sends traffic to network 200.0.0.0/24

I need to define two different ACLs for interesting traffic:

NAT-ROUTER#sh run | s ip access
ip access-list extended TO-NET-151-5-1
permit ip host 10.0.0.1 151.5.1.0 0.0.0.255
ip access-list extended TO-NET-200
permit ip host 10.0.0.1 200.0.0.0 0.0.0.255

Then I must define the pool:

NAT-ROUTER(config)#ip nat pool POOL-192 192.0.0.1 192.0.0.254 prefix-length 24 add-route

NAT-ROUTER(config)#ip nat pool POOL-193 193.0.0.1 193.0.0.254 prefix-length 24 add-route

ADD-ROUTE Option creates the static routes pointing to NVI interface and I configured OSPF to redistribute the routes.

NAT-ROUTER#sh ip route static | i NVI
S     192.0.0.0/24 [0/0] via 0.0.0.0, NVI0
S     193.0.0.0/24 [0/0] via 0.0.0.0, NVI0

NAT-ROUTER#show ip os database | b Type-5
Type-5 AS External Link States

Link ID         ADV Router      Age         Seq#       Checksum Tag
192.0.0.0       10.10.10.10     363         0x80000001 0x00F0C6 0
193.0.0.0       10.10.10.10     336         0x80000001 0x00E3D2 0

NAT-ROUTER(config)#ip nat inside source list TO-NET-151-5-1 pool POOL-192
NAT-ROUTER(config)#ip nat inside source list TO-NET-200 pool POOL-193

To recap NAT-Config:

NAT-ROUTER#sh run | s ip nat
ip nat inside e0/0
ip nat outside e0/1
ip nat outside e0/2
ip nat pool POOL-192 192.0.0.1 192.0.0.254 prefix-length 24 add-route
ip nat pool POOL-193 193.0.0.1 193.0.0.254 prefix-length 24 add-route
ip nat inside source list TO-NET-151-5-1 pool POOL-192
ip nat inside source list TO-NET-200 pool POOL-193

NAT-ROUTER#sh ip nat translations

NAT-ROUTER#debug ip nat
IP NAT debugging is on

pinging server 151.5.1.25 from PC1:

PC1#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 2/6/20 ms
PC1#

NAT-ROUTER#
*Apr 21 16:13:23.462: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [0]
*Apr 21 16:13:23.468: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [0]
*Apr 21 16:13:23.481: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [1]
*Apr 21 16:13:23.482: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [1]
*Apr 21 16:13:23.486: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [2]
*Apr 21 16:13:23.489: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [2]
*Apr 21 16:13:23.490: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [3]
*Apr 21 16:13:23.491: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [3]
*Apr 21 16:13:23.493: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [4]
*Apr 21 16:13:23.495: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [4]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.1:0       10.0.0.1:0         151.5.1.25:0       151.5.1.25:0
— 192.0.0.1          10.0.0.1           —                —

As usual NAT-ROUTER creates two entry, a full dynamic entry and a simple entry that persists even when full entry expires:

NAT-ROUTER#
*Apr 21 16:14:24.722: NAT: expiring 192.0.0.1 (10.0.0.1) icmp 0 (0)

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 192.0.0.1          10.0.0.1           —                —

ACLs show that NAT-ROUTER used an ACL entry from ACL TO-NET-151-5-1

NAT-ROUTER#show ip access-lists
Extended IP access list TO-NET-151-5-1
10 permit ip host 10.0.0.1 151.5.1.0 0.0.0.255 (1 match)
Extended IP access list TO-NET-200
10 permit ip host 10.0.0.1 200.0.0.0 0.0.0.255

Now look at what happens if PC1 try to reach S200 at 200.0.0.200

PC1#ping 200.0.0.200
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 200.0.0.200, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/6/17 ms

NAT-ROUTER does a translation:

NAT-ROUTER#
*Apr 21 16:17:59.130: NAT*: s=10.0.0.1->192.0.0.1, d=200.0.0.200 [5]
*Apr 21 16:17:59.138: NAT*: s=200.0.0.200, d=192.0.0.1->10.0.0.1 [5]
*Apr 21 16:17:59.147: NAT*: s=10.0.0.1->192.0.0.1, d=200.0.0.200 [6]
*Apr 21 16:17:59.150: NAT*: s=200.0.0.200, d=192.0.0.1->10.0.0.1 [6]
*Apr 21 16:17:59.152: NAT*: s=10.0.0.1->192.0.0.1, d=200.0.0.200 [7]
*Apr 21 16:17:59.154: NAT*: s=200.0.0.200, d=192.0.0.1->10.0.0.1 [7]
*Apr 21 16:17:59.156: NAT*: s=10.0.0.1->192.0.0.1, d=200.0.0.200 [8]
*Apr 21 16:17:59.158: NAT*: s=200.0.0.200, d=192.0.0.1->10.0.0.1 [8]
*Apr 21 16:17:59.161: NAT*: s=10.0.0.1->192.0.0.1, d=200.0.0.200 [9]
*Apr 21 16:17:59.163: NAT*: s=200.0.0.200, d=192.0.0.1->10.0.0.1 [9]

But I can see that the translated address doesn’t belong to NAT pool POOL-193, 10.0.0.1 is still translated to 192.0.0.1

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.1:1       10.0.0.1:1         200.0.0.200:1      200.0.0.200:1
— 192.0.0.1          10.0.0.1           —                —

After some time dynamic NAT expire:

NAT-ROUTER#
*Apr 21 16:19:00.627: NAT: expiring 192.0.0.1 (10.0.0.1) icmp 1 (1)

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 192.0.0.1          10.0.0.1           —                —

We can see also that NAT-ROUTER didn’t used other ACL TO-NET-200 and didn’t use ACL TO-NET-151-5-1 we still have 1 match (the first packet of the first ping done by PC1 to 151.5.1.25)

NAT-ROUTER#show ip access-lists
Extended IP access list TO-NET-151-5-1
10 permit ip host 10.0.0.1 151.5.1.0 0.0.0.255 (1 match)
Extended IP access list TO-NET-200
10 permit ip host 10.0.0.1 200.0.0.0 0.0.0.255

This happens because NAT-ROUTER use the ACLs to write new entry only when it needs a new entry; in this second ping, NAT-ROUTER receives a packet on its inside interface, it performs routing to exit interface then it translate source address of incoming packet based on the NAT entry already present in NAT Table, looking at this entry NAT-ROUTER has enough information to do the translation, inside-local 10.0.0.1 is matched in NAT Table and it is translated to 192.0.0.1

This is an unwanted result caused by the simple entry that remains in NAT Table after the first translation to 151.5.1.25 is done.

Another unwanted effect is that with this entry, an outside device can contact PC1 using IP 192.0.0.1, see here:

From S25 interface e0/1 with ip address 151.5.2.25 (an address no used before) I can reach PC1:

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

NAT-ROUTER#
*Apr 21 16:32:27.786: NAT*: s=151.5.2.25, d=192.0.0.1->10.0.0.1 [0]
*Apr 21 16:32:27.788: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.2.25 [0]
*Apr 21 16:32:27.797: NAT*: s=151.5.2.25, d=192.0.0.1->10.0.0.1 [1]
*Apr 21 16:32:27.799: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.2.25 [1]
*Apr 21 16:32:27.802: NAT*: s=151.5.2.25, d=192.0.0.1->10.0.0.1 [2]
*Apr 21 16:32:27.805: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.2.25 [2]
*Apr 21 16:32:27.811: NAT*: s=151.5.2.25, d=192.0.0.1->10.0.0.1 [3]
*Apr 21 16:32:27.813: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.2.25 [3]
*Apr 21 16:32:27.816: NAT*: s=151.5.2.25, d=192.0.0.1->10.0.0.1 [4]
*Apr 21 16:32:27.818: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.2.25 [4]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.1:0       10.0.0.1:0         151.5.2.25:0       151.5.2.25:0
— 192.0.0.1          10.0.0.1           —                —

When packet from S25 comes to NAT-ROUTER it simply need to fill the missing part of the entry for outside address to complete the full entry. This is a behaviour that theoretically speaking should be possible only when a static NAT is configured.

To avoid this side effects and to add more features to the NAT operations a ROUTE-MAP can be used instead of an ACL.

I want to get this result:

10.0.0.1 <==> 192.0.0.X when it sends traffic to network 151.5.1.0/24
10.0.0.1 <==> 193.0.0.Y when it sends traffic to network 200.0.0.0/24

I clear NAT configuration(leaving ip nat inside and ip nat outside on the interfaces and the previous defined NAT pools)

NAT-ROUTER(config)#no ip nat inside source list TO-NET-151-5-1 pool POOL-192
NAT-ROUTER(config)#no ip nat inside source list TO-NET-200 pool POOL-193

The command ip nat inside source has route-map as an usable option:

NAT-ROUTER(config)#ip nat inside source ?
list       Specify access list describing local addresses
route-map  Specify route-map
static     Specify static local->global mapping

NAT-ROUTER(config)#ip nat inside source route-map ?
WORD  Route-map name

NAT-ROUTER(config)#ip nat inside source route-map TO-NET151 ?
interface  Specify interface for global address
pool       Name pool of global addresses

I use the same pool defined before:

NAT-ROUTER(config)#ip nat inside source route-map TO-NET151 pool ?
WORD  Pool name for global addresses

NAT-ROUTER(config)#ip nat inside source route-map TO-NET151 pool POOL-192 ?
no-payload  No translation of embedded address/port in the payload
overload    Overload an address translation
redundancy  NAT HA redundancy
reversible  Allow out->in traffic
vrf         Specify vrf
<cr>

NAT-ROUTER(config)#ip nat inside source route-map TO-NET151 pool POOL-192
NAT-ROUTER(config)#ip nat inside source route-map TO-NET200 pool POOL-193

I defined a Dynamic NAT using a route-map to match the interesting traffic, then I must define route-maps:

Previous acls I used with the ‘list’ command are still there and I can reference them in route-map:

NAT-ROUTER#sh run | s ip access
ip access-list extended TO-NET-151-5-1
permit ip host 10.0.0.1 151.5.1.0 0.0.0.255
ip access-list extended TO-NET-200
permit ip host 10.0.0.1 200.0.0.0 0.0.0.255

NAT-ROUTER(config)#route-map TO-NET151 permit 10
NAT-ROUTER(config-route-map)#match ip address TO-NET-151-5-1

NAT-ROUTER(config)#route-map TO-NET200 permit 10
NAT-ROUTER(config-route-map)#match ip address TO-NET-200

Nat configuration becomes:

NAT-ROUTER#sh run | s ip nat
ip nat inside e0/0
ip nat outside e0/1
ip nat outside e0/2
ip nat pool POOL-192 192.0.0.1 192.0.0.254 prefix-length 24 add-route
ip nat pool POOL-193 193.0.0.1 193.0.0.254 prefix-length 24 add-route
ip nat inside source route-map TO-NET151 pool POOL-192
ip nat inside source route-map TO-NET200 pool POOL-193

When no interesting traffic is flowing no NAT table entry is created:

NAT-ROUTER#sh ip nat translations
NAT-ROUTER#

NAT-ROUTER#debug ip nat
IP NAT debugging is on

Sending a ping from PC1 to 151.5.1.25 I have:

PC1#ping 151.5.1.25 so 10.0.0.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, 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 = 14/31/45 ms

*Apr 28 21:12:01.688: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:12:01.732: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:12:01.762: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:12:01.794: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:12:01.809: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0

Ping is ok. On NAT-ROUTER I see the translation of the five ping probes:

NAT-ROUTER#
*Apr 28 21:12:01.646: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [0]
*Apr 28 21:12:01.657: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [0]
*Apr 28 21:12:01.695: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [1]
*Apr 28 21:12:01.698: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [1]
*Apr 28 21:12:01.736: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [2]
*Apr 28 21:12:01.739: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [2]
*Apr 28 21:12:01.769: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [3]
*Apr 28 21:12:01.773: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [3]
*Apr 28 21:12:01.796: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [4]
*Apr 28 21:12:01.802: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [4]

NAT Table is:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.1:0       10.0.0.1:0         151.5.1.25:0       151.5.1.25:0

NOTE: The Key difference between a route-map and an extended ACL used to define the interesting traffic is that with an ACL router create a simple entry together with the dynamic entry, simple entry remains in NAT Table also when the dynamic entry expires. Instead when using a route-map the Dynamic Entry created is a FULL entry (inside and outside fields are filled in) and this is the only one entry in NAT TABLE we have no persisting simple entry in the table. This helps to avoid the sides effects described before (first one: external outside hosts can contact the inside host using the natted address like a static nat configuration and second one: PC1 is translated to the same IP 151.5.1.25 also when it sends traffic to 200.0.0.0 network)

As usual after some times the dynamic entry expires:

NAT-ROUTER#
*Apr 28 21:13:02.772: NAT: expiring 192.0.0.1 (10.0.0.1) icmp 0 (0)

Another interesting thing to see that is valid in general when speaking about NAT, is that even when using a route-map the matched ACL used in route-map is still used only when NAT-ROUTER needs it to create the first translation entry, once this is done traffic keeps matching the created entry, in other words:

NAT-ROUTER#sh ip access-lists
Extended IP access list TO-NET-151-5-1
10 permit ip host 10.0.0.1 151.5.1.0 0.0.0.255 (1 match)
Extended IP access list TO-NET-200
10 permit ip host 10.0.0.1 200.0.0.0 0.0.0.255

I can see that I sent 5 ping probes but ACL TO-NET-151-5-1 matched only the first one, this first matched packet is the trigger for NAT-ROUTER to create the entry in NAT table, next 4 pings probes don’t really match the ACL (see the counter match in show ip access list above) because NAT-ROUTER doesn’t need to create different entry, it translates the last 4 ping packet using the entry created by the first one.

If Now I send two consecutive ping from PC1, one to S25 (151.5.1.25) and one to S200 (200.0.0.200) I have:

NAT-ROUTER#sh ip nat translations
NAT-ROUTER#

NAT-ROUTER#sh debug
Generic IP:
IP NAT debugging is on

PC1#ping 151.5.1.25 repeat 10
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!!!!!!
Success rate is 100 percent (10/10), round-trip min/avg/max = 8/19/40 ms

PC1#
*Apr 28 21:35:32.729: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.739: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.749: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.763: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.784: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.810: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.843: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.858: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.890: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:32.904: ICMP: echo reply rcvd, src 151.5.1.25, dst 10.0.0.1, topology BASE, dscp 0 topoid 0

PC1#ping 200.0.0.200 repeat 10
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 200.0.0.200, timeout is 2 seconds:
!!!!!!!!!!
Success rate is 100 percent (10/10), round-trip min/avg/max = 4/10/44 ms

PC1#
*Apr 28 21:35:40.111: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.136: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.144: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.150: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.157: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.163: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.171: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.175: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.180: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0
*Apr 28 21:35:40.185: ICMP: echo reply rcvd, src 200.0.0.200, dst 10.0.0.1, topology BASE, dscp 0 topoid 0

NAT-ROUTER#
*Apr 28 21:35:32.693: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [5]
*Apr 28 21:35:32.698: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [5]
*Apr 28 21:35:32.731: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [6]
*Apr 28 21:35:32.737: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [6]
*Apr 28 21:35:32.743: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [7]
*Apr 28 21:35:32.748: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [7]
*Apr 28 21:35:32.752: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [8]
*Apr 28 21:35:32.757: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [8]
*Apr 28 21:35:32.767: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [9]
*Apr 28 21:35:32.772: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [9]
*Apr 28 21:35:32.789: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [10]
*Apr 28 21:35:32.791: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [10]
*Apr 28 21:35:32.816: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [11]
*Apr 28 21:35:32.820: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [11]
*Apr 28 21:35:32.850: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [12]
*Apr 28 21:35:32.856: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [12]
*Apr 28 21:35:32.862: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [13]
*Apr 28 21:35:32.866: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [13]
*Apr 28 21:35:32.897: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [14]
*Apr 28 21:35:32.900: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [14]

NAT-ROUTER#
*Apr 28 21:35:40.073: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [15]
*Apr 28 21:35:40.081: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [15]
*Apr 28 21:35:40.122: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [16]
*Apr 28 21:35:40.129: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [16]
*Apr 28 21:35:40.140: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [17]
*Apr 28 21:35:40.143: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [17]
*Apr 28 21:35:40.146: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [18]
*Apr 28 21:35:40.149: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [18]
*Apr 28 21:35:40.151: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [19]
*Apr 28 21:35:40.155: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [19]
*Apr 28 21:35:40.158: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [20]
*Apr 28 21:35:40.162: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [20]
*Apr 28 21:35:40.165: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [21]
*Apr 28 21:35:40.170: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [21]
*Apr 28 21:35:40.172: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [22]
*Apr 28 21:35:40.174: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [22]
*Apr 28 21:35:40.176: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [23]
*Apr 28 21:35:40.179: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [23]
*Apr 28 21:35:40.182: NAT*: s=10.0.0.1->193.0.0.1, d=200.0.0.200 [24]
*Apr 28 21:35:40.184: NAT*: s=200.0.0.200, d=193.0.0.1->10.0.0.1 [24]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.1:1       10.0.0.1:1         151.5.1.25:1       151.5.1.25:1
icmp 193.0.0.1:2       10.0.0.1:2         200.0.0.200:2      200.0.0.200:2

NOTE: USING A ROUTE-MAP LETS ME TO TRANSLATE THE SAME INSIDE LOCAL ADDRESS TO DIFFERENT INSIDE GLOBAL ADDRESS BELONGING TO DIFFERENT POOLS.

If now I look at show ip access-list command I see:

NAT-ROUTER#sh ip access-lists
Extended IP access list TO-NET-151-5-1
10 permit ip host 10.0.0.1 151.5.1.0 0.0.0.255 (2 matches)
Extended IP access list TO-NET-200
10 permit ip host 10.0.0.1 200.0.0.0 0.0.0.255 (1 match)

Again, counter matches of an ACL, used as a match condition in a route-map used in NAT, are not counting the total number of packets matching the defined traffic rules (20 in this case), but instead counts how many times the first packet of an IP flow causes NAT-ROUTER to create an entry in the NAT table. Here I can see that NAT-ROUTER creates entry in the NAT Table three times, two times for the two pings to 151.5.1.25 (NAT-ROUTER did this two times because the second ping was issued after the first entry was expired, so NAT-ROUTER use the first packet of the second ping to recreate the entry, then uses the first packet of the second ping (to 200.0.0.200) to create the second entry.

Using a route-map offers me the chance to use some of the feature specific to a route-map, for example I can match a particular interface or set an ip next-hop, this makes NAT more powerful and versatile. Such an example follows.

I modify route-maps:

route-map TO-NET200 permit 10
match ip address TO-NET-200
route-map TO-NET151 permit 10
match ip address TO-NET-151-5-1

NAT-ROUTER(config)#no route-map TO-NET200
NAT-ROUTER(config)#no route-map TO-NET151

NAT-ROUTER#show ip route 200.0.0.200
Routing entry for 200.0.0.0/24
Known via “ospf 1”, distance 110, metric 30, type inter area
Last update from 151.6.0.11 on Ethernet0/1, 01:05:58 ago
Routing Descriptor Blocks:
* 151.6.0.11, from 151.7.0.254, 01:05:58 ago, via Ethernet0/1
Route metric is 30, traffic share count is 1

NAT-ROUTER#show ip route 151.5.1.25
Routing entry for 151.5.1.0/24
Known via “ospf 1”, distance 110, metric 30, type intra area
Last update from 151.5.0.22 on Ethernet0/2, 01:06:15 ago
Routing Descriptor Blocks:
* 151.5.0.22, from 151.5.1.4, 01:06:15 ago, via Ethernet0/2
Route metric is 30, traffic share count is 1

I see from routing table that to reach 151.1.5.25 exit interface is e0/2 and to reach 200.0.0.200 is e0/1. Matching the exit interface under a route-map I can translate all traffic coming on inside interface of NAT-ROUTER based on IP destination of the packet:

NAT-ROUTER(config-route-map)#match interface e0/1
NAT-ROUTER(config-route-map)#exit

NAT-ROUTER(config)#route-map TO-NET151
NAT-ROUTER(config-route-map)#match interface e0/2

So here I’m not using any ACL to match interesting traffic, I’m simply matching the exit interface chosen by NAT-ROUTER to route the packet:

PC1#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 3/6/19 ms

PC2#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 7/14/32 ms

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

S100#ping 200.0.0.200
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 200.0.0.200, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/9/22 ms

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.1:3       10.0.0.1:3         151.5.1.25:3       151.5.1.25:3
icmp 192.0.0.2:0       10.0.0.2:0         151.5.1.25:0       151.5.1.25:0
icmp 193.0.0.1:0       10.0.0.3:0         200.0.0.200:0      200.0.0.200:0
icmp 193.0.0.2:0       10.0.0.100:0       200.0.0.200:0      200.0.0.200:0

Note how all 4 source addresses from the inside network are translated, NAT-ROUTER works this way: it receives packet on inside interface, performs routing, select exit interface, match this  interface in the route-map and selects the corresponding pool of translation.

NOTE: Another interesting thing not strictly related to route-map usage but valid as general rule is the id(port number) used in the translations, for inside local address 10.0.0.1  NAT-ROUTER uses id 3 (10.0.0.1:3) (because NAT-ROUTER translated four times this address or better saying it created four times a NAT entry in its table (first ping set (five packets) id=0, then nat entry expires, second ping set (five packets) id=1, and so on…)) for other local inside address since it’s the first time it translates them it assigns id(port)=0.

IOS gives us the chance to use route-map with the same rules valid for an extended ACL, this can be useful for compatibility reasons of for specific scenario. I wrote before that if I use an extended ACL to define the interesting traffic to translate, I can face a side effect that outside hosts, once an inside host is natted to an INSIDE GLOBAL ADDRESS X, can initiate a connection to the inside host using the same address X (like a static route translation), this is due to the persistent SIMPLE entry created together with the dynamic entry, that persists also when the dynamic nat expires. Generally speaking this is an unwanted behaviour, but maybe that some specific scenario could require this possibility. If I use a route-map this possibility is forbidden by the fact that route-maps in NAT don’t create a persistent simple entry, they only create dynamic entry that expires when traffic is no more present. To add this capability also to route-map IOS gives me an option called REVERSIBLE or using more words:

ROUTE-MAP OUTSIDE-TO-INSIDE SUPPORT

Many words to describe the concept but very simple configuration, to have route-map supporting outside-to-inside initiated connection it’s enough to add the KEYWORD REVERSIBLE when defining the nat translation rules as follows:

NAT-ROUTER#
ip nat inside source route-map TO-NET151 pool POOL-192 REVERSIBLE
ip nat inside source route-map TO-NET200 pool POOL-193 REVERSIBLE

Simply speaking what the REVERSIBLE option does is CREATING THE PERSISTENT SIMPLY ENTRY THAT IS CREATED WHEN WE USE A SIMPLE ACL TO MATCH THE TRAFFIC.

NOTE: When configuring nat with route-map for supporting reversible option, match interface and match ip next-hop are not supported option under the route-map, also PAT is not supported. Traffic must be matched with an ACL under the route-map.

Here an example, I change again route-map configuration to match traffic against ACLs:

NAT-ROUTER#show run | s ip access
ip access-list extended TO-NET-151-5-1
permit ip host 10.0.0.1 151.5.1.0 0.0.0.255
ip access-list extended TO-NET-200
permit ip host 10.0.0.1 200.0.0.0 0.0.0.255

NAT-ROUTER#sh run | s ip nat
ip nat inside –> e0/0
ip nat outside –> e0/1
ip nat outside –> e0/2
ip nat pool POOL-192 192.0.0.1 192.0.0.254 prefix-length 24 add-route
ip nat pool POOL-193 193.0.0.1 193.0.0.254 prefix-length 24 add-route
ip nat inside source route-map TO-NET151 pool POOL-192 reversible
ip nat inside source route-map TO-NET200 pool POOL-193 reversible

NAT-ROUTER#sh ip nat translations
NAT-ROUTER#

NAT-ROUTER(config)#route-map TO-NET200 permit 10
NAT-ROUTER(config-route-map)#no match interface e0/1
NAT-ROUTER(config)#route-map TO-NET151 permit 10
NAT-ROUTER(config-route-map)#no match interface e0/2

NAT-ROUTER(config)#route-map TO-NET200 permit 10
NAT-ROUTER(config-route-map)#match ip address TO-NET-200

NAT-ROUTER(config)#route-map TO-NET151 permit 10
NAT-ROUTER(config-route-map)#match ip address TO-NET-151-5-1

PC1#ping 151.5.1.25
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 151.5.1.25, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 3/5/11 ms

NAT-ROUTER#
*Apr 29 00:13:05.791: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [50]
*Apr 29 00:13:05.792: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [50]
*Apr 29 00:13:05.802: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [51]
*Apr 29 00:13:05.804: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [51]
*Apr 29 00:13:05.810: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [52]
*Apr 29 00:13:05.811: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [52]
*Apr 29 00:13:05.813: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [53]
*Apr 29 00:13:05.815: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [53]
*Apr 29 00:13:05.817: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.25 [54]
*Apr 29 00:13:05.819: NAT*: s=151.5.1.25, d=192.0.0.1->10.0.0.1 [54]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.1:8       10.0.0.1:8         151.5.1.25:8       151.5.1.25:8
— 192.0.0.1          10.0.0.1           —                —            –> THIS ENTRY IS CREATED BY THE USAGE OF REVERSIBILE KEYWORD

When dynamic nat entry expires:

NAT-ROUTER#
*Apr 29 00:14:06.655: NAT: expiring 192.0.0.1 (10.0.0.1) icmp 8 (8)

The simple entry persists in NAT Table and this allows an external hosts from the same subnet permitted as destination in the ACL under the route-map to initiate a connection to 10.0.0.1 using address 192.0.0.1

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 192.0.0.1          10.0.0.1           —                —

S25(config)#int e1/0
S25(config-if)#ip address 151.5.1.254 255.255.255.0 secondary

S25#sh run int e1/0 | b interface
interface Ethernet1/0
ip address 151.5.1.254 255.255.255.0 secondary
ip address 151.5.1.25 255.255.255.0

S25#ping 192.0.0.1 source 151.5.1.254
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.0.0.1, timeout is 2 seconds:
Packet sent with a source address of 151.5.1.254
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 3/8/16 ms

*Apr 29 00:57:21.700: ICMP: echo reply rcvd, src 192.0.0.1, dst 151.5.1.254, topology BASE, dscp 0 topoid 0
*Apr 29 00:57:21.716: ICMP: echo reply rcvd, src 192.0.0.1, dst 151.5.1.254, topology BASE, dscp 0 topoid 0
*Apr 29 00:57:21.726: ICMP: echo reply rcvd, src 192.0.0.1, dst 151.5.1.254, topology BASE, dscp 0 topoid 0
*Apr 29 00:57:21.730: ICMP: echo reply rcvd, src 192.0.0.1, dst 151.5.1.254, topology BASE, dscp 0 topoid 0
*Apr 29 00:57:21.734: ICMP: echo reply rcvd, src 192.0.0.1, dst 151.5.1.254, topology BASE, dscp 0 topoid 0

NAT-ROUTER#
*Apr 29 00:57:21.689: NAT*: s=151.5.1.254, d=192.0.0.1->10.0.0.1 [50]
*Apr 29 00:57:21.692: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.254 [50]
*Apr 29 00:57:21.701: NAT*: s=151.5.1.254, d=192.0.0.1->10.0.0.1 [51]
*Apr 29 00:57:21.704: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.254 [51]
*Apr 29 00:57:21.718: NAT*: s=151.5.1.254, d=192.0.0.1->10.0.0.1 [52]
*Apr 29 00:57:21.720: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.254 [52]
*Apr 29 00:57:21.728: NAT*: s=151.5.1.254, d=192.0.0.1->10.0.0.1 [53]
*Apr 29 00:57:21.729: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.254 [53]
*Apr 29 00:57:21.731: NAT*: s=151.5.1.254, d=192.0.0.1->10.0.0.1 [54]
*Apr 29 00:57:21.733: NAT*: s=10.0.0.1->192.0.0.1, d=151.5.1.254 [54]

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
icmp 192.0.0.1:10      10.0.0.1:10        151.5.1.254:10     151.5.1.254:10  –> initiated connection from outside to inside
— 192.0.0.1          10.0.0.1           —                —

Then the REVERSIBLE option with route-map is a little more restrictive with respect to using an ACL because reverse traffic will be permitted only from the subnet defined under the route-map as destination subnet of matching traffic inside-to-outside, instead with an ACL all external hosts can use the PARENT (simple) entry created in the NAT TABLE.

§§§ NAT and IPSEC §§§

To understand how NAT and IPSEC interact I must recall how NAT order of operations works:

nat-pic14-order-of-op

Then I will use this simplified topology:

nat-pic15

Before natting ipsec traffic I want do ipsec encrypting traffic originating from LAN 30.0.0.0/24 ad directed to LAN 40.0.0.0/24. I give LAN-to-LAN connectivity using OSPF single Area0:

R2#ping 30.0.0.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 30.0.0.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 2/4/6 ms

Host2#ping 30.0.0.10
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 30.0.0.10, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 8/12/16 ms

Doing IPsec:

R1#sh run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 20.0.0.2
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
crypto map MY-MAP 1 ipsec-isakmp
set peer 20.0.0.2
set transform-set MY-SET
match address LAN-30-40
crypto map MY-MAP

R1#sh run | s ip access
ip access-list extended LAN-30-40
permit ip 30.0.0.0 0.0.0.255 40.0.0.0 0.0.0.255

R1#show logging | i Buffer
Buffer logging:  level debugging, 4 messages logged, xml disabled,
Log Buffer (100000 bytes):

R1#show logging | i Console
Console logging: level informational, 60 messages logged, xml disabled,

R1#sh run int e0/0 | b interface
interface Ethernet0/0
ip address 10.0.0.1 255.255.255.0
crypto map MY-MAP

R2#show run | s logging
logging buffered 100000
logging console informational
logging host 10.0.0.100 (wireshark host and syslog server)

R2#show logging | i Buffer
Buffer logging:  level debugging, 4 messages logged, xml disabled,
Log Buffer (100000 bytes):

R2#show logging | i Console
Console logging: level informational, 60 messages logged, xml disabled,

R2#show run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 10.0.0.1
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
crypto map MY-MAP 1 ipsec-isakmp
set peer 10.0.0.1
set transform-set MY-SET
match address LAN-30-40
crypto map MY-MAP

R2#sh run | s ip access
ip access-list extended LAN-30-40
permit ip 40.0.0.0 0.0.0.255 30.0.0.0 0.0.0.255

R2#sh run int e0/1 | b interface
interface Ethernet0/1
ip address 20.0.0.2 255.255.255.0
crypto map MY-MAP

R2#show run | s logging
logging buffered 100000
logging console informational
logging host 10.0.0.100 (wireshark host and syslog server)

Then I configured a traffic capture on port e0/0 and e0/1 of NAT-ROUTER:

NAT-ROUTER#show monitor capture buffer LEFT parameters
Capture buffer LEFT (circular buffer)
Buffer Size : 1048576 bytes, Max Element Size : 2000 bytes, Packets : 12
Allow-nth-pak : 0, Duration : 0 (seconds), Max packets : 0, pps : 0
Associated Capture Points:
Name : PROC-LEFT, Status : Active
Name : E00, Status : Active
Configuration:
monitor capture buffer LEFT max-size 2000 circular
monitor capture point associate PROC-LEFT LEFT
monitor capture point associate E00 LEFT

NAT-ROUTER#show monitor capture buffer RIGHT parameters
Capture buffer RIGHT (circular buffer)
Buffer Size : 1048576 bytes, Max Element Size : 2000 bytes, Packets : 12
Allow-nth-pak : 0, Duration : 0 (seconds), Max packets : 0, pps : 0
Associated Capture Points:
Name : PROC-RIGHT, Status : Active
Name : E01, Status : Active
Configuration:
monitor capture buffer RIGHT max-size 2000 circular
monitor capture point associate PROC-RIGHT RIGHT
monitor capture point associate E01 RIGHT

NAT-ROUTER#show monitor capture point all
Status Information for Capture Point E00
IPv4 CEF
Switch Path: IPv4 CEF            , Capture Buffer: LEFT
Status : Active

Configuration:
monitor capture point ip cef E00 Ethernet0/0 both

Status Information for Capture Point E01
IPv4 CEF
Switch Path: IPv4 CEF            , Capture Buffer: RIGHT
Status : Active

Configuration:
monitor capture point ip cef E01 Ethernet0/1 both

Status Information for Capture Point PROC-LEFT
IPv4 Process
Switch Path: IPv4 Process        , Capture Buffer: LEFT
Status : Active

Configuration:
monitor capture point ip process-switched PROC-LEFT both

Status Information for Capture Point PROC-RIGHT
IPv4 Process
Switch Path: IPv4 Process        , Capture Buffer: RIGHT
Status : Active

Configuration:
monitor capture point ip process-switched PROC-RIGHT both

So I’m sniffing cef on both ports and process-switching on NAT-ROUTER

Making some interesting traffic R1 and R2 should establish an IPSEC association and encrypt the traffic:

Host10#ping 40.0.0.2 source 30.0.0.10 repeat 10
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 40.0.0.2, timeout is 2 seconds:
Packet sent with a source address of 30.0.0.10
.!!!!!!!!!
Success rate is 90 percent (9/10), round-trip min/avg/max = 6/7/9 ms

R1#sh crypto isakmp sa
IPv4 Crypto ISAKMP SA
dst             src             state          conn-id status
20.0.0.2        10.0.0.1        QM_IDLE           1001 ACTIVE

R1#show crypto ipsec sa

interface: Ethernet0/0
Crypto map tag: MY-MAP, local addr 10.0.0.1

   protected vrf: (none)
local  ident (addr/mask/prot/port): (30.0.0.0/255.255.255.0/0/0)
remote ident (addr/mask/prot/port): (40.0.0.0/255.255.255.0/0/0)
current_peer 20.0.0.2 port 500
PERMIT, flags={origin_is_acl,}
#pkts encaps: 9, #pkts encrypt: 9, #pkts digest: 9
#pkts decaps: 9, #pkts decrypt: 9, #pkts verify: 9

#pkts compressed: 0, #pkts decompressed: 0
#pkts not compressed: 0, #pkts compr. failed: 0
#pkts not decompressed: 0, #pkts decompress failed: 0
#send errors 0, #recv errors 0

     local crypto endpt.: 10.0.0.1, remote crypto endpt.: 20.0.0.2
plaintext mtu 1446, path mtu 1500, ip mtu 1500, ip mtu idb Ethernet0/0
current outbound spi: 0x5DE4E21E(1575281182)
PFS (Y/N): N, DH group: none
[—skipped—]

R2#show crypto isakmp sa
IPv4 Crypto ISAKMP SA
dst             src             state          conn-id status
20.0.0.2        10.0.0.1        QM_IDLE           1001 ACTIVE

R2#show crypto ipsec sa

interface: Ethernet0/1
Crypto map tag: MY-MAP, local addr 20.0.0.2

   protected vrf: (none)
local  ident (addr/mask/prot/port): (40.0.0.0/255.255.255.0/0/0)
remote ident (addr/mask/prot/port): (30.0.0.0/255.255.255.0/0/0)
current_peer 10.0.0.1 port 500
PERMIT, flags={origin_is_acl,}
#pkts encaps: 9, #pkts encrypt: 9, #pkts digest: 9
#pkts decaps: 9, #pkts decrypt: 9, #pkts verify: 9

#pkts compressed: 0, #pkts decompressed: 0
#pkts not compressed: 0, #pkts compr. failed: 0
#pkts not decompressed: 0, #pkts decompress failed: 0
#send errors 0, #recv errors 0

     local crypto endpt.: 20.0.0.2, remote crypto endpt.: 10.0.0.1
plaintext mtu 1446, path mtu 1500, ip mtu 1500, ip mtu idb Ethernet0/1
current outbound spi: 0x2F4D19AA(793581994)
PFS (Y/N): N, DH group: none
[—skipped—]

Encryption works, the first packet of the ping is lost due to ISAKMP Phase1 Establishment. Looking at logs and captured packets:

NAT-ROUTER#monitor capture buffer LEFT export tftp://10.0.0.100/IPSEC-NoNat-LEFT.pcap
NAT-ROUTER#monitor capture buffer RIGHT export tftp://10.0.0.100/IPSEC-NoNat-RIGHT.pcap

nat

ISAKMP negotiation uses by default port number 500:

R1#show crypto isakmp peer
Peer: 20.0.0.2 Port: 500 Local: 10.0.0.1
Phase1 id: 20.0.0.2

R2#show crypto ISAKMP peer
Peer: 10.0.0.1 Port: 500 Local: 20.0.0.2
Phase1 id: 10.0.0.1

Nat-Traversal (NAT-T) is the capability of two IPsec peers to detect a NAT Device along the path. The exact mechanism used by IPsec peers to detect if they are behind a NAT device is ruled by a few numbers of RFC:

IPsec-Network Address Translation (NAT) Compatibility Requirements http://www.rfc-base.org/txt/rfc-3715.txt

Negotiation of NAT-Traversal in the IKE http://www.rfc-base.org/txt/rfc-3947.txt
UDP Encapsulation of IPsec ESP Packets http://www.rfc-base.org/txt/rfc-3948.txt

Making a brief, since a NAT device could translate IP address and Port Numbers it could break the IPsec process. To workaround this problem an IPsec peer must know if the remote peer is capable of doing NAT-T and they need to discover if a NAT Device is present along the path between them.

Reading RFC3947 we see:

“The detection of support for NAT-Traversal and detection of NAT along the path between the two IKE peers occurs in IKE [RFC2409] Phase 1.” and

“The NAT-Traversal capability of the remote host is determined by an exchange of VENDOR ID PAYLOADS. In the first two messages of Phase 1, the vendor id payload for this specification MUST be sent if supported (and it MUST be received by both sides) for the NAT-Traversal probe to continue. The content of the payload is the MD5 hash of the string RFC 3947. The exact content in hex for the payload is “4a131c81070358455c5728f20e95452f “

Cisco IOS support RFC3947 so I should see this hash of “RFC 3947 sent to the peer” and each peer should receive it. I can confirm this looking at debug messages and captured packet:

R1 (initiator)

R1#show log | i ISAKMP
*May  9 16:36:14.062: ISAKMP:(0): SA request profile is (NULL)
*May  9 16:36:14.062: ISAKMP: Created a peer struct for 20.0.0.2, peer port 500
*May  9 16:36:14.062: ISAKMP: New peer created peer = 0xB2924480 peer_handle = 0x80000002
*May  9 16:36:14.062: ISAKMP: Locking peer struct 0xB2924480, refcount 1 for isakmp_initiator
*May  9 16:36:14.062: ISAKMP: local port 500, remote port 500
[— skipped —]
*May  9 16:36:14.063: ISAKMP:(0): constructed NAT-T vendor-rfc3947 ID
*May  9 16:36:14.063: ISAKMP:(0): constructed NAT-T vendor-07 ID
*May  9 16:36:14.063: ISAKMP:(0): constructed NAT-T vendor-03 ID
*May  9 16:36:14.063: ISAKMP:(0): constructed NAT-T vendor-02 ID
[— skipped —]
*May  9 16:36:14.085: ISAKMP:(0): processing vendor id payload
*May  9 16:36:14.085: ISAKMP (0): vendor ID is NAT-T RFC 3947

Here I can see the dump of the first isakmp packet sent by 10.0.0.1 (R1) to 20.0.0.2 (R2)

nat-pic16

Here I have many informations, Source IP (10.0.0.1), Destination IP (20.0.0.2) Source Port and Destination Port (500) and the VENDOR ID PAYLOADS sent. I see that IOS sends four vendor IDs, one for RFC3497 and three others for previous IETF draft, for example vendor-ID 03 sends MD5 hash of “draft-ietf-ipsec-nat-t-ike-03” – [“7d9419a6 5310ca6f 2c179d92 15529d56”] as can been verified at this link –> http://www.ietf.org/proceedings/54/I-D/draft-ietf-ipsec-nat-t-ike-03.txt

R2 does the same thing:

nat-pic17

So I verified that in first two messages of IKE phase1 peers detect if they support NAT-T. Other Vendor-ID are exchanged for example peers detect if they support Dead Peer Detection – DPD, more about this reading its RFC https://tools.ietf.org/html/rfc3706

Moving forward on RFC3947 I see:

The NAT-D payload not only detects the presence of NAT between the two IKE peers, but also detects where the NAT is.  The location of the NAT device is important, as the keepalives have to initiate from the peer “behind” the NAT. To detect NAT between the two hosts, we have to detect whether the IP address or the port changes along the path. This is done by sending the hashes of the IP addresses and ports of both IKE peers from each end to the other. If both ends calculate those hashes and get same result, they know there is no NAT between. If the hashes do not match, somebody has translated the address or port.  This means that we have to do NAT-Traversal to get IPsec packets through. If the sender of the packet does not know his own IP address (in case of multiple interfaces, and the implementation  does not know which IP address is used to route the packet out), the sender can include multiple local hashes to the packet (as separate NAT-D payloads). In this case, NAT is detected if and only if none of the hashes match. The hashes are sent as a series of NAT-D (NAT discovery) payloads. Each payload contains one hash, so in case of multiple hashes, multiple NAT-D payloads are sent. In the normal case there are only two NAT-D payloads. The NAT-D payloads are included in the third and fourth packets of Main Mode, and in the second and third packets in the Aggressive Mode.

Let’s check this on my capture, this is the dump of the second packet sent by R1 to R2:

nat-pic18

Looking at the above picture I see that R1 sends many Vendor-ID Payload (DPD, Exchange of the hash of the key…) and among them there are TWO NAT-D payload, reading into them I see that the first NAT-D payload is hash of ip address and port (remote-peer) and the second contains the hash of R1’s IP address and port.

In the following picture I can see what R2 sends out as NAT-D payload:

nat-pic19

The two previous pics show that R1 calculates and sends:

MD5_HASH[peer’s_IP_ADD_PORT]=MD5_HASH[20.0.0.2 500] = 2a:5e:79:9d:9e:a7:b4:bb:cc:9e:e7:76:50:19:a7:5e
MD5_HASH[ITS_IP_ADD_PORT]=MD5_HASH[10.0.0.1 500] = 32:a5:41:96:a2:d4:98:69:ee:d3:50:5c:b2:fc:8d:2a

R2 calculates and sends:
MD5_HASH[peer’s_IP_ADD_PORT]=MD5_HASH[10.0.0.1 500] = 32:a5:41:96:a2:d4:98:69:ee:d3:50:5c:b2:fc:8d:2a
MD5_HASH[ITS_IP_ADD_PORT]=MD5_HASH[20.0.0.2 500] = 2a:5e:79:9d:9e:a7:b4:bb:cc:9e:e7:76:50:19:a7:5e

R1 and R2 looking at the calculated and received hash know that no NAT devices is present along the path because hash values are matching, for example R2 knows that its configured peer is at 10.0.0.1 port 500, the local calculated value (sent as second NAT-D payload by R2) for that pair matches with the one received by R2 (and sent as first NAT-D payload by R1).

Indeed, RFC3947 specifies:

“If there is no NAT between the peers, the first NAT-D payload received should match one of the local NAT-D payloads (i.e., the local NAT-D payloads this host is sending out), and one of the other NAT-D payloads must match the remote end’s IP address and port. If the first check fails (i.e., first NAT-D payload does not match any of the local IP addresses and ports), it means that there is dynamic NAT between the peers, and this end should start sending keepalives as defined in the [RFC3948] (this end is behind the NAT).”

R1 and R2 after this ISAKMP messages exchange declare that no NAT is found for them or their peers:

R1#
*May  9 16:36:14.107: ISAKMP (1001): No NAT Found for self or peer

R2#
*May  9 16:36:14.096: ISAKMP (1001): No NAT Found for self or peer

After IKE phase 1 is completed and the presence of NAT-Device along the path is excluded, IKE PHASE2 (IPSEC) completes and the remaining 9 ping packets are encrypted by ESP protocol:

nat-pic20

Now I’m going to configure NAT-ROUTER to perform NAT, and with debugging and captured packets I will check how crypto peers detect the presence of a NAT-device and how things change to let IPsec pass through the NAT device.

STEP 1] Defining static NAT and logging.

I will use static NAT for syslog-server, this way R2 can send syslog messages too to it. Outside Local IP address for the server will be 20.0.0.100

10.0.0.100 <-> 20.0.0.100

NAT interface: e0/0 = INSIDE ; e0/1 = OUTSIDE

NAT-ROUTER#sh run int e0/0 | b interface
interface Ethernet0/0
ip address 10.0.0.254 255.255.255.0
ip nat inside

NAT-ROUTER#sh run int e0/1 | b interface
interface Ethernet0/1
ip address 20.0.0.1 255.255.255.0
 ip nat outside

NAT-ROUTER(config)#ip nat inside source static 10.0.0.100 20.0.0.100

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
— 20.0.0.100         10.0.0.100         —                —

R2(config)#logging host 20.0.0.100
*May 10 14:47:11.069: %SYS-6-LOGGINGHOST_STARTSTOP: Logging to host 20.0.0.100 port 514 started – CLI initiated

Logging configuration on R1, NAT-ROUTER and R2 is:

R1#sh run | s logging
logging buffered 100000
logging console informational
logging trap debugging
logging origin-id hostname
logging host 10.0.0.100

NAT-ROUTER#show run | s logging
logging buffered 100000
logging console informational
logging trap debugging
logging origin-id hostname
logging host 10.0.0.100

R2#sh run | s logging
logging buffered 100000
logging console informational
logging trap debugging
logging origin-id hostname
logging host 20.0.0.100

After configuring R2 to send logs to NATTED IP 20.0.0.100 NAT-Router fills its NAT-TABLE:

NAT-ROUTER#sh ip nat tra
NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
udp 20.0.0.100:514     10.0.0.100:514     20.0.0.2:64248     20.0.0.2:64248
— 20.0.0.100         10.0.0.100         —                —

STEP2] Defining Dynamic NAT

R1 and R2 are the crypto peer configured to encrypt traffic from LAN_30(30.0.0.0/24) to LAN_40 (40.0.0.0/24) in both directions. From previous test (NO NAT present) I see that ESP packet are IP encapsulated with source address 10.0.0.1 and destination address 20.0.0.2 – Since I want no IP address of Network 10.0.0.0/24 be present OUTSIDE, NAT-ROUTER will translate source address into an OUTSIDE LOCAL IP ADDRESS OVERLOADING ITS E0/1 INTERFACE ON IP 20.0.0.1. NAT configuration becomes:

NAT-ROUTER(config)#ip access-list extended NAT-LAN-10
NAT-ROUTER(config-ext-nacl)#permit ip host 10.0.0.1 host 20.0.0.2

NAT-ROUTER(config)#ip nat inside source list NAT-LAN-10 interface e0/1 overload

STEP3] activating debug and captures

R1 and R2 –> debug crypto isakmp + debug crypto ipsec – R1: monitor interface e0/1,e0/0 – R2: monitor interface e0/1,e1/0

NAT-ROUTER –> debug ip nat + monitor interface e0/0,e0/1

R1#monitor capture buffer R1_BUFF max-size 2000 circular
R1#monitor capture point ip process-switched R1_PROC both
R1#monitor capture point ip cef E01 Ethernet0/1 both
R1#monitor capture point ip cef E00 Ethernet0/0 both
R1#monitor capture point associate R1_PROC R1_BUFF
R1#monitor capture point associate E01 R1_BUFF
R1#monitor capture point associate E00 R1_BUFF

R2#monitor capture buffer R2_BUFF max-size 2000 circular
R2#monitor capture point ip process-switched R2_PROC both
R2#monitor capture point ip cef E01 Ethernet0/1 both
R2#monitor capture point ip cef E10 Ethernet1/0 both
R2#monitor capture point associate R2_PROC R2_BUFF
R2#monitor capture point associate E01 R2_BUFF
R2#monitor capture point associate E10 R2_BUFF

NAT-ROUTER#monitor capture buffer NAT_BUFF max-size 2000 circular
NAT-ROUTER#monitor capture point ip process-switched NAT_PROC both
NAT-ROUTER#monitor capture point ip cef E01 Ethernet0/1 both
NAT-ROUTER#monitor capture point ip cef E00 Ethernet0/0 both
NAT-ROUTER#monitor capture point associate NAT_PROC NAT_BUFF
NAT-ROUTER#monitor capture point associate E01 NAT_BUFF
NAT-ROUTER#monitor capture point associate E00 NAT_BUFF

Clear Logs on all routers and activate captures:

R1#monitor capture point start R1_PROC
R1#monitor capture point start E00
R1#monitor capture point start E01

NAT-ROUTER#monitor capture point start NAT_PROC
NAT-ROUTER#monitor capture point start E01
NAT-ROUTER#monitor capture point start E00

R2#monitor capture point start R2_PROC
R2#monitor capture point start E01
R2#monitor capture point start E10

STEP4] changing crypto policy to adapt it to NATTED address, R2 will see ISAKMP messages as sourced by 20.0.0.1

crypto config will be:

R1#sh run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 20.0.0.2     
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
crypto map MY-MAP 1 ipsec-isakmp
 set peer 20.0.0.2
set transform-set MY-SET
match address LAN-30-40
crypto map MY-MAP

R1#show run | s ip access
ip access-list extended LAN-30-40
permit ip 30.0.0.0 0.0.0.255 40.0.0.0 0.0.0.255

R2#sh run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 20.0.0.1 
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
crypto map MY-MAP 1 ipsec-isakmp
 set peer 20.0.0.1
set transform-set MY-SET
match address LAN-30-40
crypto map MY-MAP

R2#show run | s ip access
ip access-list extended LAN-30-40
permit ip 40.0.0.0 0.0.0.255 30.0.0.0 0.0.0.255


STEP5] Producing 5 ping packet from LAN30 to LAN 40

Host10#ping 40.0.0.2 source 30.0.0.10 repeat 10
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 40.0.0.2, timeout is 2 seconds:
Packet sent with a source address of 30.0.0.10
.!!!!!!!!!
Success rate is 90 percent (9/10), round-trip min/avg/max = 6/8/22 ms

####### TEST VERIFICATION #######

NAT TABLE on NAT-ROUTER after ping succeeds:

nat-pic30

NAT-ROUTER#show ip access-lists
Extended IP access list NAT-LAN-10
10 permit ip host 10.0.0.1 host 20.0.0.2 (3 matches)

1] Host10 prepare a ping packet –> [s=30.0.0.10,d=40.0.0.2] and sends it to its default router R1 (30.0.0.1)
2] R1 crypto map match ping packet so it starts ISAKMP negotiation:

R1#
*May 10 15:52:47.414: IPSEC(sa_request): ,
(key eng. msg.) OUTBOUND local= 10.0.0.1:500, remote= 20.0.0.2:500,
local_proxy= 30.0.0.0/255.255.255.0/256/0,
remote_proxy= 40.0.0.0/255.255.255.0/256/0,
protocol= ESP, transform= esp-3des esp-md5-hmac  (Tunnel),
lifedur= 3600s and 4608000kb,
spi= 0x0(0), conn_id= 0, keysize= 0, flags= 0x0
*May 10 15:52:47.415: ISAKMP:(0): SA request profile is (NULL)
*May 10 15:52:47.415: ISAKMP: Created a peer struct for 20.0.0.2, peer port 500
*May 10 15:52:47.415: ISAKMP: New peer created peer = 0xB29AB1A0 peer_handle = 0x80000003
*May 10 15:52:47.415: ISAKMP: Locking peer struct 0xB29AB1A0, refcount 1 for isakmp_initiator
*May 10 15:52:47.415: ISAKMP: local port 500, remote port 500

As I know from previous example with NO-NAT two phases start: a) NAT-T support between peers b) NAT Device detection along the path, this can be seen in following pic:

nat-pic21

So, for R1 at the beginning nothing changes because R1 has no Knowledge of NAT yet. The ISAKMP packet travels to NAT-ROUTER

nat-pic22

NAT-ROUTER performs routing then translates this packet based on configured NAT-Rules (source address becomes 20.0.0.1)

nat-pic23

On R2 we can see that all ISAKMP messages comes from IP 20.0.0.1 (and not the original 10.0.0.1)

nat-pic24

Exchanging the NAT-D Payload R1 and R2 discover that a NAT-device is on the path. I can verify this looking at the logs:

R1#
*May 10 15:52:47.459: ISAKMP:received payload type 20
*May 10 15:52:47.459: ISAKMP (1001): NAT found, both nodes inside NAT
*May 10 15:52:47.459: ISAKMP:received payload type 20
*May 10 15:52:47.459: ISAKMP (1001): My hash no match –  this node inside NAT

R2#
*May 10 15:52:47.447: ISAKMP:received payload type 20
*May 10 15:52:47.447: ISAKMP (1001): His hash no match – this node outside NAT
*May 10 15:52:47.447: ISAKMP:received payload type 20
*May 10 15:52:47.447: ISAKMP (1001): His hash no match – this node outside NAT

In few words, R1 sends to R2 two hashes:

MD5_HASH[peer’s_IP_ADD_PORT]=MD5_HASH[20.0.0.2 500] = bf:04:82:3c:9d:32:b7:7d:e4:77:16:c0:44:11:1e:df
MD5_HASH[ITS_IP_ADD_PORT]=MD5_HASH[10.0.0.1 500] = 56:35:1c:56:cd:7b:dd:d1:cc:0f:d0:09:99:11:3b:88

R1’s NAT-D payload can be seen in the following pic

nat-pic25

R2 calculates and sends two hashes:

MD5_HASH[peer’s_IP_ADD_PORT]=MD5_HASH[20.0.0.1 500] = 8b:3d:dd:25:18:a6:ba:21:4e:98:46:c9:54:f2:0c:99
MD5_HASH[ITS_IP_ADD_PORT]=MD5_HASH[20.0.0.2 500] = bf:04:82:3c:9d:32:b7:7d:e4:77:16:c0:44:11:1e:df

R2’s NAT-D payload can be seen in the following pic

nat-pic26

After verifying that hash don’t match R1 and R2 renegotiate to exchange packet encapsulating them in UDP port 4500:

R2#
*May 10 15:52:47.475: ISAKMP:(1001):Detected port floating to port = 4500

Here the ping packet encapsulated in ESP packet encapsulated in UDP packet:

nat-pic27

From translations on NAT-ROUTER:

nat-pic30

I can see that ISAKMP sessions used standard udp port 500 so it seems that NAT-ROUTER doesn’t translate it. But this happens only because there is only two crypto peers making encryption (one inside R1 and one outside R2), in the next test I add a third crypto peer R3 as per following new topology:

nat-pic28

Now NAT-ROUTER has to translate two IPsec sessions (ISAKMP and ESP), one coming from R1 and going to R2 (10.0.0.1 to 20.0.0.2) and one coming from R3 going to R2 (10.0.0.3 to 20.0.0.2), since the translated Inside Global Address will be the same for both sessions it needs to distinguish it in its NAT table, I modified NAT configuration as follows:

NAT-ROUTER#show run | s ip nat
ip nat inside
ip nat outside
ip nat inside source list NAT-LAN-10 interface Ethernet0/1 overload
ip nat inside source static 10.0.0.100 20.0.0.100

NAT-ROUTER#sh ip access-lists
Extended IP access list NAT-LAN-10
10 permit ip host 10.0.0.1 host 20.0.0.2
20 permit ip host 10.0.0.3 host 20.0.0.2

I simply added IP 10.0.0.3 so NAT-ROUTER can translate it. Also I needed to modify R2 to accept a crypto session from R3 too:

R3#sh run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 20.0.0.2
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
crypto map MY-MAP 1 ipsec-isakmp
set peer 20.0.0.2
set transform-set MY-SET
match address LAN-50-40
crypto map MY-MAP

R3#show ip access-lists
Extended IP access list LAN-50-40
10 permit ip 50.0.0.0 0.0.0.255 40.0.0.0 0.0.0.255

R2#show run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 20.0.0.1
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
crypto map MY-MAP 1 ipsec-isakmp
set peer 20.0.0.1
set transform-set MY-SET
match address LAN-30-40
crypto map MY-MAP 5 ipsec-isakmp
set peer 20.0.0.1
set transform-set MY-SET
 match address LAN-50-40
crypto map MY-MAP

R2#show ip access-lists
Extended IP access list LAN-30-40
10 permit ip 40.0.0.0 0.0.0.255 30.0.0.0 0.0.0.255
Extended IP access list LAN-50-40
10 permit ip 40.0.0.0 0.0.0.255 50.0.0.0 0.0.0.255

Before making any traffic from LAN 30 and 50 I have in NAT Table:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
udp 20.0.0.100:514     10.0.0.100:514     20.0.0.2:56707     20.0.0.2:56707 –> log messages sent from R2 to syslog natted behind address 20.0.0.100
— 20.0.0.100         10.0.0.100         —                —

Sending some ping traffic to encrypt from R1 and R3:

Host10#ping 40.0.0.2 source 30.0.0.10 repeat 10
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 40.0.0.2, timeout is 2 seconds:
Packet sent with a source address of 30.0.0.10
.!!!!!!!!!

Success rate is 90 percent (9/10), round-trip min/avg/max = 7/9/17 ms

Host20#ping 40.0.0.2 source 50.0.0.20 repeat 10
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 40.0.0.2, timeout is 2 seconds:
Packet sent with a source address of 50.0.0.20
.!!!!!!!!!
Success rate is 90 percent (9/10), round-trip min/avg/max = 7/10/17 ms

Encryption works and NAT Table becomes:

NAT-ROUTER#sh ip nat translations
Pro Inside global      Inside local       Outside local      Outside global
udp 20.0.0.1:500       10.0.0.1:500       20.0.0.2:500       20.0.0.2:500
udp 20.0.0.1:4500      10.0.0.1:4500      20.0.0.2:4500      20.0.0.2:4500
udp 20.0.0.1:1         10.0.0.3:500       20.0.0.2:500       20.0.0.2:500
udp 20.0.0.1:1024      10.0.0.3:4500      20.0.0.2:4500      20.0.0.2:4500

udp 20.0.0.100:514     10.0.0.100:514     20.0.0.2:56707     20.0.0.2:56707
— 20.0.0.100         10.0.0.100         —                —

I can see that Global Inside Address 20.0.0.1 is natted on port number 1 for ISAKMP session coming from R3 (10.0.0.3) and ESP packets are encapsulated using port 1024 so here we have a double port translations for traffic coming from the second crypto peer R3, I can verify this looking at logs:

R3#
*May 12 10:25:03.450: IPSEC(sa_request): ,
(key eng. msg.) OUTBOUND local= 10.0.0.3:500, remote= 20.0.0.2:500,
local_proxy= 50.0.0.0/255.255.255.0/256/0,
remote_proxy= 40.0.0.0/255.255.255.0/256/0,
protocol= ESP, transform= esp-3des esp-md5-hmac  (Tunnel),
lifedur= 3600s and 4608000kb,
spi= 0x0(0), conn_id= 0, keysize= 0, flags= 0x0
*May 12 10:25:03.450: ISAKMP:(0): SA request profile is (NULL)
*May 12 10:25:03.450: ISAKMP: Created a peer struct for 20.0.0.2, peer port 500
*May 12 10:25:03.450: ISAKMP: New peer created peer = 0xB22FBE48 peer_handle = 0x80000002
*May 12 10:25:03.450: ISAKMP: Locking peer struct 0xB22FBE48, refcount 1 for isakmp_initiator
*May 12 10:25:03.450: ISAKMP: local port 500, remote port 500
*May 12 10:25:03.450: ISAKMP: set new node 0 to QM_IDLE

R2#
*May 12 10:25:03.453: ISAKMP (0): received packet from 20.0.0.1 dport 500 sport 1 Global (N) NEW SA
*May 12 10:25:03.454: ISAKMP: Created a peer struct for 20.0.0.1, peer port 1
*May 12 10:25:03.454: ISAKMP: New peer created peer = 0xB43C5CB0 peer_handle = 0x80000003
*May 12 10:25:03.454: ISAKMP: Locking peer struct 0xB43C5CB0, refcount 1 for crypto_isakmp_process_block
*May 12 10:25:03.454: ISAKMP: local port 500, remote port 1

During ISAKMP phase 1 R3 and R2 detect the presence of a NAT device, so they start UDP encapsulation of ESP packets:

R3#
*May 12 10:25:03.540: ISAKMP:(1001):beginning Quick Mode exchange, M-ID of 2199629583
*May 12 10:25:03.540: ISAKMP:(1001):QM Initiator gets spi
*May 12 10:25:03.540: ISAKMP:(1001): sending packet to 20.0.0.2 my_port 4500 peer_port 4500 (I) QM_IDLE

R2#
*May 12 10:25:03.562: ISAKMP (1002): received packet from 20.0.0.1 dport 4500 sport 1024 Global (R) QM_IDLE
*May 12 10:25:03.562: ISAKMP: set new node -2095337713 to QM_IDLE
*May 12 10:25:03.562: ISAKMP:(1002): processing HASH payload. message ID = 2199629583
*May 12 10:25:03.562: ISAKMP:(1002): processing SA payload. message ID = 2199629583
*May 12 10:25:03.562: ISAKMP:(1002):Checking IPSec proposal 1

I see that R2 sends out ISAKMP packet on local port 500, remote port 500 and UDP/ESP packet on port 4500 (local and remote), NAT-ROUTER translates port 500 into port 1 and port 4500 into 1024 when sending traffic to R2 and translates back these port 1 and 1024 into 500 and 4500 when sending back traffic to R3.

Checking Logs on NAT-ROUTER:

NAT-ROUTER#sho log | i UDP
*May 12 10:25:03.453: NAT: UDP s=500->1, d=500
*May 12 10:25:03.455: NAT: UDP s=500, d=1->500
*May 12 10:25:03.474: NAT: UDP s=500->1, d=500
*May 12 10:25:03.483: NAT: UDP s=500, d=1->500
*May 12 10:25:03.498: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:03.500: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:03.550: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:03.564: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:03.572: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.452: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.455: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:05.463: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.466: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:05.471: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.474: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:05.478: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.482: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:05.486: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.491: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:05.499: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.502: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:05.508: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.518: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:05.523: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.525: NAT*: UDP s=4500, d=1024->4500
*May 12 10:25:05.538: NAT*: UDP s=4500->1024, d=4500
*May 12 10:25:05.541: NAT*: UDP s=4500, d=1024->4500

From these tests I can conclude that:

1] When Cisco IOS does NAT crypto peers by default are able to detect presence of a NAT device and adapt the IPsec traffic so that NAT-ROUTER can use UDP ports to perform NAT-Translations and have not ambiguous entries in its NAT Table.

2] NAT-T capability of a crypto peer is enabled by default and works exchanging NAT-D payload using hash values of local peer’s source IP address and port and remote peer’s destination IP address and ports.

3] To disable NAT-T transparency udp-encapsulation the command is

R1(config)#no crypto ipsec nat-transparency udp-encapsulation ?
<cr>

§§§ NAT-T TRANSPARENCY AND IPSEC AWARE NAT §§§

Reading previous sections we can think that when NAT-T Transparency udp-encapsulation is disabled on a crypto peer IPsec will not work if a NAT device is present on the path; I try to do that to check if this is true or not.

R1#sh run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 20.0.0.2
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
crypto map MY-MAP 1 ipsec-isakmp
set peer 20.0.0.2
set transform-set MY-SET
match address LAN-30-40
crypto map MY-MAP

R1(config)#no crypto ipsec nat-transparency udp-encapsulation

R1#sh run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 20.0.0.2
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
NO CRYPTO IPSEC NAT-TRANSPARENCY UDP-ENCAPSULATION
crypto map MY-MAP 1 ipsec-isakmp
set peer 20.0.0.2
set transform-set MY-SET
match address LAN-30-40
crypto map MY-MAP

On R2 I leave the same configuration used in previous tests.

R2#sh run | s crypto
crypto isakmp policy 1
encr 3des
hash md5
authentication pre-share
crypto isakmp key MY-KEY address 20.0.0.1
crypto ipsec transform-set MY-SET esp-3des esp-md5-hmac
mode tunnel
crypto map MY-MAP 1 ipsec-isakmp
set peer 20.0.0.1
set transform-set MY-SET
match address LAN-30-40

Then I activate debug crypto (isakmp/ipsec) debug ip nat and monitor capture buffer on involved routers:

R1#monitor capture buffer R1_BUFF max-size 2000 circular
R1#monitor capture point ip process-switched R1_PROC both
R1#monitor capture point ip cef E01 Ethernet0/1 both
R1#monitor capture point ip cef E00 Ethernet0/0 both
R1#monitor capture point associate R1_PROC R1_BUFF
R1#monitor capture point associate E01 R1_BUFF
R1#monitor capture point associate E00 R1_BUFF

R2#monitor capture buffer R2_BUFF max-size 2000 circular
R2#monitor capture point ip process-switched R2_PROC both
R2#monitor capture point ip cef E01 Ethernet0/1 both
R2#monitor capture point ip cef E10 Ethernet1/0 both
R2#monitor capture point associate R2_PROC R2_BUFF
R2#monitor capture point associate E01 R2_BUFF
R2#monitor capture point associate E10 R2_BUFF

NAT-ROUTER#monitor capture buffer NAT_BUFF max-size 2000 circular
NAT-ROUTER#monitor capture point ip process-switched NAT_PROC both
NAT-ROUTER#monitor capture point ip cef E01 Ethernet0/1 both
NAT-ROUTER#monitor capture point ip cef E00 Ethernet0/0 both
NAT-ROUTER#monitor capture point associate NAT_PROC NAT_BUFF
NAT-ROUTER#monitor capture point associate E01 NAT_BUFF
NAT-ROUTER#monitor capture point associate E00 NAT_BUFF

R1#monitor capture point start R1_PROC
R1#monitor capture point start E00
R1#monitor capture point start E01

NAT-ROUTER#monitor capture point start NAT_PROC
NAT-ROUTER#monitor capture point start E01
NAT-ROUTER#monitor capture point start E00

R2#monitor capture point start R2_PROC
R2#monitor capture point start E01
R2#monitor capture point start E10

Testing ping from Host10:

Host10#ping 40.0.0.2 source 30.0.0.10 repeat 10
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 40.0.0.2, timeout is 2 seconds:
Packet sent with a source address of 30.0.0.10
.!!!!!!!!!
Success rate is 90 percent (9/10), round-trip min/avg/max = 6/7/14 ms

Ping works!

R1#show crypto isakmp sa
IPv4 Crypto ISAKMP SA
dst             src             state          conn-id status
20.0.0.2        10.0.0.1        QM_IDLE           1001 ACTIVE

R1#sh crypto ipsec sa | i pkts
#pkts encaps: 9, #pkts encrypt: 9, #pkts digest: 9
#pkts decaps: 9, #pkts decrypt: 9, #pkts verify: 9

#pkts compressed: 0, #pkts decompressed: 0
#pkts not compressed: 0, #pkts compr. failed: 0
#pkts not decompressed: 0, #pkts decompress failed: 0

Encryption works too. So what about disabling udp-encapsulation? To answer this questions look at NAT-TABLE:

nat-pic29

and compare it to the case when nat-t udp encapsualtion is configured (by default):

nat-pic30

When NAT-T is disabled IOS uses another embedded mechanism to let IPsec traffic flowing through the NAT Device. This mechanism matches the SPI number associated with IPsec SA in each directions, the concept is: since spi is unique NAT-ROUTER can use it to distinguish among entry in its NAT-TABLE, looking at the following captured packets I can see that NAT entries use number 4BD798D9 and number FA4211D5 for Inside Local Address and Outside Global Address, this number are the SPI number associated to the IPsec SA:

nat-pic31

Then, IOS by default is:

1] NAT-T capable –> CRYPTO IPSEC NAT-TRANSPARENCY UDP-ENCAPSULATION is on by default (you don’t see it in running config, you see it when you disable it)
2] NAT IPsec Aware –> CRYPTO IPSEC NAT-TRANSPARENCY SPI-MATCHING is on by default (you don’t see it in running config, you see it when you disable it)

When both methods are on (by default) NAT-T is preferred and crypto peer will detect the presence of a NAT device using NAT-D payload exchange. If NAT-T is disabled IOS fall back on SPI-MATCHING, in this case no NAT-D payloads are exchanged (verify this with the whole wireshark file R1_IPSEC_NAT_NO_NAT-T-UDP-ENC) and NAT-ROUTER creates an entry for each flow in each direction using spi number to distinguish the entry.

nat-ipsec

NOTE: IPsec Aware NAT cannot be disabled, NAT-T can be disabled, if you configure ‘no crypto ipsec nat-transparency udp-encapsulation’ and try also to configure ‘no crypto ipsec nat-transparency spi-matching’ you receive no errors but you don’t see the command ‘no crypto ipsec nat-transparency spi-matching’ in configuration meaning that is not disabled.

REFERENCE:

INE CCIE Advanced Technologies Class

NAT Getting Started

NAT Definitions

Simultaneous Static and Dynamic Nat

Nat Outside