Saturday, September 18, 2010

Cisco IOS Destination-NAT

Throughout my career in networking, I’ve often implemented Source-NAT translation on Cisco routers (the practice of replacing the source IP address in packets) to either hide the private address or because the subnet overlapped with another location.  However, I’ve rarely implemented Destination-NAT (the practice of replacing the destination IP address in packets).  Destination-NAT, it turns out is not as self-explanatory as Source-NAT when it comes to CLI commands.  And, the materials I found on CCO and Google searches did not clearly explain how to do this simple task in Cisco IOS.  So, I think it warrants a quick article in case others need!

Why would you want to Destination-NAT?  It is needed when a service provider assigns private addressing (RFC 1918) to a service you need to target and you already have a route in your network for that subnet, which goes elsewhere.  Or, you need to direct certain lines of business (LOB) to use one circuit over another, to reach the same service.  In this case, you can have one LOB target the real IP to reach the service over a specific circuit, and another LOB would target the Destination-NAT IP.  This way, the two LOBs don’t have to share the circuit.

If you are translating one IP to one IP, there is no need for a pool, or an ACL, for either source OR destination-NAT.  You would use the “ip nat inside source static” or “ip nat outside source static”.  I’ll explain which one to use for which scenario.  I just depends of the direction the session is initiated.  I usually assign the interface for my network (the one closer to the network core) as the “inside” interface using the “ip nat inside”.  And the interface facing the other network as “outside” using the “ip nat outside” command.  This also happens to be the way zone based firewalls work, although NAT has nothing to do with security or firewalls, and you could very well do the opposite.

Before I give a Destination-NAT example, let’s do a Source-NAT because that’s more common.  Here is the topology:

Core network where sessions get initiated ( –> NAT router –> Other network (

In this scenario, we hide the core network’s real host IP address ( for that flow with the NAT range IP address of  So, the “other network” sees our traffic coming from the NAT address.

The IOS CLI command to do this is:

ip nat inside source static

Of course, you have to ensure there is a route for the translated address in the routing tables along the path for any router to reach that destination. 

Now, let’s say we also need to use this NAT router to translate the destination of our packet.  In other words, there is a LOB who needs to reach via a different path, or we simply cannot advertise into our core, for various reasons.  We need the host on our core to be able to target by using destination address

At the NAT router, you can’t use “ip nat inside destination static” because there is no such command in IOS.  Instead, you would use the following:

ip nat outside source static add-route

As you can see, we are dealing with the outside NAT interface, which means we NAT in the return direction, which is why we have to reverse the order of the translation and use “source” instead of “destination”!

The “add-route” keyword may be needed if there is no route (or a route with an incorrect next-hop) in the routing table for the old “not-translated” destination.

Again, you have to ensure the route is advertised inside your core, so the hosts can reach it.

Note- not all applications are tolerant to NAT, so make sure you test!