NAT on a stick

NAT on a stick.

I ran into this a while back, and then again the other day. Its really a puzzling way of doing NAT.

The topology:

Imagine this scenario (even though its very unlikely as far as i can see):

Our organisation has purchased an internet connection with a local provider. They are only able to provide us with 2 available IP addresses + our transit IP address.

We have several servers, and alot of clients that needs to connect to the internet.

NAT is the obvious choice. However, theres a problem. Our gateway only have 1 interface, and we are not allowed to buy anything else! Also, we cant use sub-interfaces.

(i told you it was quite unlikely 🙂 )

So, our IP addresses are:

Our public IP transit address: 83.84.85.130/30

Our gateway at the ISP: 83.84.85.129/30

Our extra assigned IP addresses: 70.70.70.1/30

Our internal IP addresses: 192.168.100.0/24

We have configured a router to act as the server, and this router has the IP address: 192.168.100.50

Beyond that, we have a loopback interface with this IP address: 10.0.0.1/24

For demonstration purposes, the entire internet is represented as 1.1.1.1, which is a loopback on the ISP router.

Also, i know that the choice of IP addresses would not really work in real life, but bear with me, its not important for the scenario.

Our first hat-trick is to get basic connectivity between our gateway-router (R1) and our LAN, as well as to the ISP.

Lets configure the interface in this manner:

Lets verify that we have connectivity:

To our server:

And to our ISP:

Everything is OK! so far.

Lets just check the routing table on R1, so you can all follow along a bit better:

Okay, everything seems fine RIB wise.

Next up is a mind-bender. Remember that in order for NAT to work, we need to designate one interface as inside, and another as outside.

This is really to create a logical flow of things. However, our main limitation is that we only have 1 interface to operate on. If we had a router with two interfaces, we could use one as inside and the other as the outside interface.

What we want to utilize in order to get this working, is how IOS process packets.

I can highly recommend that you take a look at this: http://www.cisco.com/en/US/tech/tk648/tk361/technologies_tech_note09186a0080133ddd.shtml

First, inbound packets to the router are first subject to policy-based routing, before any NAT’ing takes place. It is also taking place right before ordinary routing.

What we want to do, is send packets to the R1 router, these will be received by the “inside” interface, completing the first requirement. The routing decision has already been made, we need to send it to loopback0. This is done in order to “hit” an outside interface.

When the loopback interface sees the packets, it makes the routing decision, not per policy-based routing, but by ordinary routing. However, IOS routes it OUT of the loopback0

interface, back to our f0/0 interface. This completes the second requirement, going out of the interface thats configured as “outside”.

Since it doesnt match what we want to policy-base route on f0/0, it gets routed OUT of the f0/0 interface, NAT’ed as 70.70.70.1-2.

Return answers goes through the same process. It is received by the f0/0 interface, gets policy-routed (since the outside NAT is not on the f0/0 interface) to the loopback interface, which IS the outside interface and gets translated back to our original source (LAN IP addresses).

So lets get the components configured.

One of the most important components is our policy-routing. As mentioned, we will put our policy onto the f0/0 interface, which means that packets comming into this interface will be subject to policy routing if it matches the route-map.

We want two things to match our policy-routing. Namely inside traffic, that needs to get NAT’ed in order to goto the internet, and return traffic, destined for the NAT addresses (remember they must hit the outside interface again).

This access-list should do the job:

We then need to create our route-map used for policy-based route:

So, everything that matches our access-list gets policy-routed to the loopback0 interface.

Lets go ahead and apply it to the interface, so we are done with it:

At this point, we are done with the policy routing section. Next up is our NAT setup.

Remember that we want our f0/0 interface to be the inside interface and the loopback0 interface to be the outside interface, so lets get that out of the way:

Alright, next up is to create a pool of IP addresses we can use for the NAT process. (I want to point out at this point that i have not gotten NAT with the 1 transit IP address working in this scenario).

The above creates a NAT pool, which states that we want to use 2 IP addresses, namely .1 and .2.

We also need to create an access-list that specifies which internal (as Cisco calls Inside Local) IP addresses we want to perform NAT on:

Basically it states that all internal IP addresses will be NAT’ed when going out the outside interface.

Finally, lets put our NAT statement into place:

So we want to take all IP addresses listed in access-list 120 and replace the source-address with the addresses in the TSTPOOL. We also want to perform PAT (port based NAT) to further increase our chances of getting an internet connection. (Otherwise, only 2 simultanous connections could exist).

Now, lets test this out! Lets try with a ping from our Server-1 to the internet (which is 1.1.1.1):

Awesome, we have connectivity. Lets check out what the “internet” is really receiving by looking at the ISP router:

Again, what we would expect. The source address has been translated into our assigned IP addresses. As a final confirmation, lets check the NAT status on R1:

As can be seen, we have translated the source-address of 192.168.100.50 to 70.70.70.2.

I want to show you the output of “debug ip policy” on R1, so you can see the logic taking place:

And later on:

The first one shows that a request from an internal host is POLICY routed to the loopback0 interface. The second one shows the reply, in which the destination 70.70.70.2 is POLICY routed to the loopback0 interface.

This matches our access-list for policy based routing.

In summary, this is VERY ugly and it has some caveats. For example you cannot specify your own next-hop ip address on the loopback interface. If you had a /24 loopback interface, you could specify an ip-next hop of something else in there and IOS would try to route it through the loopback, resulting in it getting hit with the ip nat outside. Also, i have not found a way to use the transit net as the source address as you would normally use.

I wanted to show you this so you dont go “What!?” if you see it anywhere, which is most likely to be in a lab scenario, not real-life.

So please! dont ever use this 🙂