iptables cheatsheet

Home

1 iptables -t nat

1.1 chains (INPUT, OUTPUT, PREROUTING, POSTROUTING)

Just as the filters table has three pre-defined chains, INPUT, OUTPUT, FORWARD, the nat table has 2 predefined chains:

(PREROUTING and POSTROUTING).

These are checked against any network traffic relevant to those chains and a decision is made based on the outcome of those rules.

Think of these chains from the perspective of traffic to the internal, inside, protected network.

1.2 POSTROUTING

For outgoing packets, outbound. (e.g. after the packets have been passed around the inside network.) VMs on the inside network have their source ip hidden (re-written, or "translated") on the way to connect to an external IP server.

1.3 PREROUTING

For incoming packets. inbound. (e.g. before packets are delivered to the protected, inside, hidden, privatly addressed VMs) For outside clients to be able to connect to a VM server, but presenting a public IP address to the client, and translating that public ip address to the VM's actual inside private ip address.

1.4 Targets (a.k.a actions)

The predefined targets for -t nat tables are:

  1. Terminating targets
    1. -j MASQUERADE
    2. -j SNAT
    3. -j DNAT
    4. -j REDIRECT
    5. -j RETURN

    In the following table, assume that 192.168.99.0 network is the inside private network, 17.27.1.11 and .12 are two public outside addresses of the host.

    -t chain interface match -j translation
    nat PREROUTING -i ens33 -d 17.27.1.11 DNAT –to-destination 192.168.99.11
    nat PREROUTING -i ens33 -d 17.27.1.12 DNAT –to-destination 192.168.99.12
    nat POSTROUTING -o ens33 -s 192.168.99.11 SNAT –to 17.27.1.11:21
          -p tcp –dport 21    
    nat POSTROUTING -o ens33 -s 192.168.99.12 SNAT –to 17.27.1.12:51889
          -p tcp –dport 21    

    iptables-nat-diagram.png

    Figure 1: Whiteboard diagram showing -t nat table construct

    For the ethernet to have multiple outside public ip addresses you can add them: ip addr add 17.27.1.12 dev ens33 ip addr add 17.27.1.13 dev ens33

    Then list the main and all secondary ip addresses on ens33 with: ip addr list dev ens33

    The last line in the table above would result in packets leaving ens33 that were sourced from 192.168.99.12 and were destined to some ftp server, to have the source address changed to 192.168.168.168, and the destintation port changed to 51889. (Presumably for a specific server on the outside that was listening on port 51889 as an ftp server. - this is just an example)

1.5 PREROUTING and -j DNAT

Destination NAT only works with the PREROUTING chain. i.e. for allowing outside clients to connect to a service that is offered on an inside VM. So for inbound packets.

We are changing the destination address of inbound packets for all the next examples: iptables -t nat -A PREROUTING -j DNAT --to {addr[-addr][:port[-port]]}

Example to translate and pass ALL inbound traffic to 192.168.111.11 seen on interface eth0 iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 192.168.111.11

Change inbound web traffic seen on eth0 to destination addresses 5.6.7.8, and port 8080. iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j DNAT --to 5.6.7.8:8080

Change destination address of traffic heading to 10.10.10.10 on our host, to an inside host, whose address is 192.168.111.11 iptables -t nat -A PREROUTING -d 10.10.10.10/32 -j DNAT --to 192.168.111.11

More encompassing example would be to specify any inbound traffic seen on interface eth0 and translate the address to send it to host: ..111.11 iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 192.168.111.11

–to-destination <ipaddr>[-<ipaddr>][:port-port]

You can specifiy a single address or a range of addresses You can specify a single port or a range of ports You would do that if you want to balance between several public addresses

1.6 DNAT ONLY works with static ip addresses (NOT DHCP)

For dynamic (dhcp) clients on the inside, use -j MASQUERADING

1.7 -j REDIRECT –to-port 3128

A specialized case of DNAT, if you want to redirect packets to a different incoming port. i.e. PREROUTING only. For example: send incoming port-80 web traffic to our squid (transparent) proxy iptables -t nat -A PREROUTING -i eth0 -p tcp –dport 80 -j REDIRECT –to-port 3128

(for PREROUTING (and OUTPUT chain if locally generated traffic))

1.8 POSTROUTING and -j SNAT

Source NAT only works the POSTROUTING chain. (i.e. outbound )

  • (and INPUT chain for locally destined packets)_

Similar to Masquerading , but SNAT is for static addresses. Please note: the "–to address" is NOT the address that you are trying to get to, i.e. NOT the destination address, but rather it is the address to which to translate the source address.

e.g. "please translate my source address 192.168.111.11 to 1.2.3.4"

Obviously 1.2.3.4 has to be an address on the outside that can be reachable from the outside, so the reply packets know how to get back.

iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4 iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4-1.2.3.6 iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4:1-1023

We are changing the source address of packets destined to the outside. So that the outside thinks packets are coming from the natted source, specified by the –to address, not the original inside host address.

You can specifiy a single address or a range of addresses You can specify a single port or a range of ports

SNAT ONLY works with static ip addresses (NOT DHCP) That is why it has –to-source This a requirement. For SNAT one has to specify the new source-IP explicitly.

Change source addresses to 1.2.3.4. iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4

SNAT means "source nat" and not "static nat", although it is for static addresses.

For example, if we have changed incoming traffic to a different DNAT recipient We have to fix the reverse direction by altering reply packets to look like they came from the original destination address. For example we can change destination address of traffic heading to 10.10.10.10, an address on our host, to an inside host, whose address is 192.168.111.11

iptables -t nat -A PREROUTING -d 10.10.10.10/32 -j DNAT --to 192.168.111.11

fix the reverse direction: iptables -t nat -A POSTROUTING -s 192.168.111.11 -j SNAT --to 10.10.10.10

1.9 -j MASQUERADE (for POSTROUTING (and INPUT for locally destinec packets)

Like SNAT, it ONLY works with the POSTROUTING chain, i.e. for VMs or clients to connect to an external IP address, and have the VM's source ip address hidden/re-written/translated as the specified externally routable address.

iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE

This masks the private ip address of an inside node with the external ip address of the firewall/gateway. It works with clients that use DHCP. Some times the address may change if the client gets has a new dhcp lease, the client (inside addr changes). by using -j MASQUERADE the NAT process checks every time.

MASQUERADE also automatically keeps track of the inside clients that have connected outbound so that outbound reply packets can be DNAT'ed back to the originating inside client. - no need to configure PREROUTING chain rules for these inbout reply packets.

Because MASQUERADING keeps track of all these translated connections, it costs more in performance compared to the static that use -j SNAT.

1.10 difference between SNAT and MASQUERADE

The SNAT target requires you to give it an IP address to apply to all the outgoing packets. The MASQUERADE target lets you give it an interface, and whatever address is on that interface is the address that is applied to all the outgoing packets.

In addition, with SNAT, the kernel's connection tracking keeps track of all the connections when the interface is taken down and brought back up; the same is not true for the MASQUERADE target.

1.11 options for POSTROUTING chains:

–to-destination address[:port] -j SNAT –to-destination address-address[:port-port] -j SNAT –to-port

1.12 options for PREROUTING chains:

–to-destination address[:port] -j DNAT –to-destination address-address[:port-port] -j DNAT

2 Commands specific to nat tables

iptables –delete-chain iptables –table nat –flush # to flush just the nat rules iptables –table nat –delete-chain

  • delete all chains that are not in default filter and nat chains.

iptables -t nat -F

setup ip forwarding and masquerading iptables -t nat -A POSTROUTING –out-interface eth0 -j MASQUERADE iptables –append FORWARD –in-interface eth1 -J ACCEPT

3 kernel setup

echo 1 > /proc/sys/net/ipv4/ip-forward # check this it might be obsolete

4 c8host settings pre-lab3

sudo iptables -t nat -S POSTROUTING


-P POSTROUTING ACCEPT
-A POSTROUTING -s 192.168.111.0/24 -d 224.0.0.0/24 -o ens33 -j RETURN
-A POSTROUTING -s 192.168.111.0/24 -d 255.255.255.255/32 -o ens33 -j RETURN
-A POSTROUTING -s 192.168.111.0/24 ! -d 192.168.111.0/24 -o ens33 -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.111.0/24 ! -d 192.168.111.0/24 -o ens33 -p udp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.111.0/24 ! -d 192.168.111.0/24 -o ens33 -j MASQUERADE
-A POSTROUTING -s 192.168.111.0/24 -d 224.0.0.0/24 -o ens33 -j RETURN
-A POSTROUTING -s 192.168.111.0/24 -d 255.255.255.255/32 -o ens33 -j RETURN
-A POSTROUTING -s 192.168.111.0/24 ! -d 192.168.111.0/24 -o ens33 -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.111.0/24 ! -d 192.168.111.0/24 -o ens33 -p udp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.111.0/24 ! -d 192.168.111.0/24 -o ens33 -j MASQUERADE
 $

sudo iptables -t nat -L POSTROUTING –line-numbers


  Chain POSTROUTING (policy ACCEPT)
  num  target     prot opt source               destination         
  1    RETURN      all  --  192.168.111.0/24     base-address.mcast.net/24 
  2    RETURN      all  --  192.168.111.0/24     255.255.255.255     
  3    MASQUERADE  tcp  --  192.168.111.0/24    !192.168.111.0/24     masq ports: 1024-65535
  4    MASQUERADE  udp  --  192.168.111.0/24    !192.168.111.0/24     masq ports: 1024-65535
  5    MASQUERADE  all  --  192.168.111.0/24    !192.168.111.0/24    
  6    RETURN      all  --  192.168.111.0/24     base-address.mcast.net/24 
  
  7    RETURN      all  --  192.168.111.0/24     255.255.255.255     
  8    MASQUERADE  tcp  --  192.168.111.0/24    !192.168.111.0/24     masq ports: 1024-65535
  9    MASQUERADE  udp  --  192.168.111.0/24    !192.168.111.0/24     masq ports: 1024-65535
  10   MASQUERADE  all  --  192.168.111.0/24    !192.168.111.0/24    
$

5 troubleshooting iptables -t nat

You can display the nat tables, much like the filter (default) tables with:

sudo iptables -t nat -L
sudo iptables -t nat -L -v
sudo iptables -t nat -L --line-numbers
sudo iptables -t nat -L POSTROUTING --line-numbers
sudo iptables -t nat -L PREROUTING --line-numbers

You can also display the chains using -S option, which gives you the output
as it would be saved in an =iptables-save > ~/table-backup=  command.

sudo iptables -t nat -S POSTROUTING

6 Good explanation of why MASQUERADE needed in POSTROUTING chain

From unix stack exchange

Your question breaks down into two parts.

Why do we need the MASQUERADE rule. Why does it need to be in the POSTROUING chain. Is there any altenative? To answer the first question we must first understand how iptables NAT works. The NAT tables are used on the first packet of a connection to determine what translations should be applied to that connection. Once the first packet is processed an internal mapping table entry is created which is used to process later packets of the connection but a box can only process packets that it sees.

So lets assume that XXX.XXX.XXX.XXX and YYY.YYY.YYY.YYY are both servers on the Internet with no special routing configured. Lets assume that the client is also on the open internet with no firewalls and has an IP of ZZZ.ZZZ.ZZZ.ZZZ . Lets look at what happens without the MASQURADE rule.

The client sends an initial packet ZZZ.ZZZ.ZZZ.ZZZ:1234 -> XXX.XXX.XXX.XXX:80

The packet arrives at server A which performs destination NAT, so the packet is now ZZZ.ZZZ.ZZZ.ZZZ:1234 -> YYY.YYY.YYY.YYY:80 it creates the connection tracking entry and puts the packet back out on the network. The ISP may block the packet at this point for "spoofing" or they may deliver it to sever B. Lets assume that they do deliver it to server B. The packet arrives at server B which crafts a response

YYY.YYY.YYY.YYY:80 -> ZZZ.ZZZ.ZZZ.ZZZ:1234

The response is delivered to the client. The client looks up the response in it's table of sockets but it fails to find a match and discards the packet (possibly sending an ICMP error in response). How does this change if we add the MASQUERADE rule?

The client sends an initial packet ZZZ.ZZZ.ZZZ.ZZZ:1234 -> XXX.XXX.XXX.XXX:80 The packet arrives at server A which performs destination NAT and MASQURADING, so the packet is now XXX.XXX.XXX.XXX:5678 -> YYY.YYY.YYY.YYY:80 it puts it back out on the network. The ISP delivers the packet to server B The packet arrives at server B which crafts a response

YYY.YYY.YYY.YYY:80 -> XXX.XXX.XXX.XXX:5678

The response is delivered to server A Server A looks the packet up in it's connection tracking tables and changes it's source and destination to XXX.XXX.XXX.XXX:80 -> ZZZ.ZZZ.ZZZ.ZZZ:1234 The network delivers the response to the client. The client looks up the response in it's table of sockets and finds a match. The connection is succesfully established. For question 2 I don't really have an answer, iptables insists that SNAT/MASQUERADE can only be done in POSTROUTING but I don't see any good technical justification for why this should be the case.

We might reasonablly want to avoid using MASQUERADE. It has serveral problems, firstly we lose the information on the original source of the traffic which we would like to have for abuse control. Secondly server A has a limited supply of ports.

This can be solved but only if both servers are under our control. The soloution involves three steps.

We establish a tunnel of some sort between servers A and B. The tunnel endpoints are assigned private IP addresses. On server A we DNAT the traffic to the tunnel IP of server B. On server B we use policy routing so that traffic coming from server B's private IP is sent down the tunnel to server A rather than being sent back out on to the internet.

6.1 Home