Setup Ubuntu Server 20.04.1 LTS as Router
Some time ago, I setup a mini-PC AWOW AK34 with Arch Linux as a router. On occasion, my PC would drop its connection from this router, and this router reported no error. A reboot would immediately fix it but kind of annoying. On top of that, I was unable to setup Squid Proxy Server 4.x on it unless I downgrade to 3.5, and that also caused lots of problems. I therefore decided to try out Ubuntu Server as a router (not Ubuntu, as that would be catastrophic in boot time). I’m also planning on using this router to compile Android images for my phone, it’d be easier to follow the process (I also failed to compile these images on Arch Linux, so it’s only fitting I turn to Ubuntu even though I love Arch Linux).
Download the Ubuntu Server ISO from https://ubuntu.com/download/server and burn it on a USB key (at least 2GB) using Rufus from https://rufus.ie/. Make sure the “Partition Scheme” is “GPT” and the “Target System” is “UEFI” in Rufus (UEFI because my mini-PC is UEFI). Click “Start” when ready. After it’s finished, go to the USB folder and create the folder “wpasupplicant“. Ubuntu Server does not come with it, and unless you have a wired Internet connection, the newly installed Ubuntu will be useless. At the time of this post, I had to download the following 3 *.deb files to the “wpasupplicant” folder :
libpcsclite1: https://packages.ubuntu.com/focal/amd64/libpcsclite1/download
libnl-route-3-200: https://packages.ubuntu.com/focal/amd64/libnl-route-3-200/download
wpasupplicant: https://packages.ubuntu.com/focal/amd64/wpasupplicant/download
Wifi as Main Interface to Connect to Internet
Insert the USB key into the mini-PC, turn it on, and follow the installation instruction until it’s finished. Remove the USB, reboot the system, and then log into your account. Insert the USB key and mount the USB and copy the *.deb files to the home directory, and install them. And change the root password:
NewUser@Hostname:~$ mkdir wpasupplicant_files NewUser@Hostname:~$ sudo mkdir /media/USB NewUser@Hostname:~$ sudo mount-t vfat /dev/sdb1 /media/USB -o uid=1000,gid=1000,utf8,dmask=027,fmask=027 NewUser@Hostname:~$ cp /media/USB/wpasupplicant/*.deb ~/wpasupplicant_files/* NewUser@Hostname:~$ cd wpasupplicant_files NewUser@Hostname:~$ sudo dpkg -i *.deb NewUser@Hostname:~$ sudo passwd root
Enable IP Forwarding
The first thing we’ll do is setup packet forwarding. We’ll create the file 30-ip_forward.conf in /etc/sysctl.d (the number 30 is the level of execution or priority). I personally use the Vim editor, but for beginners, you can use “nano”. Save the file and exit using Ctrl-x. When finish, reload the system’s variables.
NewUser@Hostname:~$ cd /etc/sysctl.d NewUser@Hostname:/etc/sysctl.d$ sudo nano 30-ip_forward.conf net.ipv4.ip_forward=1 net.ipv6.conf.default.forwarding=1 net.ipv6.conf.all.forwarding=1 NewUser@Hostname:/etc/sysctl.d$ sudo sysctl --system
Set Dynamic and Static IP Addresses
Next, we’ll configure the network interfaces with dynamic and static IP addresses. They’re “enp1s0”, “enp2s0”, and “wlo1”. The wireless is “wlo1” and is connected to the internet, and the other two are the ethernet interfaces for private networks. These names may be different for you, and you can check them using the command “ip addr”.
NewUser@Hostname:/etc/sysctl.d$ ip addr 1: lo: . 2: enp1s0: . 3: enp2s0: . 4: wlo1: .
With this Ubuntu version, the network interfaces are managed with NetPlan. Let’s modify the existing configuration file 00-installer-config.yaml in /etc/netplan and we’ll have the system generate for us. Make sure the indentation within the file is respected. If you indent with 3 spaces, make sure all indentations are 3 spaces. If you’re using 4 or 8, make sure they are of the same width.
NewUser@Hostname:/etc/sysctl.d$ cd /etc/netplan NewUser@Hostname:/etc/netplan$ sudo nano 00-installer-config.yaml network: renderer: networkd wifis: wlo1: dhcp4: true access-points: SSID_NAME_TO_CONNECT password: PASSWORD ethernets: enp1s0: dhcp4: false addresses: [172.17.100.1/24] nameservers: addresses: [8.8.8.8,8.8.4.4] enp2s0: dhcp4: false addresses: [172.18.200.1/24] nameservers: addresses: [8.8.8.8,8.8.4.4] version: 2 NewUser@Hostname:/etc/netplan$ sudo netplan generate NewUser@Hostname:/etc/netplan$ sudo netplan apply NewUser@Hostname:/etc/netplan$ sudo netplan --debug apply
Setup DHCP Server
Next step is to setup the DHCP server to generate dynamic IP addresses to all devices connected to this router. First we need to install a DHCP server, then specify the network interfaces to , and then we’ll have to set up a range for addresses.
NewUser@Hostname:/etc/netplan/$ cd NewUser@Hostname:~$ sudo apt install isc-dhcp-server NewUser@Hostname:~$ cd /etc/default/ NewUser@Hostname:/etc/default$ sudo nano isc-dhcp-server INTERFACESv4="enp1s0 enp2s0" INTERFACESv6="" NewUser@Hostname:/etc/default$ cd /etc/dhcp NewUser@Hostname:/etc/dhcp$ sudo nano dhcpd.conf option domain-name-servers 8.8.8.8, 8.8.4.4; default-lease-time 86400; max-lease-time 86400; ddns-update-style none; authoritative; subnet 172.17.100.0 netmask 255.255.255.0 < range 172.17.100.150 172.17.100.154; # From 150 to 154 = only 5 devices maximum option routers 172.17.100.1; # Same static IP address as enp1s0 option subnet-mask 255.255.255.0; option broadcast-address 172.17.100.255; >subnet 172.18.200.0 netmask 255.255.255.0 < range 172.18.200.150 172.18.200.154; # From 150 to 154 = only 5 devices maximum option routers 172.18.200.1; # Same static IP address as enp1s0 option subnet-mask 255.255.255.0; option broadcast-address 172.18.200.255; >NewUser@Hostname:/etc/dhcp/$ sudo systemctl start isc-dhcp-server NewUser@Hostname:/etc/dhcp/$ sudo systemctl enable isc-dhcp-server NewUser@Hostname:/etc/dhcp/$ sudo systemctl status isc-dhcp-server
IPTables/Firewall Rules
The next part is to tell how the packets are routed from one interface to another using iptables rules.
NewUser@Hostname:/etc/dhcp$ cd NewUser@Hostname:~$ sudo iptables -t nat -A POSTROUTING -o wlo1 -j MASQUERADE NewUser@Hostname:~$ sudo iptables -A FORWARD -i enp1s0 -o wlo1 -j ACCEPT NewUser@Hostname:~$ sudo iptables -A FORWARD -i enp2s0 -o wlo1 -j ACCEPT NewUser@Hostname:~$ sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT NewUser@Hostname:~$ sudo apt install iptables-persistent
Sometimes, the typos are not flagged and not shown on the command line as errors. Therefore, it is important to know how to correct them. To look at the rules in the IP table, you can use the command “sudo iptables -L -v” for all the INPUT, OUTPUT, and FORWARD sections, and “sudo iptables -L -v -t nat” for the NAT section. Let’s say you type the wrong interface name in the POSTROUTING rule, and used wlo3 instead of wlo1. You’ll need to delete the rule (-D for delete instead of -A for append) and add the proper one. You’ll also need to save the new set of rules as root.
NewUser@Hostname:~$ sudo iptables -t nat -D POSTROUTING -o wlo3 -j MASQUERADE NewUser@Hostname:~$ sudo iptables -t nat -A POSTROUTING -o wlo1 -j MASQUERADE NewUser@Hostname:~$ su /etc/iptables/rules.v4 root@Hostname:~# exit NewUser@Hostname:~$
Install and Configure SSH Server
It is very possible that the SSH Server is already installed during installation. If not, install it. This allows the connected devices to access the router remotely. I’m also going to configure it so that it doesn’t use the default port 22 for SSH connection. You can choose any port you want as long as it’s not in the following list: https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
NewUser@Hostname:~$ sudo apt install openssh-server NewUser@Hostname:~$ cd /etc/ssh NewUser@Hostname:/etc/ssh$ sudo nano sshd_config #Port 22 Port 31420 # Change the default Port 22 to 31420 HostKey /etc/ssh/ssh_host_rsa_key # Uncomment this line PermitEmptyPasswords no # Uncomment this line AllowUsers NewUser # Add this line to allow certain users to remote connect PidFile /var/run/sshd.pid # Uncomment this line NewUser@Hostname:/etc/ssh$ sudo systemctl restart ssh NewUser@Hostname:/etc/ssh$ sudo systemctl status ssh # to verify if SSH is listening to the new port NewUser@Hostname:/etc/ssh$ sudo systemctl enable ssh
You should now be able to connect from any connected device to this router using the command format “ssh -p port_number username@ip_address”
ssh -p 31420 NewUser@172.17.100.1
The final test is to reboot the router and see if it works upon power up. That’s it~
Update (October 26 2021):
DHCP Server service failure
If you started having trouble with DHCP Server failing at boot up or reboot, it might be the DHCP server service tries to start before the network interfaces have establish. You can restart the DHCP server service manually, and it’ll work fine, but you definitely don’t want to do that every time, especially not for a router. One way to solve this is to automatically restart the service at an interval if it fails (rather than trying to rearrange service startup priorities).
NewUser@Hostname:~$ sudo nano /lib/systemd/system/isc-dhcp-server.service [Service] EnvironmentFile=/etc/default/isc-dhcp-server # already here RuntimeDirectory=dhcp-server # already here Restart=on-failure #
Kernel Update
Sometimes, you’d want to use a different Linux kernel that suits your needs better than the one shipped by default. Once you’ve determined which kernel you want to use, you can install it as follows.
Kernel website: https://kernel.ubuntu.com/~kernel-ppa/mainline/v(kernel version) -> headers generic -> headers all -> image unsigned -> modules or get the low-latency ones if you need them
In my case, kernel 5.6.10 works best for me.
# Make a directory for kernels NewUser@Hostname:~$ mkdir -p ~/linux_kernels/v.5.6.10 NewUser@Hostname:~$ cd !$ # Download the necessary files using Wget NewUser@Hostname:v.5.6.10$ wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.6.10/linux-headers-5.6.10-050610-generic_5.6.10-050610.202005052301_amd64.deb NewUser@Hostname:v.5.6.10$ wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.6.10/linux-headers-5.6.10-050610_5.6.10-050610.202005052301_all.deb NewUser@Hostname:v.5.6.10$ wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.6.10/linux-image-unsigned-5.6.10-050610-generic_5.6.10-050610.202005052301_amd64.deb NewUser@Hostname:v.5.6.10$ wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.6.10/linux-modules-5.6.10-050610-generic_5.6.10-050610.202005052301_amd64.deb # Install the *.deb files NewUser@Hostname:v.5.6.10$ sudo dpkg -i *.deb
After experimenting with different kernels, you might want to remove the ones that you no longer use. You’ll need to first boot into a kernel that you will be using in GRUB, and only then you remove the unwanted kernel.
NewUser@Hostname:~$ sudo vim /etc/default/grub GRUB_DEFAULT=0 #GRUB_TIMEOUT_STYLE=hidden #
After selecting the kernel in “Advanced Options”, then you can proceed with removing kernels.
# Command to list the different kernels NewUser@Hostname:~$ dpkg --list | egrep -i --color 'linux-' # Find all names of the kernel versions you want to remove and uninstall them as follows NewUser@Hostname:~$ sudo dpkg --purge linux-headers-5.6.10-050610-generic NewUser@Hostname:~$ sudo dpkg --purge linux-image-unsigned-5.6.10-050610-generic NewUser@Hostname:~$ sudo dpkg --purge linux-modules-5.6.10-050610-generic NewUser@Hostname:~$ sudo update-grub NewUser@Hostname:~$ sudo reboot
Everything should be fine. If not, browse in “/boot” directory and make sure the “initrd.img” and “vmlinuz” links are pointing to the proper kernel.