iptables – NAT MASQUERADING in Linux

In a previous post I wrote about how can we accomplish NAT with Cisco devices. This time let’s examine how can we implement the same thing in Linux with the topology below. Basically we’re going to turn our Kali1 machine into a router which is a Docker instance running in GNS3.

Step 1: GET AN ADDRESS VIA DHCP ON ETH0, TEST CONNECTION

First I leased an IP address via my AP with the dhclient command (192.168.122.226). Yes, it’s a private RFC 1918 address, and our network is double NATted, but for the purpose of this demonstration let’s imagine that it is a public address, and eth1 faces our local network with private addresses from the 10.0.0.0/24 subnet.

Let’s verify our interface configurations with the ip command.

eth0 got its address, I tested my connection as well as the DNS name resolution by pinging an address on the internet.

Step 2: ASSIGN IP ADDRESS MANUALLY TO ETH1

We’re going to configure the eth1 interface of the Kali1 machine manually (although we’ve a DHCP server on the local network – we’ll be dealing with that later). This interface will be the default gateway for the hosts on the local network, so it’s reasonable to have a static address.

Or we could’ve done the same thing using the deprecated ifconfig command.

Make sure that our routing table is correct:

We have a default route through eth0 which we’ve just got via DHCP in Step 1.

Step 3: ENABLE PACKET FORWARDING

To turn our Kali1 machine into a router we need to modify an important kernel parameter in Linux with the sysctl utility. To be able to forward packets between our interfaces we need to make sure that the net.ipv4.ip_forwarding kernel parameter is enabled. We can verify this with one of the following commands:

1 in this case means that the IP forwarding is enabled. If it shows 0 aka. disabled we can turn IP forwarding on by issuing one of the following commands:

or

Either of them is a complete solution. But a useful reminder that by issuing these commands the kernel parameter we’ve just enabled won’t be persistent, that is we’re going to lose our settings after system reboot.
To make our settings we’ve configured above persistent we also have 2 options. Option no.1 is the easiest, just issue the following command:

Option no.2 edit the /etc/sysctl.conf file by uncommenting the following line:

Step 4: CONFIGURE R1 AS DHCP SERVER FOR LOCAL NETWORK

For the hosts in the local network I designated a Cisco IOSv router as a DHCP server for assigning IP addresses for the three hosts. I could’ve assigned addresses for them statically via the ip or ifconfig utility, but this method doesn’t scale, so decided to designate a DHCP server for this purpose. Here is the configuration of R1 (some Cisco stuff):

I checked that the addresses have been assigned correctly to the three hosts:

Step 5: CONFIGURE NAT MASQUERADE WITH IPTABLES

The most important thing: we need to edit our firewall rules with iptables on the Kali1 machine. To perform NAT we need to configure the NAT table (-t NAT) instead of the filter table which is the default. We define our rule on the POSTROUTING chain which means we’re going to “translate” the internal addresses after routing calculations. With the -o flag we appoint the output interface interface, eth0 in this case.

So by implementing NAT we “translate” the source IP addresses of our packages: Kali1 simply switches the source IP address of our internal hosts to the address of his eth0 interface.

To visualize what we’ve just done let’s view some packet capture between our Kali1 and the NAT Cloud and between Kali1 and the IOSvL2 switch.

Packet capture between Kali1 and the IOSvL2 switch
Packet capture between Kali1 and the IOSvL2 switch
Packet capture between Kali1 and the NAT Cloud
Packet capture between Kali1 and the NAT Cloud

As it can be seen the source IP addresses have been swapped.

By doing that we hide the addresses of our internal hosts from the outside network. We also only need one public address for many hosts.