How to Install Wireguard and set up a ptp tunnel on Ubuntu and others

Disclaimer

IMPORTANT: I have used Ubuntu 16.04 when writing this tutorial, your mileage may vary depending on the OS, distribution and other variables.

Objective

After having followed this tutorial, you will have a point-to-point tunnel established using Wireguard.

Prerequisites

In order to follow this tutorial, you are in need of two machines. Only one of them necessarily has the need to have a dedicated IP/ forwarded ports on which the Wireguard server can listen. Make sure you use machines where you have control over the kernel, as we need to compile custom kernel modules.

Installing Wireguard

This step really depends on your OS, but it really boils down to the need for two packages to be installed: wireguard-dkms and wireguard-tools. In my case, I am using Ubuntu, where we can use PPA.

sudo add-apt-repository ppa:wireguard/wireguard
sudo apt-get update
sudo apt-get install wireguard-dkms wireguard-tools

In case the latter command outputs any message stating it is unable to compile the kernel modules, run the following command to install the headers Wireguard requires.

apt-get install linux-headers-$(uname -r)

Patching WG-Quick

Wireguard has a certain function built-in for routing, which messes up your routing table. We want to remove this:
Open the wg-quick script:

nano `which wg-quick`

Look for the add_route() function (Hint: Ctrl-W in nano).
Replace the full block with the following:

add_route() {
        return 0
}

Use Ctrl-O and Ctrl-X to save the file and exit out of nano.

Configuring Wireguard

Run the following command on both servers:

(umask 077 && printf "[Interface]\nPrivateKey = " | tee /etc/wireguard/TUNNEL.conf > /dev/null)
wg genkey | tee -a /etc/wireguard/TUNNEL.conf | wg pubkey | tee /etc/wireguard/publickey

This command will output a key in the following forms.
Server A: V8R/WruSAl3cwmx6uvmqB1Zewm7ltjds8vGxatikhSA=
Server B: t9EDNLIDhek3RulvNHKqh4UeZMkjYfjQsCp5BQqxNUw=
Make sure to note this down, as we need this public key on the other server.

After having run the beforementioned command on both servers, open the Wireguard config file, and add the following lines:
Server A:

ListenPort = 7777
Address = 10.0.0.1/30, fe80::a/64

[Peer]
PublicKey = t9EDNLIDhek3RulvNHKqh4UeZMkjYfjQsCp5BQqxNUw=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 8.8.8.8:7777
PersistentKeepalive = 21

Server B:

ListenPort = 7777
Address = 10.0.0.2/30, fe80::b/64

[Peer]
PublicKey = V8R/WruSAl3cwmx6uvmqB1Zewm7ltjds8vGxatikhSA=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 9.9.9.9:7777
PersistentKeepalive = 21

You should notice that we have exchanged public keys, the public key of server A is in the [Peer] section of the configuration of server B and the other way around.
In the event where one of these machines has no public IP / forwarded ports, you can simply remove the Endpoint line in the configuration on the other end. When possible I recommend configuring an Endpoint at both ends.

Getting the tunnel up

After having editted both configuration files, it’s time to get the tunnel up.
Run the next command on both servers:

systemctl start wg-quick@TUNNEL

Let’s test whether we can ping over the tunnel.

root@server-a:~# ping 10.0.0.2 -c 10
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=8.93 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=9.09 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=9.18 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=8.95 ms
64 bytes from 10.0.0.2: icmp_seq=5 ttl=64 time=9.10 ms
64 bytes from 10.0.0.2: icmp_seq=6 ttl=64 time=8.92 ms
64 bytes from 10.0.0.2: icmp_seq=7 ttl=64 time=9.15 ms
64 bytes from 10.0.0.2: icmp_seq=8 ttl=64 time=9.13 ms
64 bytes from 10.0.0.2: icmp_seq=9 ttl=64 time=9.15 ms
64 bytes from 10.0.0.2: icmp_seq=10 ttl=64 time=9.15 ms

If you see similar results, we’re good and it’s time to make the tunnel last after a reboot, using the next command:

systemctl enable wg-quick@TUNNEL

Looking back

We have established a tunnel using Wireguard. Wireguard is a rather lightweight piece of software while using modern cryptography and enabling great flexibility.