Port Forwarding featured image

Forwarding Ports with Iptables in Linux: A How-To Guide

Port forwarding also referred to as port mapping, is a method for allowing remote devices to connect to a specific service within your private local-area network (LAN). As the name suggests, the process involves forwarding requests for a specific port to another port or network. It modifies the destination of the packet in-flight and is considered a type of network address translation (NAT) operation.

Enabling port forwarding allows those devices or hosts not connected with the internal network to access each other, which is otherwise restricted when disabled. You can leverage the benefits of port forwarding to block target websites, upgrade security, and add a detour around the NAT firewall at your convenience.

In this tutorial, we will walk you through the steps of forwarding ports with iptables in Linux.

Prerequisites

To follow along with this tutorial, you will need:

Host Details

First, we need to know the details of the interfaces and addresses of the working servers. Let’s check the network interfaces of our system:

You’ll see the output:

Here, the highlighted output shows two interfaces, the first one eth0 assigned to the address 192.51.100.45, and the second eth1 assigned to the address 192.168.1.5. Out of these two interfaces, one is public and the other is private. We will run a command to distinguish between the two, and figure out the public interface, the one connected to your default gateway. To distinguish, type:

You’ll see the output:

Dummy Data for the Tutorial

We will use dummy addresses and interface assignments throughout this tutorial. You are free to use these data or replace them, at your convenience.

Web server network details:

  • Public IP Address: 203.0.113.2

  • Private IP Address: 192.0.2.2

  • Public Interface: eth0

  • Private Interface: eth1

Firewall network details:

  • Public IP Address: 203.0.113.15

  • Private IP Address: 192.0.2.15

  • Public Interface: eth0

  • Private Interface: eth1

Web Server Set-Up

Let’s make a start with our web server host. First, log in with your sudo user.

Install Nginx

First, we will install Nginx on our web server host and lock it down so that it only listens to its private interface. It will enable our web server to only be available if we have set up port forwarding in a correct manner.

Next, update the local package cache and use apt to download and install Nginx:

Add Restrictrictions

Once we’ve installed Nginx on our web server host, we’ll lock it to ensure it accepts inputs from private interfaces and nowhere else. Also, it will ensure that our web servers will be active only if the port forwarding setup is correct.

To add restrictions, open up the default server block configuration file /etc/nginx/sites-enabled/default on any text editor of your choice (here we’re using nano text editor), and type:

In the output, you’ll see the listen directive appearing twice:

Port Forwarding Nginx Default File

In this tutorial, we’re using the first directive to demonstrate IPv4 forwarding. The second one, which is configured for IPv6, can be removed. Add your web server’s private IP address with a colon just ahead of the 80 to inform Nginx to take inputs only from the private interface. Next, edit the directive:

Port Forwarding Nginx Edited Default File

Once done, save and close the file. Before heading forward, make sure there are no syntax errors. Let’s test the file:

Nginx T

If you see no error displayed, you’re good to restart Nginx and enable the new configuration:

Verification of the Network Restriction

Let’s verify the level of access we have to our web server. Try to access the webserver using the private interface using the curl command:

You’ll see the output:

Port Forwarding Nginx Output1

If we attempt to use the public interface, we will not be able to connect:

This is exactly what we expected.

Configure the Firewall to Forward Port 80

Let’s progress our work with implementing port forwarding on our firewall machine.

Enable Forwarding in the Kernel

By default, most systems have port forwarding turned OFF. We’ll make changes to turn ON port forwarding by making a few edits. Also, there is an option to turn ON port forwarding permanently using the sudo privileges as shown in the upcoming steps.

To turn ON traffic forwarding at the kernel level, type:

To turn ON port forwarding permanently, edit the /etc/sysctl.conf file. Open the file with sudo privileges, and type:

Inside, find and uncomment the line that looks like this:

Once done, save and close the file. Then, use the sysctl commands to apply changes in the settings to make it more effective:

Basic Firewall Setup

First, go over the guide on how to set up a basic firewall on your machine. Upon completion, you will have:

  • Installed iptables-persistent
  • Saved the default rule set into /etc/iptables/rules.v4
  • Comprehensive knowledge of adding and modifying rules using the iptables command

Also, you can check out how to list and delete iptables Firewall rules.

Adding the Forwarding Rules

We’ll configure our firewall to ensure that traffic flowing into our public interface ( eth0 ) on port 80 gets forwarded to our private interface ( eth1). By default, our basic firewall has a FORWARD chain set to DROP traffic. Adding firewall rules will allow forward connections to our web server. For adding security, we will lock the firewall rules to permit forward requests.

In the FORWARD chain, we will accept new connections destined for port 80 coming from our public interface and heading to our private interface. We’ll identify the new connections with the help of the conntrack extension and represent them by a TCP SYN packet:

You need to allow any subsequent traffic in both directions resulting from the incoming connection. Type the commands below to allow ESTABLISHED and RELATED traffic between our public and private interfaces:

Let’s verify if our policy on the FORWARD chain is set to DROP:

Until now, we’ve added a few rules that allow traffic between our public and private interfaces to proceed through our firewall. However, iptables is not yet informed to direct the traffic because firewall rules configuration is yet to be done. In the next steps, we will add the NAT rules and adjust the permanent rule set to direct traffic.

Adding the NAT Rules to Direct Packets

We’ll perform two separate operations in order for iptables to correctly alter the packets, and streamline communication with the clients and the webserver.

DNAT is the first operation that commences the PREROUTING chain of the nat table. The operation alters the packet’s destination address and enables it to be correctly routed as it passes between networks. However, the clients on the public network will be connecting to our firewall server and will have no information about our private network topology. To pass information with the private network, change the destination address of each packet to allow it to correctly reach our destination web server.

It is crucial to note that we’re focusing on configuring port forwarding. Performing NAT on every packing hitting the firewall is not a part of our tutorial. We will match packets at port 80 to our web server’s private IP address:

The packet will get routed correctly to our web server containing the client’s original address as the source address. Despite attempts made by the server to send the reply directly to that address, there will be no possibility to establish a legitimate TCP connection.

To configure proper routing, we’ll modify the packet’s source address. Let’s edit the source address to our firewall server’s private IP address. After modification, the reply will be sent back to the firewall, which will forward back to the client.

To enable this functionality, add a rule to the POSTROUTING chain of the nat table evaluated right before packets are sent out on the network. Then, match the packets destined for our web server by IP address and port:

Once this rule is in place, our web server should be accessible by pointing our web browser at our firewall machine’s public address:

You’ll see the output:

Nginx Output2

Our port forwarding setup is complete.

Adjust the Permanent Rule Set

After completing the port forwarding setup, we’ll save this to our permanent rule set. If you want to keep the comments in the current rule set, use the iptables-persistent service to save your rules:

You can also open it up and edit manually to keep the comments in your file:

Next, configure the filter table and the nat table to add the FORWARD chain rules and ROUTING rules respectively. Adjusting the nat table will allow us to add PREROUTING and POSTROUTING rules as shown in the example below:

After adding the above values, save and close the file. Next, type the below command to test the syntax of your rules:

If you see no errors, load the rule set:

Let’s verify that our web server is still accessible through your firewall’s public IP address:

Conclusion

By the end of this tutorial, you must be comfortable with forwarding ports on a Linux server with iptables. You can leverage port forwarding capabilities to disguise your private network’s topology whilst streamlining service traffic to flow freely through your gateway firewall machine.

As the process relies explicitly on your network safety and the ports used, it is safe. There may be a possibility of risk involved if you don’t have a security firewall or VPN security on your network. Therefore, it is advisable to configure the firewall as discussed in this tutorial. We hope this guide helps you stay safe on the internet when using your private network.

To further explore more firewall solutions you can implement on your system, check these resources from our blog:

Happy Computing!