My WireGuard VPN Setup

May 16, 2019

I recently set up WireGuard as a VPN solution so that I can connect to my home network while on the road.

This post serves as a guide/lookup to future me, when I need to add new clients or set it up again. Hopefully it can also be of help to others.

My setup is on a Debian server, after I gave up on configuring WireGuard on my UniFi Security Gateway (router). I learned a lot about WireGuard from my failed attempts at getting a correct config set up using the UniFi system. As such much of the information here is from articles I found during my research for that setup. They will be linked throughout the post and at the bottom.

So What Is WireGuard Anyway?

WireGuard is a new take on VPN, serving as a kernel module with much simpler setup than many other VPN solutions.

In the words of the WireGuard website:

WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN.

Installing

Following the installation steps from the article Setup a VPN Server with WireGuard on Debian 9, I had the software installed pretty quickly. If you are not on Debian (or a compatible distro), the rest of this post should still serve as a guide once you’ve figured out how to install on your distro of choice.

1
2
3
4
echo "deb http://deb.debian.org/debian/ unstable main" | sudo tee /etc/apt/sources.list.d/unstable.list
echo -e "Package: *\nPin: release a=unstable\nPin-Priority: 150\n" | tee /etc/apt/preferences.d/limit-unstable
sudo aptitude update
sudo aptitude install wireguard

You can check the installation with:

lsmod | grep wireguard

which should not return an empty response. If it did, you can try enabling the kernel module using:

sudo modprobe wireguard

Config

Again, following the Setup a VPN Server with WireGuard on Debian 9 article, I placed my config file in /etc/wireguard/wg0s.conf. This files content is fairly simple. Let’s go over it, step by step.

Server

1
2
3
4
5
6
[Interface]
Address = 10.0.1.1/24
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o enp2s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o enp2s0 -j MASQUERADE
ListenPort = 51820
PrivateKey = {the servers private key}

In this section, we define the interface on the VPN server.

The first thing you see is the Address which in my case is set to 10.0.1.1/24. The /24 is CIDR notation, and in this case it means the interface covers all IP’s from 10.0.1.1 to 10.0.1.255, for a total of 254 IP’s.

The PostUp and PostDown are used to toggle allowing traffic to the VPN interface along with the server being enabled and disabled.

ListenPort is somewhat self-explanatory, as that’s the port the server will listen for incomming connections on. If you need to access your VPN on a very strict network, you might want to set this port to something in a more normal range, such as 443 (https) or 80 (http). Assuming you don’t need to host anything else on those ports.

The PrivateKey is a little more interesting. This is the private key of the server, which you generate with the following command:

wg genkey | tee server.private.key | wg pubkey > server.public.key

The names of the files are up to you, but I prefer this naming scheme as it’s very clear what’s what, and WireGuard is a little confusing with all the keys needed.

1
2
3
4
5
6
7
8
9
[Peer]
# Andreas Laptop
PublicKey = {a public key}
AllowedIPs = 10.0.1.20/32

[Peer]
# Andreas Phone
PublicKey = {a public key}
AllowedIPs = 10.0.1.21/32

The configuration for clients (or peers) on the server side is quite a bit simpler. Here we simply need to add a new [Peer] block for every client we want to add.

Just like we have the PrivateKey in the [Interface] section, the peers have PublicKey, which is their public key. You can generate the clients keys on the server too if you like. However for some clients it’s easier to use the provided interface that comes with WireGuard for the platform. More about this later.

AllowedIPs are the IP’s assigned to the client when they connect to the server, again in CIDR notation. /32 means the specific IP written.

Clients

So far I have only set up clients on MacOS, so for now this only covers MacOS.

I installed the client from the App Store. It’s a menu bar app, so find it up top, select Manage tunnels, and proceeded to create a new tunnel by clicking the + button in the lower left corner of the Manage WireGuard Tunnels window, as seen below. Then choosing Add empty tunnel....

Manage WireGuard Tunnels - List

A modal will now show, with your private and public keys. Give your new tunnel a name.

Create New Tunnel

Keep the private key as is, and use the public key to create a new [Peer] block on your server. Then follow the below template to configure your client to talk to your server.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Interface]
PrivateKey = {your private key}
Address = 10.0.1.21/32 # Your IP as assigned by the server
DNS = 1.1.1.1 # A DNS server to use if you want that

[Peer]
PublicKey = {the public key of the server}
AllowedIPs = 10.0.1.1/24
Endpoint = {your server ip/domain}:51820
PersistentKeepalive = 25

Most of the above config should look familiar by now.

The one gotcha that confused me a bit here is that the [Peer] block’s AllowedIPs are the interfaces your client can communicate with on the server. So if you want to reach into your normal network when connected to VPN, it’s important to remember your main IP range too.

The Endpoint is either the IP or domain of your server. If the server is not directly exposed to the internet, you of course need to port forward and open up your firewall to allow the traffic through.

Mobile clients

When it comes to mobile clients, it’s quite a bit easier to create the config file on a computer, and scan a QR code with the phones camera. Follow the template below (identical to the non-mobile clients), changing values as needed, for a quick setup. Thanks to WireGuard Setup Guide for iOS.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Interface]
PrivateKey = {the phones private key}
Address = 10.0.1.20/32
DNS = 1.1.1.1

[Peer]
PublicKey = {the public key of the server}
AllowedIPs = 10.0.1.1/24
Endpoint = {your server ip/domain}:51820
PersistentKeepalive = 25

Again, you can create the keys for the phone on the server (or anywhere else you have the wg command available). Use the same command as we did for creating the servers keys.

wg genkey | tee MOBILE_DEVICE_NAME.private.key | wg pubkey > MOBILE_DEVICE_NAME.public.key

Now create a [Peer] on the server using the mobile device’s public key, and insert the value from the private key in the above template, and save it. I suggest using a similar naming scheme as your keys.

Then run this command on the file to generate a QR code on the screen, and import it on your mobile device using it’s camera: qrencode -t ansiutf8 < MOBILE_DEVICE_NAME.conf

Run The Server

Starting the server once you’ve configured it is very easy:

sudo wg-quick up wg0s

Shutting it down is equally easy. Just substitute up for down in the above command.

To check the status of the server, run:

sudo wg show

Tips

The Address under the [Interface] header on your clients is the IP they should get on the network you’re connecting to.

The AllowedIPs under [Peer] on your clients needs to be the CIDR IP of the router (eg 10.0.1.1/24).

On-Demand on clients is a really cool feature that can automatically connect them to the VPN based on simple rules. I use it for connecting to my home VPN when I am not connected to my home WiFi.

Sources

Setup a VPN Server with WireGuard on Debian 9

Install Wireguard VPN on Debian 9 Server

WireGuard Setup Guide for iOS

WireGuard + UniFi