Stateless NAT, occasionally maligned as dumb NAT [31], is the simplest form of NAT. It involves rewriting addresses passing through a routing device: inbound packets will undergo destination address rewriting and outbound packets will undergo source address rewriting. The iproute2 suite of tools provides the two commands required to configure the kernel to perform stateless NAT. This section will cover only stateless NAT, which can only be accomplished under linux with the iproute2 tools, although it can be simulated with netfilter.
Creating an iproute2 NAT mapping has the side
effect of causing the kernel to answer ARP requests for the NAT IP.
For more detail on ARP filtering, suppression and conditional ARP, see
Chapter 2, Ethernet. This can be considered, alternatively, a
benefit or a misfeature of the kernel support for NAT.
The nat
entry in the local routing table causes
the kernel to reply for ARP requests to the NAT IP.
Conversely,
netfilter DNAT makes no ARP entry or
provision for neighbor advertisement.
Whether or not it is using a packet filter, a linux machine can perform NAT using the iproute2 suite of tools. This chapter will document the use of iproute2 tools for NAT with a simple example and an explanation of the required commands, then an example of using NAT with the RPDB and using NAT with a packet filter.
NAT with iproute2 can be used in conjunction with the routing policy database (cf. RPDB) to support conditional NAT, e.g. only perform NAT if the source IP falls within a certain range. See Section 3.3, “Conditional Stateless NAT”.
Assume that example company in example network wants to provide SMTP service on a public IP (205.254.211.0/24) but plans to move to a different IP addressing space in the near future. Network address translation can assist example company prepare for the move. The administrator will select an IP on the internal network (192.168.100.0/24) and configure the router to accept and translate packets for the publicly reachable IP into the private IP.
Example 5.1. Stateless NAT Packet Capture [32]
[root@masq-gw]#
tcpdump -qnn
19:30:17.824853 eth1 < 64.70.12.210.35131 > 205.254.211.17.25: tcp 0 (DF) 19:30:17.824976 eth0 > 64.70.12.210.35131 > 192.168.100.17.25: tcp 0 (DF) 19:30:17.825400 eth0 < 192.168.100.17.25 > 64.70.12.210.35131: tcp 0 (DF) 19:30:17.825568 eth1 > 205.254.211.17.25 > 64.70.12.210.35131: tcp 0 (DF)
The first packet comes in on eth1, masq-gw 's
outside interface. The packet is addressed to the NAT IP,
205.254.211.17 on tcp/25. This is the IP/port pair on which
which our service runs. This is a snapshot
of the packet before it has been handled by the NAT code.
| |
The next line is the "same" packet leaving eth0, masq-gw 's
inside interface, bound for the internal network.
The NAT code has substituted the real IP of the server,
192.168.100.17. This rewriting is handled by the
nat entry in the
local routing table (ip
route ). See also
Example 5.2, “Basic commands to create a stateless NAT”.
| |
The SMTP server then sends a return packet which arrives on
eth0. This is the packet before the NAT code on masq-gw
has rewritten the outbound packet. This rewriting is handled
by the RPDB entry (ip rule ). See also
Example 5.2, “Basic commands to create a stateless NAT”.
| |
Finally, the return packet is transmitted on eth1 after having been rewritten. The source IP address on the packet is now the public IP on which the service is published. |
There are only a few commands which are required to enable stateless
NAT on a linux routing device. The commands below will configure
the host masq-gw
(see
Section 1, “Example Network Map and General Notes” and
Section 2, “Example Network Addressing Charts”) as shown above in
Example 5.1, “
Stateless NAT Packet Capture
”.
Example 5.2. Basic commands to create a stateless NAT
[root@masq-gw]#
ip route add nat 205.254.211.17 via 192.168.100.17
[root@masq-gw]#
ip rule add nat 205.254.211.17 from 192.168.100.17
[root@masq-gw]#
ip route flush cache
[root@masq-gw]#
ip route show table all | grep ^nat
nat 205.254.211.17 via 192.168.100.17 table local scope host
[root@masq-gw]#
ip rule show
0: from all lookup local 32765: from 192.168.100.17 lookup main map-to 205.254.211.17 32766: from all lookup main 32767: from all lookup 253
This command tells the kernel to perform network address translation on any packet bound for 205.254.211.17. The parameter via tells the NAT code to rewrite the packet bound for 205.254.211.17 with the new destination address 192.168.100.17. Note, that this only handles inbound packets; that is, packets whose destination address contains 205.254.211.17. | |
This command enters the corresponding rule for the outbound traffic into the RPDB (kernel 2.2 and up). This rule will cause the kernel rewrite any packet from 192.168.100.17 with the specified source address (205.254.211.17). Any packet originating from 192.168.100.17 which passes through this router will trigger this rule. In short, this command rewrites the source address of outbound packets so that they appear to originate from the NAT IP. | |
The kernel maintains a routing cache to handle routing
decisions more quickly
(Section 7, “Routing Cache”). After making changes
to the routing tables on a system, it is good practice to
empty the routing cache with ip route flush
cache . Once the cache is empty, the
kernel is guaranteed to consult the routing tables again
instead of the routing cache.
| |
These two commands allow the user to inspect the
routing policy database and the local
routing table to determine if the NAT routes and rules were
added correctly.
|
NAT introduces a complexity to the network in which it is used because a service is reachable on a public and a private IP. Usually, this is a reasonable tradeoff or else stateless NAT would fail in the selection process. In the case that the linux routing device is connected to a public network and more than one private network, there is more work to do.
Though the service is available to the public network on a public (NAT) IP, internal users may need to connect to the private or internal IP.
This is accomplished by use of the routing policy database (RPDB), which allows conditional routing based on packet characteristics. For a more complete explanation of the RPDB, see Section 9, “Routing Policy Database (RPDB)”. The routing policy database can be manipulated with the ip rule command. In order to successfully configure NAT, familiarity with the ip rule command is required.
Example 5.3. Conditional Stateless NAT (not performing NAT for a specified destination network)
[root@masq-gw]#
ip rule add to 192.168.99.0/24 from 192.168.100.17
[root@masq-gw]#
ip route flush cache
[root@masq-gw]#
ip rule show
0: from all lookup local 32764: from 192.168.100.17 to 192.168.99.0/24 lookup main 32765: from 192.168.100.17 lookup main map-to 205.254.211.17 32766: from all lookup main 32767: from all lookup 253
Note that we now have an entry of higher priority in the RPDB
for any packets returning from 192.168.100.17 bound for
192.168.99.0/24. The rule tells the kernel to find the route
for 192.168.99.0/24 (from 192.168.100.17) in the main
routing table. This exception to the NAT mapping of our public
IP to our internal server will allow the hosts in our second
internal network to reach the host named isolde
on
its private IP address.
If tristan
were to initiate a connection to isolde
now, the
packet would return from IP 192.168.100.17 instead of being
rewritten from 205.254.211.17.
Now we have had success creating a NAT mapping with the iproute2 tools and we have successfully made an exception for another internal network which is connected to our linux router. Now, supposing we learn that we will be losing our IP space next week, we are prepared to change our NAT rules without readdressing our server network.
Naturally, you may not wish to create these rules manually every time you want to use NAT on every device. A standard SysV initialization script and configuration file can ease the burden of managing a number of NAT IPs on your system.