1. Overview

A computer network can be defined as a collection of computer systems capable of interacting with one another. When aiming to communicate with a computer situated on a separate network, a system must establish a means to connect to that distinct network through a gateway.

In this tutorial, we explore the essential steps to configure a Linux machine as a network gateway, essentially becoming the intermediary between our internal network (e.g., home devices) and the broader internet, enabling it to forward IP traffic and perform Network Address Translation (NAT).  First, we briefly discuss the basics of gateway concepts. After that, we walk through configuring IP Forwarding and NAT on the gateway. Next, we show how to configure a client to use our gateway. And lastly, we discuss some troubleshooting tips.

We tested the code in this tutorial on Linux Mint 20.3 (Una) with GNU Bash 5.0.17. It should work in most POSIX-compliant environments unless otherwise specified.

2. Activating IP Forwarding

IP forwarding is a feature that enables a Linux system to forward packets from one network to another. By default, many Linux distributions have IP forwarding disabled to enhance security. However, when transforming our Linux machine into a gateway, activating IP forwarding becomes essential. This can be achieved through simple configuration changes.

2.1. Checking Current IP Forwarding Status

Before enabling IP forwarding, let’s verify its current status:

$ sysctl net.ipv4.ip_forward

If the output is net.ipv4.ip_forward = 0, IP forwarding is disabled. Otherwise it’s enabled.

2.2. Temporarily Activating IP Forwarding

To temporarily activate IP forwarding, we can use the sysctl command to modify kernel parameters at runtime:

$ sudo sysctl -w net.ipv4.ip_forward=1

This change is effective until the next system restart. Typically, we want to make this change permanent.

2.3. Making IP Forwarding Permanent

To make the IP forwarding setting persistent across reboots, we need to modify the sysctl configuration file. Firstly, let’s open the file in a text editor such as Vim or nano:

$ sudo nano /etc/sysctl.conf

Next, we need to add the following line:

net.ipv4.ip_forward = 1

Let’s save and close the file. Next, we need to apply the changes by using the -p option:

$ sudo sysctl -p

The -p flag in the above command instructs sysctl to load the settings from the default configuration file /etc/sysctl.conf.

3. Configuring NAT

Network Address Translation (NAT) is a technique that allows multiple devices on a local network to share a single public IP address. This is especially useful when our Linux gateway connects a private internal network to the internet. NAT helps conserve public IP addresses and adds an extra layer of security through a technique called IP Masquerading.

3.1. What Is IP Masquerading?

IP masquerading is a technique that allows us to use private IP addresses within our local network and have our Linux gateway perform intelligent, real-time translation of local IP addresses and ports to appear as if they are coming from the gateway’s external IP address.

Upon receiving a datagram from a computer on the LAN, the gateway discerns the datagram type—whether it’s TCP, UDP, ICMP, etc.—and dynamically adjusts the datagram to appear as if it originated from the gateway itself, keeping a record of this modification.

Subsequently, the gateway sends the datagram onto the Internet using its external IP address. The destination host, upon receiving the datagram, perceives it as originating from the gateway host and directs any reply datagrams back to that address.

Upon receiving a datagram from its external connection, the Linux gateway checks its table of established masqueraded connections to determine if the datagram corresponds to a computer on the local network. If it does, the gateway reverses the earlier modification performed on the forward path and transmits the datagram to the local computer.

3.2. Configuring iptables for NAT

Assuming our Linux machine has two network interfaces – one for the internal network (eth0) and another for the external network (eth1) – we can use the iptables commands to complete the configuration:

$ sudo iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
$ sudo iptables -A FORWARD -i eth1 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
$ sudo iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT

These rules perform three crucial functions: enabling MASQUERADE for outbound traffic, allowing established connections, and permitting traffic from the internal to the external network.

4. Configuring the Clients

The last step is to configure client systems on our internal network to use the gateway, either as a default gateway to access the internet or a gateway to a different network.

Assuming our client Ethernet interface name is eth0, and our gateway internal IP address is 192.168.0.1, we can use the ip command to temporarily set a default gateway:

# ip route add default via 192.168.0.1 dev eth0

Similarly, if we are using our gateway to reach a remote network rather than the internet, and assuming the remote network address is 10.10.10.0/24, we can use the ip command to set a temporary static route through our gateway:

# ip route add 10.10.10.0/24 via 192.168.0.1

However, we can lose these routes if we restart the system. Therefore, we should make the changes persistent.

5. Testing the Gateway

After activating IP forwarding and configuring the gateway and clients, it’s time to test the connectivity. We can connect devices from the internal network to the Linux machine and verify they can reach the internet.

There are multiple tools and utilities available to Linux users to verify connectivity, including ping, traceroute, netcat, etc.

For example, to ensure we can reach the internet from our client, we can utilize the ping command:

$ ping google.com
PING google.com (142.250.201.46) 56(84) bytes of data.
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=1 ttl=112 time=105 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=2 ttl=112 time=128 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=3 ttl=112 time=153 ms
64 bytes from mrs08s20-in-f14.1e100.net (142.250.201.46): icmp_seq=4 ttl=112 time=176 ms

--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 105.295/140.699/176.149/26.553 ms

Additionally, if we want to confirm our traffic is passing through our gateway, we can use the traceroute command:

$ traceroute google.com
traceroute to google.com (142.250.201.46), 30 hops max, 60 byte packets
 1  LinuxRouter (192.168.0.1)  102.952 ms  102.900 ms  102.888 ms
...

Here, we see that LinuxRouter is the first hop and our gateway to the internet.

5.1. Troubleshooting

If connectivity issues arise, firstly, we should check the iptables rules, ensuring they match our network configuration. Additionally, detailed logs, often found in /var/log/syslog or /var/log/messages, can provide insights into any potential issues.

Furthermore, we can utilize tcpdump to inspect traffic traversing the gateway and verify it’s being routed correctly.

6. Conclusion

Transforming our Linux machine into a gateway is a powerful way to manage and direct network traffic. By understanding the fundamentals of IP forwarding and mastering iptables for NAT, we can configure a system to efficiently route packets between networks.

In this article, we’ve walked through the process step by step, from activating IP forwarding to configuring iptables rules, configuring clients, and finally testing the gateway’s functionality.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.