How to route home network via Wireguard running on Raspberry Pi 4

I was wondering how to simply protect all my traffic from anonymous data collection of my network provider & also how to be able to access all of the devices on my home network.

I’ve been playing with Wireguard for a while now and I find it to be super interesting network tunnelling technology.

In this post, I will walk you through steps to setup your own wireguard server and wireguard client that can connect your entire network to wireguard server.

As I wireguard server, I’m using my VPS from vpsFree.cz, which is a non-profit organisation providing infrastructure for its members. Generally, any VPS based on KVM/XEN or LXC will work. Just make sure you trust it enough :-).

I do not want to set up wireguard client on every single device at home, I’ve decided to route the entire traffic through gateway box – Raspberry Pi 4. You can use almost any device that can run Linux and has enough power to encrypt/decrypt your bandwidth.

The final bandwidth over the tunnel via Raspberry Pi 4 on 300/30 Mbps line is pretty good!

% speedtest-cli
Retrieving speedtest.net configuration…
Testing from Master Internet s.r.o. (77.93.x.y)…
Retrieving speedtest.net server list…
Selecting best server based on ping…
Hosted by JM-Net z.s. (Prague) [0.43 km]: 13.27 ms
Testing download speed……………………………………………………………………..
Download: 267.72 Mbit/s
Testing upload speed……………………………………………………………………………………
Upload: 32.58 Mbit/s

So, let’s get started!

For both server & gateway I will be using Ubuntu 18.04 LTS.

The Server

Please, make sure your server is update before we start. We will also do a reboot to load a new kernel. Feel free to omit it.

# apt-get update && apt-get -y dist-upgrade

# reboot

Wireguard is not directly included in Ubuntu’s repository, so we will need to add an extra repo from PPA:

# add-apt-repository ppa:wireguard/wireguard

# apt-get update

# apt-get install wireguard

Let’s set correct permisions on the new keys and generate them on server:

# cd /etc/wireguard

# umask 077

# wg genkey | tee privatekey | wg pubkey > publickey

Create a new file under /etc/wireguard/wg0.conf and make sure you replace Keys and IP addresses with your setup. We will be running the tunnel on port 80, so we can connect from anywhere. If you are running a web server on your server, just changed the port number :).

Also, we will set up POSTROUTING rules for handling different MTU sizes and we we will set up FORWARD (nat) rules between ens3 (network) and wg0 (tunnel).

[Interface]
Address = 10.0.0.1/24
SaveConfig = true

PostUp = iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o ens3 -j TCPMSS --clamp-mss-to-pmtu
PostUp = iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostUp = iptables -A FORWARD -i ens3 -j ACCEPT
PostUp = sysctl -q -w net.ipv4.ip_forward=1

PostDown = sysctl -q -w net.ipv4.ip_forward=0
PostDown = iptables -D FORWARD -i ens3 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -t mangle -D POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o ens3 -j TCPMSS --clamp-mss-to-pmtu

ListenPort = 80
PrivateKey = <private key of server>

We can start wireguard on the server, but nobody will be able to connect as we lack Peer section. We will add that later during setting up gateway.

# cd /etc/wireguard

# wg-quick up wg0

The Gateway

As gateway device, I’ve decided to use Raspberry Pi 4 Model B with 4GB of RAM. It is fairly cheap and it has enough power to route my entire bandwith (300Mbps / 30Mbps) over the Wireguard tunnel.

You can also get a cheaper version of Raspberry Pi 4 with less memory, but I’m still thinking about running other services on the box as well.

To set it up, we will need the board, power adapter, fan(less) case, micro-sd card (at least 16G), extra USB-3 Ethernet adapter and mini-HDMI cable.

I bought cover with fan, I would recommend to buy a fanless armor for your device, there is no need for active fan, unless you really want to overclock your PI.

You will need a SD card or microSD card slot connected to your PC for the installation. If you do not have one, you buy USB to SD card reader for couple of EURs.

My entire shopping list is below – based on Alza.sk prices. It should not cost more than 120 EUR all together. You might need some additional network cables, but I had those already.

ItemCost (EUR)
Mini PC Raspberry Pi 4 Model B – 4 GB RAM58,25
Power adapter RASPBERRY PI 4 – 5 V/3 A black10,75
Video cable OEM RASPBERRY Pi HDMI 1,8 m5,49
Case for RASPBERRY Pi 4 – Armor Fan black15,20
Kingston Canvas micro SDXC 64GB Class 10 UHS-I + SD 13,25
Network Card USB-3 Ethernet AXAGON ADE-SR11,58
Total114,52
My shopping list for Raspberry Pi 4 Model B

Assembling Raspberry Pi 4

There is a pretty good video for assembling fan and fanless armor to the board. Just follow the instructions and you should be good to go.

Installing base system

You can download the pre-created image for your Raspberry directly from Ubuntu’s website. I suggest you grab the 64bit version.

https://ubuntu.com/download/raspberry-pi

Once you have the image downloaded, simply follow the steps from Ubuntu’s tutorial how to copy the image to SD card.

https://ubuntu.com/tutorials/how-to-sdcard-ubuntu-server-raspberry-pi#1-overview

Once you are finished, just insert the microSD card into the board slot and the ubuntu should start.

The default user is ubuntu, you will be prompt to change password immediately.

By default the ubuntu has DHCP enabled on the Ethernet port, so we can simply connect remotely.

Before we begin with the installation of wireguard, please make sure your system is fully updated. The default ubuntu image is a bit outdated, so we will do a reboot to get newest kernel.

# apt-get update && apt-get -y dist-upgrade && reboot

Wireguard gateway

In this section, we will install DHCP server that will server our internal network, then we will set up wireguard VPN to our server and route all traffic via the tunnel.

Before we begin, I will be using on-board ethernet as WAN port (eth0) and USB ethernet as LAN port (eth1).

Wireguard is not directly included in Ubuntu’s repository, so we will need to add an extra repo from PPA as we did in Server installation:

# add-apt-repository ppa:wireguard/wireguard

# apt-get update

# apt-get install wireguard

Let’s set correct permisions on the new keys and generate them on client:

# cd /etc/wireguard

# umask 077

# wg genkey | tee privatekey | wg pubkey > publickey

Create a new file under /etc/wireguard/wg0.conf and make sure you replace Keys and IP addresses with your setup. We are also adding MASQUARADE and NAT rules for packet forwarding between our tunnel interface (wg0) and LAN interface (eth1). AllowedIPs means that we will route all traffic via wg0 interface.

[Interface]
Address = 10.0.0.2/32
PrivateKey = <paste privatekey from client>

PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -A FORWARD -o wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
PostUp = iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

PostDown = sysctl -w net.ipv4.ip_forward=0
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -D FORWARD -o wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth1 -j MASQUERADE

[Peer]
PublicKey = <paste public key from server>
Endpoint = <public IP of server>:80
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

We will need to add Peer section onto our Server into /etc/wireguard/wg0.conf:

[Peer]
PublicKey = <public key of Client>
AllowedIPs = 10.0.0.2/32, 172.16.0.0/24

Do not forget to restart wiregard on server.

# wg-quick down wg0 && wg-quick up wg0

Back to our client. Now, we should be able to connect to our VPN server and route all traffic in the system through it. The public IP address should change after we connect, so let’s check that. I will be using our HTTP service to check my public IP address on ip.websupport.sk.

# curl ip.websupport.sk

178.143.x.y
Slovakia
SK

# wg-quick up wg0

# curl ip.websupport.sk

77.93.x.y
Czechia
CZ

Also, we should be able to ping our server over private wireguard tunnel.

# ping 10.0.0.1 -c 2

PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=3.46 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=4.69 ms

--- 10.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 3.460/4.077/4.694/0.617 ms

If everything works as expected, let’s enable wg0 to start on system startup, this goes for both Server and Gateway.

# systemctl enable [email protected]

DHCP Daemon

Okay, let’s build our internal network with DHCP server on Raspberry PI. We will use isc-dhcp-server and 172.16.0.0/24 on our internal network. Raspberry PI will server as gateway and will have an IP of 172.16.0.1.

First, let’s adjust netplan for eth1 to have desired IP. Just modify the file /etc/netplan/50-cloud-init.yaml.

# cat /etc/netplan/50-cloud-init.yaml

network:
ethernets:
eth0:
dhcp4: true
optional: true
eth1:
addresses:
- 172.16.0.1/24
version: 2

Let’s try the settings

# netplan try

If everything looks good, let’s apply them:

# neplan apply

Now, we will install isc-dhcp-server and create a config file for eth1 subnet with dhcp lease of IPs from our range. I’ve decided to start leasing from .10 to .250.

# apt-get -y install isc-dhcp-server

Now, adjust the config file for dhcp daemon

# cat /etc/dhcp/dhcpd.conf

default-lease-time 600;
max-lease-time 7200;

ddns-update-style none;

authoritative;

subnet 172.16.0.0 netmask 255.255.255.0 {
interface eth1;
range 172.16.0.10 172.16.0.250;
default-lease-time 600;
max-lease-time 7200;
}

Let’s start the DHCP server

# systemctl enable isc-dhcp-server

Final Check

And now all our LAN clients should be able to get IP address from our local network and be routed via Wireguard tunnel! We can verify it from local console on the client.

% ifconfig en0 |grep inet
inet 172.16.0.25 netmask 0xffffff00 broadcast 172.16.0.255
% curl ip.websupport.sk
77.93.x.y
Czechia
CZ

What to do next?

You can set up firewall on your Raspberry Pi or you could try to overclock it to get better performance or you could try to setup IPv6 network as well! I would also suggest to set up monitoring for your raspberry pi and log collecting. Have fun :-).