Introduction

This is a description on how to set up a server based on ArchLunix to route network traffic between two interfaces. As an extension I also add some common router functions such as DHCP/DNS and NAT/firewall.

For configuring a server as described here at least two network interfaces are needed. In my setup I used a virtual machine with 3 network interfaces, 1 management interface called enp0s3 and two interfaces for routing between two networks, they are called enp0s8 and enp0s9.

The interface enp0s8 is connected to network1 and enp0s9 is connected to network2.

Configuration

Routing is enabled by turning on forwarding in the kernel

# sysctl net.ipv4.conf.all.forwarding=1

This will turn on forwaring on all interfaces and set the ip_forward flag. Note that it is only temporary, it will not be persistent accross a reboot. To make forwarding persistent add a sysctl conf file:

# echo "net.ipv4.conf.all.forwarding=1"  | sudo tee /etc/sysctl.d/routing.conf

Configure IP addresses with netctl

The network interfaces that will be used for routing need to have static ip addresses so let’s start with that.

On ArchLinux netctl can be used for handling network interfaces. In order to use netctl the interfaces need to be down otherwise interfaces are considered to already be managed by some other service and netctldoes not do anything. Bring down the interfaces:

$ sudo ip link set enp0s8 down
$ sudo ip link set enp0s9 down

If dhcpcd is running the static/extra interfaces needs to be disabled from getting managed by dhcpcd. This is done by adding the following line to /etc/dhcpcd.conf:

allowinterfaces enp0s3

This will use DHCP on the ‘management’ interface and not the other interfaces.

Example

Interface enp0s8 and enp0s9 are connected to two different networks.

Assigning ip address can be done with ip addr but for making it persistent I’ll do it the netctl way.

Create a netctl profile in the file /etc/netctl/enp0s8 containing:

Interface=enp0s8
Connection=ethernet
IP=static
Address='10.0.1.1/24'

And for the next interface create the profile: /etc/netctl/enp0s9 containing:

Interface=enp0s9
Connection=ethernet
IP=static
Address='10.0.2.1/24'

Now list available netctl profiles

$ netctl list
  enp0s8
  enp0s9

A * will indicate interfaces that are up and configured.

Start profiles:

$ sudo netctl start enp0s8
$ sudo netctl start enp0s9

To make this configuration persistent:

$ sudo netctl enable enp0s8
$ sudo netctl enable enp0s9

Then set up a DHCP server to assign addresses to hosts on the two networks.

DHCP server

A simple choice for running a DHCP server is dnsmasq. Install dnsmasq

$ sudo pacman -S dnsmasq

Configure dnsmaq in /etc/dnsmasq.conf, the file contains a lot of config lines that are commented out and one just have to find the needed config option and enable it with the wanted parameters.

First specify the interfaces to listen to

interface=enp0s8
interface=enp0s9

there are other options here, for example you can list interface not to listen to instead, or the address to listen on etc.

Then configure ranges on which to hand out adresses

dhcp-range=10.0.1.100,10.0.1.250,12h
dhcp-range=10.0.2.100,10.0.2.250,12h

This will hand out addresses in the range 10.0.1.100 -> 10.0.1.250 on the 10.0.1.0/24 network and 10.0.2.100 -> 10.0.2.250 on that network. The last number on the line is the DHCP lease time.

For debugging purposes it can be nice to turn on logging in dnsmasq. This is done by editing dnsmasq service script. Open /usr/lib/systemd/system/dnsmasq.service and add the --log-facility argument:

ExecStart=/usr/bin/dnsmasq -k --enable-dbus --user=dnsmasq --pid-file --log-facility=/var/log/dnsmasq.log

DNS

dnsmasq also serves as a DNS server. It’ll use /etc/hosts to resolve hostnames. Start by specifying name and ip in /etc/hosts

10.0.1.50   server1
10.0.1.51   server2

Use dhcp-host in /etc/dnsmasq.conf to make the dhcp server hand out the ip above to a server that identifies itself as the host name.

dhcp-host=server1
dhcp-host=server2

A server with host name server1 on network1 will now get the ip 10.0.1.50 and other servers can access server1 by host name and will have the name resolved to the same ip.

Start and enable dnsmasq service:

$ sudo systemctl start dnsmasq.service
$ sudo systemctl enable dnsmasq.service

Firewall

The linux kernel firewall iptables is used to prevent access to hosts on the two networks. In this example hosts on network2 (the 10.0.2.0/24 network on enp0s9) will be behind NAT and hidden outside that network. Hosts on network1 are still accessible individually from network2.

Add a rule to the nat table to replace the source address for hosts on network2 for traffic that leaves to the other network

$ sudo iptables -t nat -A POSTROUTING -o enp0s8 -j MASQUERADE

It is also possible to use SNAT instead of MASQUERADE here since the ip address is static, perhaps also perferable for performace reasons.

Then add a rule to the filtering table to block traffic from network1 to network2, i.e. traffic entering enp0s8 and going out on enp0s9.

$ sudo iptables -I FORWARD -i enp0s8 -o enp0s9 -j REJECT

This will also block responses to traffic going out from network2 to network1. That is fixed by adding a filtering rule to allow packets that are part of an already established connection.

$ sudo iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

Make the firewall rules persistent by saving current config to a config file

$ sudo iptables-save | sudo tee /etc/iptables/iptables.rules
$ sudo iptables-save -t nat | sudo tee -a /etc/iptables/iptables.rules

Then enable the service

$ sudo systemctl enable iptables.service

Conclusions

As seen here it’s really simple to create a Linux router. Of course there is a lot more that can be done that will make things more complicated. Anyway, I had a lot of fun exploring this!

References

ArchLinux Router

netctl

iptables

NAT with iptables