This post will describe how NAT works. The reason for doing a blog post on NAT
is twofold. There is a lack of good documents out there describing NAT and I
want to do some learning for myself as well.

When we are talking about NAT we have some terminology that is commonly used.
Since the address is changed along the way we need to describe which address
we are referencing when talking about the IP address. The terminology is this.

Inside local address โ€“ This is the address as seen on the LAN (inside) before
the translation occurs.

Inside global address โ€“ This is the address as seen by other hosts on the Internet.
This is the address after translation has occurred.

Outside local โ€“ This is the address on the LAN of the other side. Note that if other side
is not running NAT the outside local and global may be the same. In the diagram the other
side is running public IP addresses on the inside (a valid design).

Outside global โ€“ The IP address as seen by other hosts on the Internet, this may be the
same as the inside local depending on if NAT is used or not.

When using NAT we need to define inside and outside interfaces (except if NVI is used).
The LAN interface(s) are the inside interfaces and the WAN interface(s) are the outside
interfaces. Translation is done when traffic is going from an inside interface to an
outside interface or vice versa.

The most basic NAT we can do is a 1:1 static NAT where the inside local address is
translated to an inside global address. We can map to an IP directly or to the
outside interface. To NAT to an interface the syntax is:

ip nat inside source static INSIDE_LOCAL interface OUTSIDE_INTERFACE

Traffic sourcing from the inside local address will be translated
to When we are doing static NAT there is a bidirectional translation
so when traffic is coming back in the outside interface the destination is
translated from inside global to inside local address. We can see this when we
debug ip nat detail.

First we see the ICMP packet coming in and the source gets translated and then
the return packet comes in and the destination address is translated. This is
how the translation table looks like.

We can also do a static NAT and choose what the inside global address should be. The syntax is this:

ip nat inside source static INSIDE_LOCAL INSIDE_GLOBAL

We now see that the source is translated to

The translation table looks like this:

When doing regular static NAT like this we can only map one inside
local to one inside global. What if we want to map several outside
addresses to the same inside address? To do that we need to create
extendable NAT translations. The syntax is the same but with the keyword
extendable at the end.

The translation table now looks like this:

If we ping from the other side we will see that being translated to

The translation table is below.

When we are doing static NAT translations we can also match on an access-list.
The good thing about matching on an ACL is that we can specify which hosts we
want to have translated and which we want to leave alone. We can create an ACL
so that traffic to gets translated but traffic to will arrive
with its original source address. The syntax is:

ip nat inside source list LIST_NAME interface INTERFACE_NAME

We can only translate to an interface or a pool of addresses when using a list
as the source.

We will debug on the destination to see which address the ICMP packet coming in has.

Once again we look at the translation table.

So we can see that when sending traffic to it does not get
translated but traffic to does. We can confirm by looking
at the ACL counters.

We can also configure NAT to NAT 1:1 for an entire network. This means that
the inside local address will be translated to If
we were sourcing traffic from .20 then that would be translated to .20 so the
addressing consistency is kept. This can be useful if we have like a web server
that is reachable from on the inside and when we want to access
it from the outside we now that it will have the IP We should
rely on DNS for reaching web servers but knowing the IP can be good in case
of a DNS failure. Use the following syntax.


Now when we ping we should see the source getting translated to

And the translation table.

We can also do NAT for a pool of addresses. Say that we have been granted
a new pool of addresses from our ISP. The pool is We create
a NAT pool matching this and then we enable NAT for the address.
The syntax is:

ip nat inside source list ACL_NAME pool POOL_NAME

We do a ping to look at the translation.

We can see that the source address got translated. As you can see
we can do NAT for networks that are not configured on the router.
This is the translation table.

When doing NAT pools we can also make the host portion of the address match
if we want to. We do that like this.

ip nat pool prefix-length type match-host

Now when we ping the IP should get translated to

Which it did. So even with pools we can match the host part of the address.
This is the translation table.

With NAT pools we can also do rotary assignments if we want or overload
the pool if we want to do Port Address Translation (PAT).

Now we will also create a scenario where using a route-map. Using route-maps
we can create more advanced scenarios. For this scenario telnet traffic
going to will get one source IP and HTTP traffic will get
another source address.

Now to verify the configuration, first we send telnet to

Now we send to port 80 instead.

And the translation table.

So using route-maps we can do more advanced scenarios. If we have multiple
inside interfaces we could even match on those.

NAT can also be used to do a form of basic load balancing. Several
inside local addresses will be mapped to one inside global address.
A pool of inside local addresses will be created and handed out in a
rotary fashion.

IP addresses, and will now be handed out in a rotary
fashion when someone tries to access the IP We can see this when
debugging the NAT translation.

So this performs a basic form of load balancing. The only thing different here is
that we are using the ip nat inside destination command. This translates the
destination of the packet. Usually we translate the source of the packet but
since static NAT is bidirectional in the other direction the destination of
the packet will be translated. When doing this form of NAT we need to trigger
it by sending TCP packets. Just sending ICMP will not trigger the NAT translation.

We have been through a lot of scenarios so far. Almost all of the scenarios
describe how to translate the source IP of the packet going out from the local
network. What if we want to translate the source of the address coming in on
the outside interface instead? This can be useful in scenarios
where there are overlapping subnets, e.g. the same subnet is used on two different
companies and they need to connect through a VPN tunnel or such. Syntax is the

ip nat outside source static OUTSIDE_GLOBAL OUTSIDE_LOCAL

Here we see that the source of the packet is translated when coming in
on the outside. And this is the translation table.

The final scenario I want to describe is NAT on a stick. It’s not a very
common scenario but the idea is this. Look at the topology below.

R3 has only one interface which leads to a problem because we need to define
one interface as inside and the other as outside. How can we solve this?
We will use what is called NAT on a stick. R3 will do policy routing and
send traffic to its loopback to trigger the NAT process. R1 and R2 need
to have default routes towards R3 which will be doing the NAT. When R1
pings with a source of its loopback ( that should be translated
to When R2 pings from its loopback ( then it should
be translated to We start by setting up the policy routing.
We create an access-list matching traffic from to
Then we create a route-map matching the ACL and set the interface to
loopback0. The loopback interface will be the NAT inside interface.

We also disable ICMP redirects so that R1 does not bypass R3 when
sending traffic to R2. We need to add a few routes on R3 for the
scenario to work. The network is routed to R1. Then and is routed to R2. Why do we need to route
the network to R2? This is because the order of operations
in Cisco routers. On inside to outside policy routing is done first, then routing
and then NAT. On outside to inside NAT is done first, then policy routing
and after that routing. Before we add the rest of the configuration
lets think about the traffic flow.

R1 sends an ICMP packet with (S= , D= The packet comes
inbound on R3 on Fa0/0. The traffic coming in matches the policy and the packet
is looped through R3 lo0. Loopback0 has ip nat inside so this triggers the
NAT process. The source IP is translated to and the destination
is translated to, then the packet is sent out Fa0/0.
The packet reaches R2 with (S=, D= R2 sends
an ICMP reply with (S=, D= The packet comes in on R3
Fa0/0 which is the NAT outside interface. That triggers a translation of the
source from to The destination is also translated from to R3 then checks the routing table and
sends the packet back out Fa0/0 to R1. The packet reaches R1 with
(S= , D= And that finishes the flow. Now to
configure it.

Take a look at the translation table.

Now to see if it works. We will debug NAT on R3 to see what is happening while
pinging from R1.

Finally here is a drawing that is describing the traffic flow.

This has been
a very big post and I wrote it to have as a reference for my studies. You
don’t have to read the whole post at once but I hope that you find some
useful scenarios that you can try out for yourself. One final piece of advice
is that if you run NAT in Dynamips you should assign that router 256MB of
memory or you will see some strange things happening like sh run not working.

A look at NAT – inside, outside and NAT on a stick
Tagged on:                                 

13 thoughts on “A look at NAT – inside, outside and NAT on a stick

  • October 3, 2012 at 4:58 pm

    Thank you! This was an excellent post.

    • October 3, 2012 at 5:02 pm

      Glad you liked it ๐Ÿ™‚ Good luck with your studies.

  • October 3, 2012 at 10:58 pm


    if a local IP address is not being translated into a global address when sending traffic to, how does the know where to send a icmp echo reply? 192.168.x.x addresses could be behind every single router in the inter-network.

    • October 4, 2012 at 8:15 am

      For this scenario I just had some default routes in the network. You would of course need a route back to the source. For a real network you would not use private addresses of course in that case. You would have a public range and you would make sure that it doesn’t go through NAT but you might have a private network that you do want to NAT as well.

  • October 4, 2012 at 4:28 am

    hey Daniel – just a quick comment re: NAT-on-a-stick. Wouldn’t the interface loopback0 need to be ip nat outside, while the ingress interface (int fa0/0) be ip nat inside?

    Otherwise, it is a great post/review!

    • October 4, 2012 at 8:23 am


      I think it is possible to do this scenario that way as well. You would just have to change the NAT statements since you would hit the outside first and then go to inside from R1 perspective. This is because PBR is done before NAT on ingress so the packet would go to loopback0 and hit the outside NAT statement and then go out Fa0/0 which is the inside. So it would be something like this:

      ip nat inside source static
      ip nat outside source static

      I’ll have to try it out ๐Ÿ™‚

  • January 6, 2013 at 12:45 pm

    straight out of Narbik CCIE Workbook Vol2 ……Be Original

    • January 6, 2013 at 3:06 pm

      Not sure which part you are referring to as I haven’t done many Narbik labs.

  • May 25, 2016 at 10:15 pm

    Not many great Info on Nat out there, your is best I have read about NAT. Thanks for sharing with us!

  • April 16, 2017 at 7:35 am

    “Loopback0 has ip nat inside so this triggers the
    NAT process. The source IP is translated to and the destination
    is translated to, then the packet is sent out Fa0/0.”

    As you said,the order of operation is to first route, then translate, when packet first hits the NAT inside interface. So, to be more precise, when packet is looped through the lo0 (according to PBR route map set interface statementโ€‹), it will first be routed to fa0/0 according to static route to destination, and only then, when hitting the fa0/0, R1 will translate the source and destination addresses according to the 2 nat inside and outside source static rules.
    Please, correct me, if I’m wrong. Also, could you add the nat rules to the configuration?

    And thanks for great post!

  • Pingback:YA-NAT: Yet Another Network Address Translation Post –

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: