Table of Contents
Wireguard is the latest version of VPN that is available in the Linux kernel, its fast and (in theory) simple to configure.
The server and client both need a private/public key pair. They exchange public keys and optionally the server can generate a pre-shared key. The IP addresses are configured for each peer and that is it. As its not something I do often it usually takes me a few tries but I've hopefully got it working with these notes.
Server Configuration
Install wireguard-tools
- snippet.bash
# Arch pacman -Syu wireguard-tools # Gentoo emerge -av wiregoard-tools
Server Configuration
Generate key pairs on the server for each client (<device>
represents a unique name for the device you want to add so they don't over-write each other)…
- snippet.bash
(umask 077 && wg genkey > wg-server-private.key) wg pubkey < <device>_private.key > wg-server-client1-public.key # All in one (umask 077 && wg genkey | tee wg-server-private.key | wg pubkey > wg-server-client1-public.key) # Preshared key wg genpsk > wg-server-client1-psk
NB If you are returning to your server at a later date to create more keys for new clients you will already have generated your servers private key and need to use that to generate the public keys that will be shared with new clients. You can do that using the following line…
- snippet.bash
grep 'PrivateKey = ' /etc/wireguard/wg0.conf | tail -n 1 | sed -e 's/.* = //g' > wg pubkey > wg-server-client2-public.key
You will need your public and private keys, show them with cat wg-private.key
and cat wg-public.key
.
/etc/wireguard/wg0.conf
Now configure /etc/wireguard/wg0.conf
, note that you won't be able to add the PublicKey
under [Peer]
until you have generated it (see next section on Clients).
- snippet.bash
[Interface] Address = 10.200.200.1/24 ListenPort = 46879 PrivateKey = <wg-server-private.key> DNS = 1.1.1.1 # note - substitute eth0 in the following lines to match the Internet-facing interface # if the server is behind a router and receive traffic via NAT, this iptables rules are not needed PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] # PublicKey = <wg-client1-public.key> # Generated in the steps below PresharedKey = <wg-server-client1-psk> = AllowedIPs = 10.200.200.2/32
The server will have the address 10.200.200.1
listening on port 46879
. It uses Cloudflares 1.1.1.1
for DNS. There are hooks to modify the iptables
firewall rules after bringing the interface up and down. The client section requires you to complete the Client Configuration in a similar manner so that the public key from each client can be added to the server configuration.
Apply the configuration on the server and check it…
- snippet.bash
wg syncconf wg0 /etc/wireguard/wg0.conf wg show wg0
Client Configuration
Each client needs its own configuration and as mentioned its own pair of Private and Public keys.
Linux
Create private and public keys on your client…
- snippet.bash
$ (umask 077 && wg genkey > wg-client1-private.key) $ wg pubkey < wg-client-private.key > wg-client1-public.key
/etc/wireguard/wg0.conf
As with the server the clients needs a similar configuration
- snippet.bash
# define the local WireGuard interface (client) [Interface] Address 10.200.200.2/32 # Note that this matches the IP address it is assigned by the server PrivateKey = <wg-client1-private.key> DNS = 1.1.1.1 # define the remote WireGuard interface (server) [Peer] # contents of wg-public.key on the WireGuard server PublicKey = <wg-server-client1-public.key> # the IP address that are allowed to use the device from the client, this allows everything on both IPv4 and IPv6 devices AllowedIPs = 0.0.0.0/0, ::/0 # public IP address and port of the WireGuard server Endpoint = 12.34.56.78:46879 # This is the public, non-VPN IP address and port of the server
Android
Install the Wireguard Application, add a new interface manually and in theory you should be able to fill in all fields between the client (the phone) and the server and it will work.
In practice I found this didn't work, I repeatedly got Handshake did not complete after 5 seconds, retrying (try 2)
in the log files (available under settings for viewing and exporting). After checking the logs on the server (see section below on how to access these) I opted to create a configuration by hand on a computer, saving to file and then import it to the Android Wireguard client. The QR-code generator I used didn't seem to produce a valid code as the Wireguard App on the phone complained about Invalid parameter in config file
but loading the file itself did. Bingo!
Trouble-shooting
I had trouble getting my new phone to connect and found that on the server you can enable logging for debugging on the fly with.
- snippet.bash
modprobe wireguard echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control dmesg -wH
This showed that when I tried to connect…
- snippet.bash
[Feb25 06:54] wireguard: wg0: Invalid MAC of handshake, dropping packet from 88.97.78.71:44542 [ +5.049426] wireguard: wg0: Invalid MAC of handshake, dropping packet from 88.97.78.71:44542