Configure Linux as a Router (IP Forwarding)
Author: Matt-Wildman
Other contributors: Nathaniel Stickman
View edit history on GitHub → Originally authored by Matt-WildmanTraducciones al EspañolEstamos traduciendo nuestros guías y tutoriales al Español. Es posible que usted esté viendo una traducción generada automáticamente. Estamos trabajando con traductores profesionales para verificar las traducciones de nuestro sitio web. Este proyecto es un trabajo en curso.
A computer network is a collection of computer systems that can communicate with each other. In order to communicate with a computer that’s on a different network, a system needs a way to connect to that other network. A router is a system that acts as an intermediary between multiple different networks. It receives traffic from one network that is ultimately destined for another. It identifies where a particular packet should be delivered, then forwards that packet over the appropriate network interface.
There are lots of options for off-the-shelf router solutions for both home and enterprise use. These solutions are often preferred for numerous reasons. They are relatively easy to configure, have lots of features, tend to have a user-friendly management interface, and may even come with support options. Under the hood, these routers are stripped-down computers running common operating systems, such as Linux.
Instead of using one of these pre-built solutions, you can create your own using any Linux server, such as an Akamai Cloud Compute Instance. Routing software like iptables provides total control over configuring a router and firewall to suit your individual needs. This guide covers how to set up a Linux system as a basic router, including enabling IP forwarding and configuring network routing.
Use Cases for a Cloud-based Router
Many workloads benefit from custom routing or port forwarding solutions, including those workloads hosted on cloud platforms like Akamai. For example, it’s common practice for security-minded applications to connect most of their systems together through a private network, like a VLAN. These systems might need access to an outside network, such as other VLANs or the public internet. Instead of giving each system their own interface to the other network, one system on the private network can act as a router. The router is configured with multiple network interfaces: one to the private VLAN and another to the other network. It then forwards packets from one interface to another. This can make monitoring, controlling, and securing traffic much easier, as it can all be done from a single system. Akamai Cloud Compute Instances can be configured with up to three interfaces, each connecting to either the public internet or a private VLAN:
- Connect systems on private VLAN to the public internet.
- Connect systems on two separate private VLANs.
- Forward IPv6 addresses from a
/56
routed range.
Configure a Linux System as a Router
Here are the basic steps needed to configure a Linux system as a router:
Deploy at least two Compute Instances (or other virtual machines) to the same data center. Connect all systems to the same private network, like a VLAN. Designate one system as the router and connect it to the public internet or a different private network.
Enable IP Forwarding on the Compute Instance designated as the router.
Configure the Routing Software on that router instance. This guide covers using nftables, iptables, or Firewalld.
Define the Gateway on each system other than the router. This gateway should point to the router’s IP address on that network.
Continue reading for detailed instructions on each of these steps.
Deploy Compute Instances
To get started, use the Akamai Cloud Compute platform to deploy multiple Compute Instances. These can mimic a basic application that is operating on a private VLAN with a single router. Skip this section if you already have an application deployed and just wish to know how to configure IP forwarding or the router software.
Deploy two or more Compute Instances to the same region and designate one as the router. This guide uses Debian 12, but the instructions are generally applicable to other Linux distributions. On the deployment page, skip the VLAN section for now. See Creating a Compute Instance to learn how to deploy Linode Compute Instances.
Edit each Compute Instance’s configuration profile. See Managing Configuration Profiles for information on viewing and editing configuration profiles.
Router Instance: On the Compute Instance designated as the router, leave eth0 as the public internet and set eth1 as a VLAN. Enter a name for the VLAN and assign it an IP address from whichever subnet range you wish to use. For example, if you wish to use the
10.0.2.0/24
subnet range, assign the IP address10.0.2.1/24
. By convention, the router should be assigned the value of1
in the last segment.Other Instance/s: On each Compute Instance other than the router, remove all existing network interfaces. Set eth0 as a VLAN, select the VLAN you just created, and enter another IP address within your desired subnet (e.g.
10.0.2.2/24
,10.0.2.3/24
, and so on).
Confirm that Network Helper is enabled and reboot each Compute Instance for the changes to take effect.
Log in to each instance and test the connectivity on each Compute Instance to ensure proper configuration. To do this, you can use SSH, or Lish if utilizing an Akamai Cloud Compute Instance.
Ping the VLAN IPv4 address of another system within the same VLAN:
Router Instanceping 10.0.2.2
Other Instance/sping 10.0.2.1
Each Compute Instance should be able to ping the IP addresses of all other instances within that VLAN.
Ping an IP address or website of a system on the public internet.
All Instancesping linode.com
This ping should only be successful for the Compute Instance configured as the router.
Enable IP Forwarding
IP forwarding plays a fundamental role on a router. This is the functionality that allows a router to forward traffic from one network interface to another. When configured along with routing software, it allows a computer on one network to reach a computer on a different network. Forwarding for both IPv4 and IPv6 addresses are controlled within the Linux kernel. The following kernel parameters are used to enable or disable IPv4 and IPv6 forwarding, respectively:
- IPv4:
net.ipv4.ip_forward
ornet.ipv4.conf.all.forwarding
- IPv6:
net.ipv6.conf.all.forwarding
Forwarding is disabled on most Linux systems by default. However, this must be enabled to configure Linux as a router. To enable forwarding, the corresponding parameter should be set to 1
. A value of 0
indicates that forwarding is disabled. To update these kernel parameters, edit the /etc/sysctl.conf
file as shown in the steps below:
On the Linux system you intend to use as a router, determine if IPv4 forwarding is currently enabled or disabled. The command below outputs the value of the given parameter. A value of
1
indicates that the setting is enabled, while0
indicates it is disabled.Router Instancesudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
If this parameter returns with a value of
0
, it is disabled, and you must continue with the instructions below.Note If you intend to configure IPv6 forwarding, check that kernel parameter as well:
sudo sysctl net.ipv6.conf.all.forwarding
Open the
/etc/sysctl.conf
file using a command-line text editor withsudo
permissions such as nano:Router Instancesudo nano /etc/sysctl.conf
Find the line corresponding with the type of forwarding you wish to enable, uncomment it, and set the value to
1
. Alternatively, you can add the following lines anywhere in the file.- File: /etc/sysctl.conf
27 28 29 30 31 32 33
# Uncomment the next line to enable packet forwarding for IPv4 net.ipv4.ip_forward=1 # Uncomment the next line to enable packet forwarding for IPv6 # Enabling this option disables Stateless Address Autoconfiguration # based on Router Advertisements for this host net.ipv6.conf.all.forwarding=1
When done, press CTRL+X, followed by Y then Enter to save the file and exit
nano
.Once the changes are saved, run the following command (or reboot the machine) to apply them:
Router Instancesudo sysctl -p
net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1
Configure the Routing Software
Linux network utilities like nftables, iptables, and Firewalld can serve as both a firewall and as a router. This section covers how to configure each of these tools to function as a basic router. You can, alternatively, opt for a commercial routing application.
On the Linux system you intend to use as a router, review the existing network rules. On a fresh Linux installation, there may not be any preconfigured rules. If there are, look for any rules that might interfere with your intended configuration. Consult a system administrator or the network utility documentation linked below to help determine.
Router Instancesudo nft list ruleset
Refer to the nftables documentation for an explanation of any existing rules.
If necessary, flush the existing rules and configure nftables to allow all traffic:
Router Instancesudo nft flush ruleset sudo nft add table inet filter sudo nft add chain inet filter input '{type filter hook input priority 0; policy accept; }' sudo nft add chain inet filter forward '{type filter hook forward priority 0; policy accept; }' sudo nft add chain inet filter output '{type filter hook output priority 0; policy accept; }'
Router Instancesudo iptables -S
Refer to the iptables documentation for clarification on any extant rules.
If necessary, flush your existing rules and configure iptables to allow all traffic:
Router Instancesudo iptables -F sudo iptables -X sudo iptables -t nat -F sudo iptables -t nat -X sudo iptables -t mangle -F sudo iptables -t mangle -X sudo iptables -P INPUT ACCEPT sudo iptables -P OUTPUT ACCEPT sudo iptables -P FORWARD ACCEPT
Router Instancesudo firewall-cmd --list-all-zones
Refer to the Firewall-cmd documentation for more on any existing configuration.
If necessary, return to Firewalld defaults and subsequently allow all traffic:
Router Instancesudo rm -rf /etc/firewalld/zones/ sudo firewall-cmd --zone=public --set-target=ACCEPT --permanent sudo firewall-cmd --complete-reload
success success
Configure the utility to allow port forwarding. This is the default setting for many systems.
Router Instancesudo nft add chain inet filter forward '{type filter hook forward priority 0; policy accept; }'
Router Instancesudo iptables -A FORWARD -j ACCEPT
Router Instancesudo firewall-cmd --zone=public --add-forward
success
Configure NAT (network address translation) within the utility. This modifies the IP address details in network packets, allowing all systems on the private network to share the same public IP address of the router. Replace
10.0.2.0/24
in the following command with the subnet of your private VLAN.nftables does not include a
nat
table by default, so you should create one, along withprerouting
andpostrouting
chains. While the masquerading rule only applies to the postrouting chain, the nftables configuration requires the complementary prerouting chain as well.Router Instancesudo nft add table inet nat sudo nft add chain inet nat prerouting '{ type nat hook prerouting priority -100; }' sudo nft add chain inet nat postrouting '{ type nat hook postrouting priority 100; }'
From there, you can add the
masquerade
rule to apply to connections from the private network.Router Instancesudo nft add rule inet nat postrouting ip saddr 10.0.2.0/24 masquerade
Note Alternatively, you can apply the rule without a specific subnet. In this case, the masquerade applies to any connection passed through the router.
Router Instancesudo nft add rule inet nat postrouting masquerade
Router Instancesudo iptables -t nat -s 10.0.2.0/24 -A POSTROUTING -j MASQUERADE
Note Alternatively, you can forgo specifying a subnet and allow NAT over all traffic using the command below:
Router Instancesudo iptables -t nat -A POSTROUTING -j MASQUERADE
Router Instancesudo firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address=10.0.2.0/24 masquerade'
success
Note Alternatively, to masquerade and allow NAT over all traffic through the router, use the command below:
Router Instancesudo firewall-cmd --zone=public --add-masquerade
Make the configurations persistent.
nftables rules apply immediately, but only hold until the nftables service restarts. To persist an nftables setup across restarts, you need to define that setup in the nftables configuration file, located at
/etc/nftables.conf
. The file needs to begin with two lines, the first executing the nftables command and the second flushing the current ruleset:- File: /etc/nftables.conf
1 2 3
#!/usr/sbin/nft -f flush ruleset
After this, you can paste your ruleset. To get the current ruleset, use the same list command as shown further above:
Router Instancesudo nft list ruleset
Note More conveniently, you can combine these steps into a set of commands to automatically recreate the configuration file from your current nftables rules. The first command recreates the configuration file with the necessary preamble lines, while the second adds your current configuration to the file:
Router Instancesudo sh -c 'echo -e "#!/usr/sbin/nft -f\n\nflush ruleset\n" > /etc/nftables.conf' sudo sh -c 'nft list ruleset >> /etc/nftables.conf'
By default, iptables rules are ephemeral. To make your configuration changes persistent, install the
iptables-persistent
package. When you do this, the rules saved within/etc/iptables/rules.v4
(andrules.v6
for IPv6) are loaded when the system boots up.You can continue making changes to iptables as normal. When you are ready to save, save the output of iptables-save to the
/etc/iptables/rules.v4
(orrules.v6
) file. For more information, see the relevant section in the Controlling Network Traffic with iptables guide.Router Instancesudo mkdir /etc/iptables | sudo iptables-save | sudo tee /etc/iptables/rules.v4
The Firewalld commands above are dynamic, meaning they take effect immediately but are not persistent. You can add the
--permanent
option to each command to make it persistent, however, Firewalld offers a dedicated command to persist its current dynamic configuration:Router Instancesudo firewall-cmd --runtime-to-permanent
success
Note Linux systems using SELinux may need to first set SELinux enforcement to
permissive
in order to convert runtime rules to persistent rules. You can do so with the following command:Router Instancesudo setenforce permissive
When you have made the rules persistent, you can return to the previous SELinux setting with
setenforce 1
.
Define the Gateway
The last step is to manually adjust the network configuration settings for each Compute Instance other than the router.
Log in to the Cloud Manager and disable Network Helper for each non-router Compute Instance you’ve deployed. While Network Helper was useful for automatically configuring the VLAN IP addresses, the configuration files controlled by Network Helper now need to be manually edited.
Log in to each Linux system that is not designated as the router. To do so, you can use SSH from the router, or Lish if using an Akamai Cloud Compute Instance.
Edit the configuration file that contains the settings for the private VLAN interface. The name and location of this file depends on the Linux distribution you are using. See the Manual Network Configuration on a Compute Instance series of guides and select the specific guide for your distribution. For a system running ifupdown on Debian 12, the network configuration is typically stored within
/etc/network/interfaces
:Other Instance/ssudo nano /etc/network/interfaces
Within this file, adjust the parameter that defines the gateway for the VLAN interface. The value should be set to the IP address assigned to the router’s VLAN interface, such as
10.0.2.1
if using the examples in this guide. For a system running ifupdown on Debian 12, add the gateway parameter in the location shown in the example below:- File: /etc/network/interfaces
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
# Generated by Linode Network Helper # Wed Dec 20 16:02:08 2023 UTC # # This file is automatically generated on each boot with your Linode's # current network configuration. If you need to modify this file, please # first disable the 'Auto-configure networking' setting within your Linode's # configuration profile: # - https://cloud.linode.com/linodes/53248278/configurations # # For more information on Network Helper: # - https://www.linode.com/docs/guides/network-helper/ # # A backup of the previous config is at /etc/network/.interfaces.linode-last # A backup of the original config is at /etc/network/.interfaces.linode-orig # # /etc/network/interfaces auto lo iface lo inet loopback source /etc/network/interfaces.d/* auto eth0 iface eth0 inet static address 10.0.2.2/24 gateway 10.0.2.1
When done, press CTRL+X, followed by Y then Enter to save the file and exit
nano
.Once those settings are saved, restart the Compute Instance or run the corresponding command to apply the changes. Continuing to use ifupdown as an example, run the command below to apply the new network configuration settings:
Other Instance/ssudo ifdown eth0 && sudo ip addr flush eth0 && sudo ifup eth0
Note The first part of the command shuts down networking services, causing you to briefly lose connection, which outputs the following error message:
RTNETLINK answers: No such process
This error can be safely ignored.
Test the Connection
To verify the configuration settings are correct, run the same tests from the last step of the Deploy Compute Instances section. Specifically, ping a public IP address or domain from a Compute Instance within the private VLAN that’s not designated as the router:
ping linode.com
This ping should now complete successfully, indicating that the network traffic was successfully forwarded through the router to the public internet.
This page was originally published on