I’ve made a few choices that fit around my own preferences (firewalld) and problems I faced (bridgeutils and the classic network interfaces over bridging)
This is as much a cookbook as a guide
Picking hardware is easy. I got a system that was overkill – but basically there’s a ton of decent options. You’d want to take a look at the ars technica article that inspired this build for ideas.
You’ll be looking for at least 2 ports (I went with 4 – for future options of messing with multi-wan andor bonding). The typical, cheap celerons are probably good enough, and you don’t need all that much ram. AES-NI is recommended if you need it.
My fully built up system takes up *about* 4gb of hard disk space (not counting swap, so 8-16gb would be a good size for a hard disk. You will *also* be managing this via command line. If this scares you, you might consider a less generic router distro like pfsense or openwrt.
I am covering *everything* in detail so its a little long
It helps a lot to have a second system (or a third ). I basically used a spare laptop to check if I was getting an IP address
When I was initially setting this up on 18.04, I got this working without bridging. There’s some super strange and frustrating race conditions with dnsmasq and netplan, so in this case I’ve chosen to disable netplan. Since I’m also using firewalld (the ubuntu default is UFW), we’re changing stuff up up anyway. Netplan will work fine unless you bridge.
You’ll want to edit /etc/apt.sources.list and add the restricted universe and multiverse repos – I’m not sure which one has firewalld, but its something that’s usual for my builds. I’d use repogen and pick everything there up to updates
For now I’m setting this up as a client in my existing network. This gives me a chance to get it up before knocking out the entire network. Plug the pc into the network, run ip addr and take down what the existing network ports are. You’ll be bridging all but the “external ports” You can probably skip everything up to the firewall bits if you don’t want/need to bridge.
Plug in your external interface to the internet. Run
ip addr and note its adaptor name and that of all the other interfaces
sudo apt-get install ifupdown bridge-utils apt purge netplan.io
Set up your /etc/network/interfaces – enp1s0 is connected to the internet and is picking up an IP over DHCP. In our case we’ve chosen to bridge the other 3 interfaces in the system as well as the wireless interface (so we can set up hostapd later)
# interfaces(5) file used by ifup(8) and ifdown(8) auto lo iface lo inet loopback #primary interface, to internet auto enp1s0 iface enp1s0 inet dhcp #3x secondary interfaces and wifi. On bridge auto br0 iface br0 inet static address 192.168.2.1 netmask 24 bridge_ports enp2s0 enp3s0 enp4s0 wlp5s0
You can restart the network with
systemctl restart networking or
restart the PC and check if the settings have taken
Now comes the fun part
apt purge ufw (unless you want to do it with UFW)
apt install firewalld (If you can't find it, you didn't enable the additional repos or apt update) systemctl enable firewalld systemctl start firewalld
Now, we’ll want to enable ipv4 forwarding
sudo nano /etc/sysctl.conf
Then find the line that reads
net.ipv4.ip_forward=1 and uncomment it
sysctl -p to load the settings, though I rebooted cause I didn’t know any better
Now we can start setting up the firewall. One of the nice things with firewalld is that there’s zones with specific settings and we’ll be adding each of our interfaces to an appropriate zone, and opening a minimum number of services. I’ve used the internal zone for the internal facing interfaces (in theory you don’t have to bridge) and public for the internet facing interfaces. The first two commands add interfaces to zones, then we reload the firewall settings then check to see what the currently active zones are.
sudo firewall-cmd --permanent --add-interface=enp1s0 --zone=public sudo firewall-cmd --permanent --add-interface=br0 --zone=internal sudo firewall-cmd --reload sudo firewall-cmd --get-active-zones
Now the fun bits (though we can’t really test it yet) – these are the bits that let your little linux box at as a router. While you can add a –permanent to a command, firewalld rules can be set runtime only – which is useful if you need to do something temporarily or if you figure you need to undo it with a reboot.
sudo firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -o enp1s0 -j MASQUERADE sudo firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i br0 -o enp1s0 -j ACCEPT sudo firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i enp1s0 -o br0 -m state --state RELATED,ESTABLISHED -j ACCEPT sudo firewall-cmd --runtime-to-permanent
Install dnsmasq, configure, enable the dnsmasq service and start it
sudo apt install dnsmasq systemctl enable dnsmasq systemctl start dnsmasq
/etc/dnsmasq.conf is long, but very very well documented.
In our case we really only need to concern ourselves with a few parts of it, but its worth reading through as you go along so you can adjust it to taste. I’ve documented the bits that I’ve edited, and why
# Add other name servers here, with domain specs if they are for # non-public domains. #server=/localnet/192.168.0.1 server=126.96.36.199
I set up 188.8.131.52 as a default dns server. I think I was troubleshooting and this may be optional
We want dnsmasq listening on specific interfaces (in our case the bridge we set up earlier) but not others – we really shouldn’t be handing out ip addresses on the internet facing port
# If you want dnsmasq to listen for DHCP and DNS requests only on # specified interfaces (and the loopback) give the name of the # interface (eg eth0) here. # Repeat the line for more than one interface. interface=br0 # Or you can specify which interface _not_ to listen on except-interface=enp1s0
We also really do want our router doing dhcp. The following option is the minimal you need for things to “work”.
# Uncomment this to enable the integrated DHCP server, you need # to supply the range of addresses available for lease and optionally # a lease time. If you have more than one network, you will need to # repeat this for each network on which you want to supply DHCP # service. dhcp-range=192.168.2.50,192.168.2.150,12h
for initial setup, I’m using 192.168.2.x so I can plug in this router to an existing router, and test it in the meanwhile. This sets a range of about a hundred IPs you can use. Static IPs are also an option – but you’ll need to find the appropriate block. Make sure the br0 IP and the range given out are in the same block.
You will need to restart dnsmasq with
systemctl restart dnsmasq
You’ll also need to open up dhcp and dns to the internal zone.
sudo firewall-cmd --zone=internal --add-service=dhcp sudo firewall-cmd --zone=internal --add-service=dns
At this point, since masquerading and bridging is set up you should be able to plug a machine into the router, get an IP and connect to the internet.
you can use “tail /var/lib/misc/dnsmasq.leases” to see which IP addresses are given out.
Its probably a good idea to consider disabling ssh for the external zone
sudo firewall-cmd --permanent --zone=public --remove-service=sshd
It makes remote management harder but ssh servers tend to get hit by a ton of brute force attacks. Of course, a properly secured ssh server should be fine