PerformanceBlog

Insights von Anton Pütz, Dipl.-Inf. (Univ.)
Anton Pütz
Raspberry Pi 4 starter kit for the WireGuard server

Creating a WireGuard VPN Server on a Raspberry Pi 4

WireGuard logo

Update (August 9, 2021): The current Raspi OS versions include WireGuard as a package, so there is no need to build it yourself anymore.


Lately, due to Coronavirus, many businesses have been obliged to switch how they operate, giving employees the ability to work from home. For many businesses – particularly newer companies with their infrastructure in the cloud – this hasn’t been much of an issue. But for businesses with on-premises infrastructure, the pandemic was an unpleasant surprise.

For over a year now, I have been freelancing and I have my IT infrastructure both on-premises and in the cloud. To be able to access my whole on-premises infrastructure, I set up a VPN server, which has been very reliable until now.
I started with OpenVPN hosted on my Synology NAS DS216+II, but I constantly struggled to keep it working, mainly due to VPN client updates that forced me to reconfigure the tunnel – very cumbersome.

So after reading a lot about WireGuard, I decided to give it a try. As hardware, I decided to use a Raspberry Pi, since I have been using them a lot since the first Raspberry Pi was released and I have had excellent experiences with them. Please see the Raspberry Pi website for more information.
Now in its fourth generation, it has a chipset based on an ARM 64-bit architecture. Nevertheless, it is still mainly used in 32-bit mode. As RAM now reaches 4 GB, it is only a matter of time until 64-bit becomes the default operating mode.

In this article, I’ll walk you through the steps to set up the Raspberry Pi 4 with Raspbian and WireGuard. Most of the steps rely on this Reddit guide and the official WireGuard installation guide.

WireGuard VPN Features

IP Roaming

When switching between mobile and wired networks, the connection stays alive without needing to reconnect.

State-of-the-art encryption

The algorithms used for encryption are powerful, which is, of course, good since you want to keep the data private.

Easy setup

Compared to both IPsec and OpenVPN, WireGuard is much simpler to set up and run. In this tutorial, we will configure the client using a QR code, which provides the configuration needed.

Performance

I haven’t benchmarked it myself, but independent benchmarks state that it is more performant than, for example, OpenVPN.

Easier to security-audit

Due to its low amount of code, it is easier to audit than other VPN solutions.

Future-proof

In March 2020, with the definition of the features for the Linux Kernel 5.6, it was decided that WireGuard would become part of the kernel, which will probably give WireGuard a big push.

There are several VPN protocols (IPsec, OpenVPN, etc.) that are difficult to set up. WireGuard gets rid of these difficulties and provides state-of-the-art encryption while doing so. The Raspberry Pi 4’s popularity makes it ideal as the underlying hardware.

You can find more information on the official WireGuard website.

Setting up the Raspberry Pi 4

If you don’t have a Raspberry Pi 4 yet, you can buy one online. I purchased a kit since it is more convenient as it includes all you need to have it operating (SD card, power supply, heatsink, fan).

Raspberry Pi 4 kit
Raspberry Pi 4 Kit
Contents of the Raspberry Pi starter kit
Contents of Starter Kit

Prepare SD-Card

Follow the installation steps for Raspberry Pi OS in the official guide.

We will be operating the Raspberry Pi in headless mode; this means the Raspberry Pi 4 will be connected only to our LAN, and we will access it over SSH.

For security reasons, SSH is disabled by default, but this can be changed pretty easily.

After writing the image to the SD card, reinsert it into your computer.

It should automatically mount a volume named "boot". In this volume, just add an empty file with the name ssh. On macOS/Linux, change to the directory and type:

touch ssh

You can configure a lot of parameters of the OS (Wi-Fi usage, Wi-Fi network, custom network information, enabling 64-bit, etc.) before starting the RPi. For more information, see the official documentation.

I’ll assume that you are using a DHCP server for IP provisioning in your network. If not, refer to the link provided previously for setting up an IP address manually.

Please retrieve the IP address provided by the server on the admin console of the router. Since this is router-dependent, please refer to your router’s manual to find out how to do this.

Once you have the IP address, it is time to connect to it over SSH using the "pi" user provided by Raspbian. On macOS/Linux, type:

ssh pi@<IP-address>

In my case, the IP is 192.168.2.112, so I use:

ssh pi@192.168.2.112

If everything works fine, you will get a message similar to this:

First login in Raspberry Pi OS
First login in Raspberry Pi OS

The default password of the "pi" user is "raspberry", which, for security reasons, we will change first.

But before doing so, let’s update everything to the latest state:

sudo apt update && sudo apt upgrade -y

Now let’s do some basic configuration. To do so, type:

sudo raspi-config

You will get a menu similar to this one:

raspi-config menu
raspi-config menu
  1. Change the password for the 'pi' user (Option 1)
  2. Configure the RPi to your timezone (Option 4 'Localisation Options', then 'I2 Change Timezone')
  3. Expand the filesystem (Option 7 'Advanced Options', then 'A1 Expand file system')
  4. Exit raspi-config, which will ask for a reboot.

Setting up WireGuard on the Raspberry Pi 4

Now we are ready for the VPN part of the tutorial. For that we log in with the "pi" user, using the new password. Then we need to install some extra packages since we will be building WireGuard from source code.

sudo apt install raspberrypi-kernel-headers libelf-dev libmnl-dev build-essential git -y

Now we are ready to clone the WireGuard source code, compile it and install it:

git clone https://git.zx2c4.com/wireguard-linux-compat && git clone https://git.zx2c4.com/wireguard-tools
make -C wireguard-linux-compat/src -j$(nproc)
sudo make -C wireguard-linux-compat/src install
make -C wireguard-tools/src -j$(nproc)

 

sudo make -C wireguard-tools/src install

 

Next, check whether IP forwarding is active. To do so, run:

sudo sysctl net.ipv4.ip_forward

If this returns 1, go ahead with the creation of the public / private keys.

If the command returned 0, please run:

echo "net.ipv4.ip_forward=1" |  sudo tee -a /etc/sysctl.d/01-custom.conf

and then let the OS reload the config files

sudo sysctl --system

and check that the IPv4 forwarding works:

sudo sysctl net.ipv4.ip_forward

which should return 1.

Thanks to pghpete for providing better instructions on improving the IP forwarding part.

Creation of Public / Private Keys

We will configure WireGuard in the next steps. Before going on, I recommend thinking about the number of clients (physical users/devices) you plan to have using the VPN tunnel simultaneously. For each combination, you will need to create one pair of public/private keys that will be used to secure the communication between server and client. We will nevertheless first go through the instructions for one client only and, in the end, provide instructions on how to create configurations for further clients.

Now we are going to create the public / private keys for the server and one client.

sudo su
cd /etc/wireguard
umask 077
wg genkey | tee server_privatekey | wg pubkey > server_publickey
wg genkey | tee peer1_privatekey | wg pubkey > peer1_publickey
exit

Now that we have the keys, we can create the configuration for both the server and the client.

Server configuration

While still in /etc/wireguard, create a file called wg0.conf with the following content:

[Interface]
Address = 10.9.0.1/24
ListenPort = <ListenPort>
DNS = <DNS>
PrivateKey = <server_privatekey>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o <Interface> -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o <Interface> -j MASQUERADE

[Peer]
#Peer-1
PublicKey = <peer1_publickey>
AllowedIPs = 10.9.0.2/32

replacing the placeholders <…> with the information as explained below

Parameters

ListenPort = The listening port for WireGuard on the Raspberry Pi.

DNS = The IP address of the DNS server (<DNS>).

PrivateKey = The content of the server_privatekey file created before (<server_privatekey>).

PublicKey = The content of the peer1_publickey file created before (<peer1_publickey>).

Interface = The interface name (normally eth0) which is connected to your LAN. This is important so that you can connect to your LAN over the VPN tunnel once the connection is made.

Peer (client) configuration

Now we are going to set up the configuration for our client.

For that, we create a file in /etc/wireguard called peer1.conf with the following content:

[Interface]
Address = 10.9.0.2/32
DNS = <DNS>
PrivateKey = <PrivateKey>
[Peer]
PublicKey = <PublicKey>
Endpoint = <Endpoint>
AllowedIPs = 0.0.0.0/0, ::/0
#PersistentKeepalive = 60

replacing the placeholders <…> with the information as explained below

Parameters

DNS = the IP address of the DNS server (<DNS>).

PrivateKey = The content of the peer1_privatekey file (<PrivateKey>).

PublicKey = The content of the server_publickey file (<PublicKey>).

Endpoint = public IP address or dynamic DNS hostname:ListenPort (for example, fictive-hostname.com:45678). Please remember that you will probably need to forward your router’s external port (45678 in the example above) to the ListenPort number configured in wg0.conf so that you can reach WireGuard in the Raspberry Pi.

AllowedIPs = For which destination networks the traffic is going to be routed over the tunnel. In this case (0.0.0.0/0, ::/0), all traffic is sent through the VPN tunnel.

You would need to uncomment the last line (PersistentKeepalive) in case you are behind a NAT.

Configuring client device

To be able to use the VPN tunnel, we need to set up a client now with the configuration used before. In case of setting up a mobile device, we can generate a QR code with the configuration and read it from the WireGuard app directly. For that, we first need to create the QR code. First, install a tool to generate the QR code, with the configuration file as input:

QR code creation
sudo apt install qrencode -y
sudo qrencode -t ansiutf8 < /etc/wireguard/peer1.conf

With that, we are going to see a QR code on the console, which we can read with the mobile device. Nothing else is needed for the tunnel to work on the client side.

Last steps

We are now going to perform some last steps on the Raspberry Pi before we can use the tunnel. We will set up WireGuard to start automatically at boot and correct the permissions of the generated files:

sudo systemctl enable wg-quick@wg0
sudo chown -R root:root /etc/wireguard/
sudo chmod -R og-rwx /etc/wireguard/

Please make sure that the Endpoint configured in the peer config file (peer1.conf) is reachable over the internet – meaning that the router is configured to forward the communication to WireGuard on the Raspberry Pi (meaning that you set a forwarding rule for UDP traffic on the configured ListenPort).

After a restart of the Raspberry Pi, the tunnel should be reachable & working from your phone.

Steps for adding another peer

In this case, you will need to create a new pair of public/private keys for the new peer (replacing n with a higher number than the number of peers already available):

sudo su
cd /etc/wireguard
umask 077
wg genkey | tee peern_privatekey | wg pubkey > peern_publickey
chown -R root:root /etc/wireguard/
chmod -R og-rwx /etc/wireguard/
exit

After that, you would append a [Peer] section in the wg0.conf file, modifying the parameters, as explained before. Instead of using peer1_publickey, you would use peern_publickey, though.

Then you would create a new peern.conf file, analogous to the peer1.conf file created before. Now you would nevertheless use peern_privatekey instead of peer1_privatekey.

This new peern.conf file is what you will use to either generate a new QR code or to import directly into your WireGuard client.

I hope you find this information helpful and can enjoy a working WireGuard VPN tunnel at the end.

This article was first published on Medium.

Self-hosted Kubernetes auf Bare Metal: Praxisbericht

Und dann habe ich einen Rust-Microservice darauf deployt, um mein Garagentor per iOS zu öffnen. Wer über Kubernetes spricht, meint ...

Optimierung der Finanzverwaltung: Wie ich mit Beancount und LLMs Amazon-Bestellungen effizient analysiere

Seit einigen Jahren nutze ich Beancount, um unsere Familienfinanzen im Blick zu behalten. Beancount ist ein System für die doppelte Buchführung, das auch ...

Sicherer WLAN-Betrieb im Haus und im Small Office

Mit dem verstärkten Einsatz von Homeoffice sind die IT-Sicherheitsanforderungen an das eigene Netz größer als zuvor. Mich stört ...
Homeoffice-Schreibtisch mit Monitoren und Kamera

Mein Setup nach einem Jahr Homeoffice

In meinem letzten Artikel hatte ich mein damaliges Setup vorgestellt. Ich habe danach sehr viel ausprobiert und bin mittlerweile mit ...