BYOR part deux Hello all!
I’m back again with part two of the Build Your Own Router Series!
In this post, we’re going to do the following:

  • Talk about our proposed network architecture
  • Set up our interfaces
  • Set up a DHCP server and define our subnets
  • Define some subnet ranges for our devices
  • Set up some DHCP reservations
  • Set up a DNS cache server
  • Set up some basic iptables rules and forwarding

What you must have before this point

You need a Linux machine with two NICs, updated and ready to go.(I’ll be using 64bit Debian Jesse)

The Network Architecture

Most likely, unless you have a particularly different setup, you have a modem connected to a combo router/wireless access point, or perhaps a modem+router+WAP all-in-one unit. See the images below for a diagram of this:

Typical All-In-One Home LAN

Typical All-In-One Home LAN

Our Home LAN

Typical Modem+Router/WAP/Switch Home LAN

The units in the red boxes usually handle the following things and not much more:

  • Routing
  • DHCP
  • DNS
  • Firewall

It’s likely a small system-on-a-chip (SoC) and is configured with a web GUI. The architecture we are proposing is a little different. We want to replace that router part (the part inside the red box) with our Linux machine. We’ll let the Linux kernel do our packet switching, and let a few services handle DHCP, DNS, and the Firewall.

Note: this will require that you have a separate modem with an Ethernet interface.

Our IP network will have the following properties:

Property Value or Description
Subnet 192.168.0.0/22
Linux machine LAN IP 192.168.0.1
DHCP Pool 192.168.1.0/24

Let’s set up the interfaces

First, let’s see our two NICs and find out what the system calls them:

machine:/# ls /sys/class/net
	eth0  eth1  lo
machine:/#

So we now know our interfaces are named eth0 and eth1. Let’s designate eth0 as the WAN or Internet side of our machine, and designate eth1 as the LAN side of the interface.
Edit the /etc/network/interfaces to set up our WAN side to get and IP address from the ISP and our LAN side to have a static IP on our subnet.
The file should look similar to:

	source /etc/network/interfaces.d/*

	# The loopback network interface
	auto lo
	iface lo inet loopback

	# The WAN network interface
	allow-hotplug eth0
	iface eth0 inet dhcp

	# The LAN network interface
	allow-hotplug eth1
	iface eth1 inet static
		address 192.168.0.1
		netmask 255.255.252.0


Once you save this file and restart the network service, you should be able to see your interfaces using the tool ifconfig.
Now, plug in the WAN side to your router and let’s get on the internet!

Setting up DHCP

Since we want our Linux machine to hand out IP addresses on our LAN side, we need to install a DHCP server. Use your package manager to install isc-dhcp-server:

	apt-get install isc-dhcp-server

Now we need to tell the DHCP server what to do. Edit the DHCP configuration file (likely in /etc/dhcp/dhcpd.conf)

	option domain-name-servers              172.16.0.1;
	option routers                          172.16.0.1;
	default-lease-time                      600;
	max-lease-time                          7200;
	ddns-update-style none;

	subnet 192.168.0.0 netmask 255.255.252.0
	{
		option broadcast-address 192.168.3.255;
		allow unknown-clients;	
		pool {
			    range 192.168.1.0 192.168.1.255;

		}
	



	}

This will instruct the DHCP server to hand out addresses on the LAN in the range 192.168.1.0/24.
Restart the DHCP service to have these changes take effect. You should now be able to plug your laptop into the LAN port on your Linux machine and get an IP address via DHCP.
Now that we have some addresses assigned for DHCP use, let’s assign some DHCP reservations. Editing the same config file, add this:

host my-laptop {
		hardware ethernet aa:bb:cc:dd:ee:ff;
        fixed-address 192.168.2.0;
}

The ‘hardware ethernet’ line should contain the MAC address of your laptop, and the ‘fixed-address’ line should be the address you want to give that machine each time it requests one. Another restart will cause these new changes to take effect.

DNS Cache server

This is the easy part!

	apt-get install bind9

Done! That’s all for a basic configuration.

Forwarding and Firewall

Now we have a machine which can hand out IP addresses, but it can’t actually forward any traffic yet! First thing’s first, let’s enable forwarding.
Edit /etc/sysctl.conf and change the line regarding IPv4 forwarding to

net.ipv4.ip_forward = 1

Then, to make these changes active, issue a ‘sysctl -p’
Now we can forward traffic, let’s create some iptables rules to keep us straight. Two things to note here,

  1. iptables rules must be re-enabled after each reboot
  2. iptables can be dangerous! always backup your configuration

Because iptables are not persistent between reboots, we’ll use a script! Let’s first create a file in /etc/network/ called ‘iptables-rules’. In this script, place the following iptables rules:

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]


-A POSTROUTING -o eth0 -j MASQUERADE

COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]



# accept all loopback
-A INPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -i lo -j ACCEPT

# accept all pings
-A INPUT -p icmp -j ACCEPT

# accept all established connections
-A INPUT -m state --state ESTABLISHED -j ACCEPT

# enable traceroute rejections to get sent out
-A INPUT -p udp -m udp --dport 33434:33523 -j REJECT --reject-with icmp-port-unreachable

# DNS from LAN
-A INPUT -i eth1 -p tcp --dport 53 -j ACCEPT
-A INPUT -i eth1 -p udp --dport 53 -j ACCEPT

# SSH from LAN
-A INPUT -i eth1 -p tcp --dport 22 -j ACCEPT

# DHCP from LAN
-A INPUT -i eth1 -p udp --dport 67:68 -j ACCEPT


# forward packets along established/related connections
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# forward from LAN to WAN 
-A FORWARD -i eth1 -o eth0 -j ACCEPT
-A FORWARD -i eth1 -o tun0 -j ACCEPT

# drop all other forwarded traffic
-A FORWARD -j DROP


# drop all other inbound traffic
-A INPUT -j DROP


COMMIT

The comments for each section describe what that particular rule accomplishes. Now, let’s make the script which will restore these rules on startup. Create an executable file in /etc/network/if-pre-up.d called iptables-restore-rules. In that file, insert this:

#!/bin/sh
iptables-restore < /etc/network/iptables-rules

The location of this script, ensures that it will be executed *prior to* the network interfaces coming up, therefore protecting us from the internet!

Wrap up

Now we have a basic Linux router which can serve IP addresses, route packets between interfaces, and has a basic level of firewalling from the internet. In the next post, we’ll do some more iptables stuff, and talk about OpenVPN and how we can use policy based routing to route some traffic through a VPN and some around it.
As always, thanks for reading!