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:
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,
- iptables rules must be re-enabled after each reboot
- 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!