Tuesday, November 10, 2020

Cisco IP NAT to Single External IP Address solution

Since it took me many hours to find this solution, I figured I would post it in as many places as possible for posterity.

TL;DR

For NATing to a single external IP address, don't configure a pool of a single address, even though the router allows it. Use this approach instead:
access-list 1 permit 192.168.1.0 0.0.0.255
ip nat inside source list 1 interface gigabitethernet 0/0/0 overload

At work, we have been a big Cisco shop for decades, so I have worked on IOS, IOS-XR, IOS-XE, etc, etc. For our lab connectivity needs, we have used NAT a ton. It is simply to allow private internal networks to reach the internet for housekeeping needs, no need for CGN. Simple IP NAT with overload has served us well for years. Until the ASR.

This started about 5 years ago when we stood up a new lab. We put in beefy Cisco Switches for internal switching and beefy Cisco ASRs for our relatively minimal routing needs. Frankly it was overkill, but we were replicating a 4G LTE packet core, so why not leverage it for our internal needs as well. But we had a consistent problem with what we thought should be simple NAT. It would work for a time, then stop working. The NAT translations were there, but no traffic would flow. This was true for both static and dynamic NAT. Sometimes a reload would solve the problem (temporarily), sometimes not. But as a colleague was administering those routers, I didn't think about it too much...wasn't directly my problem.

Recently I setup another lab for testing of industrial controls. I'm using a small ASR 1001-X for my routing needs. As I need my internal workloads (VMs, containers, etc) to be able to pull from public repos, I setup NAT on the ASR, following the documentation, such as this. The classic example of "Using NAT to Allow Internal Users Access to the Internet".

ip nat pool net-208 172.31.233.208 172.31.233.233 netmask 255.255.255.240 <------
access-list 1 permit 192.168.1.0 0.0.0.255
ip nat inside source list 1 pool net-208 overload
interface gigabitethernet 1/1/1
ip address 192.168.201.1 255.255.255.240
ip nat inside
!
interface gigabitethernet 0/0/0
ip address 192.168.201.29 255.255.255.240
ip nat outside
!

The examples all seem to show the same scenario: using a small range of external IPs to which to translate the internal IPs, and in this case with overload for port translation as well.

The command requires a startIP, a stopIP and a subnet (evidently to not accidently NAT to the network or broadcast address). So I just put the same IP address into both the start and stop, essentially a pool of a single IP address. The CLI accepted it and the NAT worked...for a day or two. Then stopped.

Now, I'll admit, I'm not one to read every word in documentation, but after extended searches the only reference in the docs to the correct solution is a similar solution is in the context of VRFs.

After hours of searching, I found this post. The answer, it seems, is simple, if not clearly documented.

For a single outside IP address, you don't use a pool. You use a slightly different command:
ip nat inside source list 100 interface <outside interface> overload

So the resultant example would look like this:

access-list 1 permit 192.168.1.0 0.0.0.255
ip nat inside source list 1 interface gigabitethernet 0/0/0 overload <---
interface gigabitethernet 1/1/1
ip address 192.168.201.1 255.255.255.240
ip nat inside
!
interface gigabitethernet 0/0/0
ip address 192.168.201.29 255.255.255.240
ip nat outside
!

As soon as I made this change, NAT worked perfectly. Now, it has only been about 12 hours since the change, and it worked for a bit using the previous approach, but I suspect this will stick.

I hope that helps someone else pulling their hair out trying to figure this out. I find it odd that A) this doesn't appear to be documented well, and B) that the original pool definition approach is not rejected by the CLI. Even more, I find it super odd that my previous approach worked for a while, then stopped, never to work again.



No comments:

Post a Comment