Linux NAT(Network Address Translation) Router Explained

Sarath Pillai's picture
Network Address Translation in Linux

For computer's to communicate with each other, each and every computer must have a unique address to send and receive data. If you do not have a unique address other's will not be able to send data to you. In IPv4 there are around 2^32 addresses, out of which 588514304 are for special purpose, which means we only have 2^32 - 588514304 unique public ip addresses.

Imagine an office in which you have 1000 computer's for the employees to work. If each of them needs to communicate with hosts in the internet, assigning a unique public ip address to each of them will be idiotic and will also be a waste of internet resource.

Also sometimes you want to hide your internal network address details from the publicly available internet, for security reasons. NAT is a solution that was made to solve these problems.

 

What is NAT(Network Address Translation)?

 

The name itself suggests that it does a translation of addresses. IP address can be translated to another with the help of NAT. The primary job of a NAT device is to rewrite the source and destination address of an IP packet.

There are hardware devices that does this job, but we will be doing this with the help of a Linux system(as it will do almost all the job done by a hardware nat device.).

Network Address Translation using Linux

 

In the above shown diagram, a linux machine with two IP addresses(One private and one public) is used as a NAT router. The private machine's that are part of internal network cannot directly communicate with the hosts in the internet, because the source address of a private range cannot be routed to internet.

In other words you can say that those internal machine's(192.168.0.3,192.168.0.4,192.168.0.5) cannot reach internet directly & hosts from internet also cannot reach them directly. In a way you can say that our internal machine's are secure till a certain extent as an attacker from internet has no direct contact with them.

In case our internal machine's needs to communicate with hosts on the internet, then our Linux NAT router in between will rewrite the their private addresses to its own public ip address(4.4.7.23 in our case.). So external hosts(hosts on the internet), will feel that the connection is initiated by the Linux router.

You might be thinking, how the Linux router machine know which packet are from which internal machine? and how will it manage these many connections from different internal IP addresses together?. The answer to that question lies in connection tracking.

 

What is connection tracking in Linux?

 

 

Connection tracking is a mechanism done by Linux machine's to keep track of TCP connections that are going out and coming inside. This connection tracking mechanism enables Linux machine's to accurately send packet's which are NATed to the exact internal machines, who initiated the connection. You can say that the complete UDP/TCP connection status is stored in the connection tracking table. This connection tracking tables consists of the following things.

  • Ip addresses
  • Protocols
  • Port number's
  • Status of the connection

Let's see some example entries from a connection tracking table in Linux. This connection tracking information in Linux is stored in /proc/net/ip_conntrack (An important fact to note here is that these connection tracking tables are stored in /proc file system. Which means its stored in RAM for faster access.)

 

[root@myvm1 ~]# cat /proc/net/ip_conntrack
cat: /proc/net/ip_conntrack: No such file or directory
[root@myvm1 ~]#

oops!! i dont have that file in my system. That's because, the kernel module that does the connection tracking is not loaded. So lets load that kernel module with the help of modprobe command.

[root@myvm1 ~]# modprobe ip_conntrack

Now as we have loaded that module, lets see the content of /proc/net/ip_conntrack file.

 

[root@myvm1 ~]# cat /proc/net/ip_conntrack
tcp      6 431999 ESTABLISHED src=192.168.159.128 dst=192.168.159.1 sport=22 dport=56261 packets=118 bytes=13900 src=192.168.159.1 dst=192.168.159.128 sport=56261 dport=22 packets=142 bytes=10776 [ASSURED] mark=0 secmark=0 use=1
udp      17 29 src=192.168.159.1 dst=192.168.159.255 sport=137 dport=137 packets=37 bytes=2886 [UNREPLIED] src=192.168.159.255 dst=192.168.159.1 sport=137 dport=137 packets=0 bytes=0 mark=0 secmark=0 use=1

If you see the above entries from ip_conntrack carefully, it provides the complete information about each and every connections. Like the protocol used (tcp/udp),source and destination address,source and destination port,status of the connection (ESTABLISHED/TIME_WAIT etc), And the duration for which the entry will be alive in the conntrack table (For example in the second line the udp connection will be alive for 29 seconds, which is denoted by the third field.)

With the help of that table, stateful firewall can filter out traffic based on the status of the connection. So if you are using state module in iptables the kernel will automatically load the ip_conntrack module for you(Similarly if you are using NAT table in iptables, it will automatically load the ip_conntrack module).

Now let's understand different types of NAT in Linux, along with its configuration.

 

Masquerade and SNAT in Linux

 

 

This is the most commonly used NAT. SNAT stands for Source Network Address Translation. The name itself tell's you what it does. It rewrites only the source address of the packets while nating. In the previously shown example of NAT many private ip addresses of the range 192.168.0.0/24 gets translated to the public source address of the Linux NAT router(4.4.7.23) .

In this case the internal network hosts, with private ip addresses can reach the internet with the help of SNAT. But hosts from the internet cannot reach those internal hosts directly (It will only reach the internal hosts, if the source was NATed to the Linux router's public IP address.) In other words, connection initiated by the internal hosts to the internet will only be fulfilled(not the reverse).

Even SNAT can be classified into different types based on the translation it does. For example if many internal private IP addresses gets translated to one public ip address assigned to the Linux router, then its called as a Static SNAT.

If many internal private IP addresses gets translated to many different public IP addresses assigned to the Linux router, then its called as a Dynamic SNAT (You can in fact give an ip address range to the Linux router to use as source address while rewriting.)

If you are using masquerading instead of SNAT, then you will be unable to specify the outgoing ip address. It will use the default IP address assigned to the outgoing interface. In a way its good because if you have an internet connection on your Linux NAT router that get's dynamic public ip addresses, then you can simply use masquerading instead of SNAT.

Let's go through the steps involved in completing a connection from a local private ip address to a host on the internet. Suppose our internal host 192.168.0.3 wants to connect to google.com through our Linux NAT router in between, below mentioned are the steps involved in completing that connection.

 

Step 1: In this step the source ip address 192.168.0.3 wants to reach google.com. So this internal machine initiates the connection with the following details.

Source address: 192.168.0.3,Destination address: www.google.com.

As the default gateway for this 192.168.0.3 is 192.168.0.6(which is our Linux NAT router), this packet will reach the linux router

 

Step 2: On receiving this IP packet from 192.168.0.3, our Linux router will look at its iptable rules to see if it has a matching rule for this. Let's say it sees a SNAT or Masquerade rule in the nat table.

The Linux router will change the source ip of the packet from 192.168.0.3 to 4.4.7.23(The public ip address on the Linux NAT router), and will add a line containing the complete information of this connection in /proc/net/ip_conntrack. This will help the router to track this connection.

Step 3: I will not include the steps done by google (Because i dont know what they really do when they get a request cheeky). Anyways that's not part of our concern to understand this NAT tutorial. Let's say google replied to that request with its web page.

On recieving the reply from google, the linux router will check the /proc/net/ip_conntrack to see if that reply belongs to any of its connections. On finding the connection from 192.168.0.3, the Linux router will rewrite the destination IP address from 4.4.7.23 to 192.168.0.3. (Please note the fact, that our linux router only rewrites the destination ip from its own ip to 192.168.0.3 because the request was from 192.168.0.3. The source ip address is left as google.com itself.)

Step 4: Our internal machine with the ip address of 192.168.0.3 gets the reply from google as shown below.

Source address: google.com, destination address: 192.168.0.3

Now let's get inside the configuration of SNAT in linux with iptables.

 

What is DNAT?

 

In the above shown example of SNAT, the connection was initiated by the host inside the internal network. What if a host on the internet needs to initiate the connection. In that case we need to design our Linux router in such a way that traffic from internet to a particular public IP address on the router will be forwarded to one particular private IP address.

Such kind of a configuration is called as DNAT, or destination NAT. It is called a destination NAT because the first address rewriting done by the router is for destination address.

Let's take an example to understand DNAT. Suppose an ip address 2.2.7.23 from the internet wants to communicate with 4.4.7.23(The puclic IP address assigned on our Linux router.), lets go through the steps involved in completing that connection.

Step 1: Host 2.2.7.23 initiates a connection with 4.4.7.23(which is our linux router public ip address) with the following ip packet.

Source Address: 2.2.7.23 Destination Address: 4.4.7.23

Step 2: On recieving the packet, Linux router will rewrite the destination address of the packet from 4.4.7.23 to 192.168.0.3, and adds an entry in the file /proc/net/ip_conntrack containing the complete information of the connection.

Step 3: After processing the request, the reply from 192.168.0.3 will be send to our Linux router with the following IP details.

Source Address: 192.168.0.3, Destination Address: 2.2.7.23

Step 4: On recieving the IP packet, the Linux router will look at the ip_conntrack table to find details about this connection, on seeing that this connection was initiated by 2.2.7.23 to 4.4.7.23 the Linux router will rewrite the source address of the packet to its own public ip address. Hence the resulting final packet that will be send to 2.2.7.23 will be something like the below.

Source Address: 4.4.7.23, Destination Address: 2.2.7.23

Disadvantages of DNAT

  • Configuring DNAT means that you are allowing hosts on the internet to initiate a communication, and will be able to reach private hosts. Which is not a good idea from a security point of view
  • Configuring DNAT using only one public ip address on the router, is a bit difficult

 

Full NAT

Full NAT is nothing but a combination of SNAT & DNAT. If you combine the above explained two methods of nating(SNAT & DNAT), in a single Linux router then you are doing a FULL NAT.

In FULL NAT, both the internal machine as well as hosts form the internet can initiate connections.

 

SNAT and DNAT configuration in iptables

There are three chain's inside the NAT table in iptable. Let's see all of them by having a look at NAT table.

[root@myvm1 ~]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
[root@myvm1 ~]#

As shown above, there are three chains inside nat table. PREROUTING, POSTROUTING, OUTPUT. The main functionality of a router is to route IP packet's. Our Linux router does exactly the same thing. Hence PREROUTING talble will consist rules that needs to be analyzed before a routing decision is made.

Let's do SNAT with the help of iptables.

We will be doing this SNAT configuration with exactly the same example of private network and public ip addresses. Our router has two ip address (192.168.0.6 & 4.4.7.23).

The NIC card with the private ip address is connected to the LAN network where all internal network can talk to each other. Our Linux router will be the default gateway for all other internal LAN machines with the ip range of 192.168.0.0/24, and the other NIC card on the Linux router is connected to the ISP(who provided us with the public ip address of 4.4.7.23)

Let's add an SNAT rule on our Linux router that will help all the internal hosts with the ip range of 192.168.0.0/24 to communicate with hosts on the internet.

 

[root@myvm1 ~]# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j SNAT --to 4.4.7.23

That makes our iptable's nat table look like the below.

 

[root@myvm1 ~]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       all  --  192.168.0.0/24       anywhere            to:4.4.7.23

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

As mentioned earlier masquerading and SNAT are almost the same except the fact that, you cannot specify the outgoing ip address. In masquerading you can specify the outgoing interface instead of the ip address. This is very useful when you get a dynamic public ip address via dhcp from your ISP.

[root@myvm1 ~]# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j MASQUERADE
[root@myvm1 ~]#

Another better approach to do SNAT is to NAT only those packets that will go outside from eth1 interface(Public IP interface) on the Linux router. You can also give an ip address range to iptables, so that iptables can use the range to do SNAT.

 

[root@myvm1 ~]# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth1 -j SNAT --to 4.4.3.27-4.4.3.45
[root@myvm1 ~]#

Most of the people get confused when they hear about PREROUTING & POSTROUTING. POSTROUTING is done for SNAT, because its done after the routing decision is made and just before the packet leaves the system. PREROUTING is done mostly in DNAT because in DNAT you are giving access to internal machines from the internet, because even before a routing decision is made, you need to alter its Destination address(Of course altering destination address will have an impact on the routing decision..hence DNAT is done as soon as the packet reaches the machine, which means PREROUTING).

DNAT configuration Examples with Iptables

Suppose you wish to allow connections to one of your internal machine 192.168.0.3 from internet, so that any of your employees can access 192.168.0.3 from home using the ineternet.

For doing this, we need to dedicatedly map one public ip address on our Linux router to that internal machine 192.168.0.3. Let's say we are mapping our public ip address 4.4.7.23 to 192.168.0.3.

[root@myvm1 ~]# iptables -t nat -A PREROUTING -d 4.4.7.23 -j DNAT --to 192.168.0.3
[root@myvm1 ~]#

After applying the above rule, anybody can access the internal machine by accessing the public ip address 4.4.7.23 on the router. For security if you only want to give access to some public IP addresses from the internet then you can do that by adding -s <list of public ip>.

In the above mentioned rule all the traffic coming to 4.4.7.23 will be send to 192.168.0.3 by doing a DNAT. A better approach is to give access to only the required services on 192.168.0.3 through 4.4.7.23.

For example you can host your web server on your intranet server 192.168.0.3 and let people from the internet access your site, by adding a DNAT rule as shown below.

[root@myvm1 ~]# iptables -t nat -A PREROUTING -d 4.4.7.23 -p tcp --dport 80 -j DNAT --to 192.168.0.3
[root@myvm1 ~]#

After adding the above rule you can let people access your website which is hosted on 192.168.0.3.

You can allow SSH access to your intranet server 192.168.0.3 with the help of DNAT, in exactly the same way as we have allowed access to the web server on 192.168.0.3.

[root@myvm1 ~]# iptables -t nat -A PREROUTING -d 4.4.7.23 -p tcp --dport 8532 -j DNAT --to 192.168.0.3:22
[root@myvm1 ~]#

In the above shown iptable rule, any traffic that comes to the port 8532 (through 4.4.7.23), will be send to ssh on 192.168.0.3. Anybody who requires ssh to 192.168.0.3 should do an ssh to 4.4.7.23:8532

You can also set up a transparent proxy with the help of iptable DNAT. Because people can disable proxy settings from thier browser while accessing internet, however you can enforce the use of proxy by sending all traffic to port 80 on the internet, to your proxy server port.

Lets see how.

 

[root@myvm1 ~]# iptables -t nat -A PREROUTING -s 192.168.0.0/24 -p tcp --dport 80 -j REDIRECT --to-port 1234

In the above shown example, all http traffic that comes from the local intranet with the source address of 192.168.0.0/24 will be redirected to our assumed proxy server port 1234.

In this way you can force your local intranet users to use proxy server while browsing web pages.

All the above shown example's are for learning purposes, you can modify them to suite your need and environment. Hope this article was helpful in understanding the concepts related to NAT.

Rate this article: 
Average: 4 (702 votes)

Comments

Hi,
Just wanted to thank you for this simple but straightforward guide. It helped me alot!!

slashmaster's picture

Hi D1,

Thanks for the comment and welcome to slashroot.in

regards

Thanks, there is no such a well explained NAT concepts in other's blog

Very nice tutorial buddy, cleared some things in my head

This is the excellent explanation !!!

Thank You,

Very well explained, simple but learnt a lot about nat and pre/post routing. One again BIG Thank's!

What happens when you have multiple private networks that need NAT?

I added the rule as follows

iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -j SNAT --to 1.2.3.138

but as soon as I do that, even though machines can reach the Internet, they can't reach each other.

Sarath Pillai's picture

Hi Jose,

Try doing a MASQUERADE instead of SNAT, and see if that works. Let me know. Basically MASQUERADE should work for environment. Otherwise your rule makes all traffic from 192.168.0.0/16 to be sourced to 1.2.3.138. MASQUERADE should make you reach internet as well as private subnets..

Let me know..If still not working, elaborate your environment in detail, so that we can dig this down.

Cheers.
Sarath

2

[root@myvm1 ~]# iptables -t nat -A PREROUTING -d 4.4.7.23 -p tcp --dport 8532 -j DNAT --to 192.168.0.3:22

For the up command, i need to open the 8532 port on the local server, or else I cann't telnet this 8532 port from a remote server. How to make the 8532 port available? Thank you!

nice woek sir

Good explanation.Simple.Clear.Concise. Thank you.

Such a beautiful article in a sweet language..So nice

Hello Sir,

Thanks for this tutorial it helped me lot.

Thanks

It is very nice to see such good and clear explanation on topics like this, that may be really confusing without such clear articles. I hope to see more of this on other aspects of routing and iptables in Linux.

Thank you.

Hi Sarath,

Thanks for sharing this good document.

I have configured both DNAT and SNAT. In my case SNAT is working, means i can see source address of the packets are changing.But DNAT is not working means,source address is not changing.

PC(192.168.2.5)-----------(eth0,192.168.2.4)NAT Server(eth1,10.10.10.4)---------PC(10.10.10.5)

SNAT

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j SNAT --to 10.10.10.4

DNAT

iptables -t nat -A PREROUTING -d 10.10.10.5 -j DNAT --to 192.168.0.3

Could you please help me on this.

Regards
Chandu

iptables -t nat -A PREROUTING -d 10.10.10.4 -j DNAT --to 192.168.0.3

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.