Setup Portforwarding with ip tables

January 9, 2018 in hypervisor, linux ‐ 4 min read

This article describles how to setup a portforwarding using iptables.

In this case we want to make the webserver on a virtual machine accessable from the internet. Since you normally have only one or a few public ip addresses we are using a techinque called Network Adress Translation.

We define how a client will have to talk to us in order for his packets get forwarded. The tool used for this task in linux is iptables.

Iptables is checking recieved IP packets and decides, based on complex rules, what should happen to them.

Before we can start working on this we have to allow the kernel to forward IP packets. To do this we open the file  /etc/sysctl.conf and change the following value from 0 to 1:

net.ipv4.ip_forward = 1

Afterwards we restart the service so the changes take place.

sudo service networking restart

 

2) Setup NAT

As of the TCP/OP standard every computer has 65535 ports we can address. The first 1024 are IANA maintained by the IANA and should not be used for NAT.

The standard ports for webservers are 80 (http) und 443 (https).

We decide on what port a requesting client should contact for his packets to be forwarded to the virtual webserver. In this example we use 2080 for http and 20443 for https.

Now we know the following facts about an incomming IP packet:

  • The target IP address is the public IP of our server: 73.97.113
  • The target port is the one defined by us: 20443
  • It will be of a specific protocol: tcp

Also we know that the packet needs to be forwarded to:

  • The IP address of the webserver: 168.122.178
  • the port of the webserver: 443

image

In iptables the set of rules a packet will be handled by is called “table”. The table used by us is called “nat” and is made up of three parts:

  • PREROUTING: Handels inbound packets
  • OUTPUT: Handels packets created by the host
  • POSTROUTING: Handels outgoing packets

We now wirte a rule for the table „nat“ that handels a packet if it:

  • Is inbound: PREROUTING
  • Has the Protocol: TCP
  • The destination adress is our public ip: 213.73.97.133
  • The destination port is: 20443

If these creterias match iptables should:

  • Jump (-j) to the DNAT table
  • Change the target IP adress to: 168.122.178
  • Change the target Port to 80

In the syntax of iptables the command is looking like this:

sudo iptables -t nat -I PREROUTING -p tcp -d 213.73.97.133 --dport 20443 -j DNAT --to-destination 192.168.122.178:443

Since the source IP address remains intact we do not have to change anything on the route back.

The same rule for port 2080 to port 80:

sudo iptables -t nat -I PREROUTING -p tcp -d 213.73.97.133 --dport 2080 -j DNAT --to-destination 192.168.122.178:80

Lets take another look at the rule.

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

image

 

3) Firewall configuration

First: Firewallrules get processed one after another. Second: If a rule triggers the traffic will be ALLOWED or DENIED

Depending on the firewall there are different philosophies on how Firewall rules work:

  • What happens, if a rule is triggered that allows traffic? –> At iptables: Allow the traffic only if there are no other DENY rules afterwards.
  • What happens, if no rule is triggered? –> At iptables: DENY the traffic

In iptables firewallrues are handeled in chains. Depending on what kind of traffic we are looking at different chains apply.

Since we are natting (forwarding) traffic, the Chain is called FORWARD.

As already mentioned iptables will drop all packets that are not handeled by a rule. A easy way to think of it is to immagine an invisible “deny any:any” rule beneath all other rules.

This means we have to configure a firewall rule that expicitly allows packets recieved on the inbound interface (in this case enp2s0) to be forwarded to the network 192.168.122.0/24.

To ensure that the traffic will not be blocked by a following rule we jump to the chain ACCEPT using the paramenter -j if the rule is triggered.

sudo iptables -i enp2s0 -I FORWARD -m state -d 192.168.122.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT

Lets take a look final look at it.

sudo iptables -L FORWARD -v --line-numbers

image

Cheers, Ori

Thanks a lot to Fl@ und beegeees, who helped me alot wrapping my mind around this.