sylvaindurand.org

Setting up a VPN with Wireguard

VPNs are very practical tools that allow you to secure the connection between two machines, to secure your connection to the Internet when you connect in public places or to bypass geographical access restrictions. When you have a personal server and you don't want to expose it to the public, a VPN is ideal to reduce the attack surface and access your tools.

For a long time, I used OpenVPN, which was quite heavy to configure and set up, and not always easy to maintain... until the arrival of Wireguard.

Wireguard is a more recent tool, completely open source, very light, simple to set up, which claims to comply with the latest encryption standards and is particularly efficient. It has recently been integrated into the Linux kernel and has clients for Windows, Mac, iOS or Android.

For this example, we will connect a "server" with a "client". In reality, all the devices connected through Wireguard are perfectly equivalent, and it is possible to configure the data transfers as you wish.

Installation

Under Arch Linux, Wireguard is already integrated in the Linux kernel, but installing `wireguard-tools` allows to get simple configuration tools.

Keys creation

To communicate, each device will need a public key and an associated private key. The public key must be shared with each machine with which we wish to communicate, and we must benefit in return from their public keys.

Thus, for this example, we will create a private key `wg.key` with the right permissions, and the corresponding public key `wg.pub`:

cd .ssh
(umask 0077; wg genkey > server.key)
wg pubkey < server.key > server.pub

We do the same by creating a set of keys for the client:

cd .ssh
(umask 0077; wg genkey > client.key)
wg pubkey < client.key > client.pub

Finally, although it is not mandatory, you can create pre-shared keys that will be used on both devices to strengthen security:

(umask 0077; wg genpsk > preshared.pub)

Server configuration

The configuration is done in the `/etc/wireguard/wg0.conf` file where we will start by declaring our interface. Specify the contents of the private key `server.key` in `PrivateKey` and the port in `ListenPort`. The `PostUp` and `PostDown` lines designate the commands to be run when activating or deactivating the Wireguard network respectively. These indicate that we have to reroute everything that is requested from or to our client. Your server will have the address `10.0.0.1` on the Wireguard network.

[Interface]
PrivateKey = ...
Address = 10.0.0.1/24
ListenPort = 51871
PostUp = sysctl -w net.ipv4.ip_forward=1 ; iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o enp3s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o enp3s0 -j MASQUERADE

The next step is to specify which clients can connect to the VPN. For each of them, we add in the same file a peer section. Specify the contents of the client's public key `client.pub` in `PublicKey`, and always the pre-shared key in `PreSharedKey`. Your client will have the address `10.0.0.2` on the Wireguard network.

[Peer]
PublicKey = ...
PreSharedKey = ...
AllowedIPs = 10.0.0.2/32

Client configuration

On the client side, the configuration will also written in `/etc/wireguard/wg0.conf`. This time we give it the address `10.0.0.2` and we indicate the private key contained in `client.key`:

[Interface]
PrivateKey = ...
Address = 10.0.0.2/24
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o enp3s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o enp3s0 -j MASQUERADE

It is also given the server as peer, the server's public key contained in `server.pub`, and the pre-shared key. The `EndPoint` field must indicate the domain name or external IP where the server will be reachable, as well as the port (which must, of course, be externally accessible and routed if necessary). The `PersistentKeepalive` field is not mandatory but allows to solve connectivity problems when connecting through a NAT router.

[Peer]
PublicKey = ...
PreSharedKey = ...
AllowedIPs = 0.0.0.0/0
Endpoint = vpn.domain.tld:51871
PersistentKeepalive = 25

The `AllowedIPs` field indicates which IPs will be passed through the VPN. With `0.0.0.0/0`, all client IPs will be passed through the VPN. If you want to limit the use of the VPN to local services on the server (e.g. self-hosted apps), you can use `10.0.0.0/24` for example.

Activation

To start the VPN, you can run `wg-quick up wg0` with root rights, both on the client and on the server. To turn it off, a simple `wg-quick down wg0` is enough. It is also possible to use a service to start the VPN automatically at startup:

sudo systemctl enable --now wg-quick@wg0

Wireguard on your phone

Wireguard has the advantage of being easily available on both iOS and Android, allowing you to access your local network and applications from any wifi network or with cellular data.

In both cases, the application allows you to enter all the fields in the same way as `wg0.conf`, but of course, entering the certificates by hand would be very tedious.

Fortunately, it is also possible to proceed with a QR code!

Create a public key and a shared key for your phone, as described above, as well as a pre-shared key if necessary. Declare them as a peer on your server, and create a `wg0-phone.conf` file on your computer.

Once this is done, we can then use `qrencode` to transform this configuration file into a QR code directly readable (and importable) by the phone, which will be displayed in the terminal:

qrencode -t ansiutf8 < wg0-iphone.conf
█████████████████████████████████████████████████████
█████████████████████████████████████████████████████
████ ▄▄▄▄▄ █  ▄██▄▄▄ ▀▄  ▄▄█ ▄ █▀▄▄ ▀▀█▀▄█ ▄▄▄▄▄ ████
████ █   █ █  █▀ █▀▀▀▀▀▄█ █  ▄  █▀▄▀▀██ ▀█ █   █ ████
████ █▄▄▄█ █▀ ▄██ ▀▄▀▀ ▀ ▄▄▄ ▀ ▀▀█▀█▄█▄▄▄█ █▄▄▄█ ████
████▄▄▄▄▄▄▄█▄▀ █▄▀▄█▄█ █ █▄█ ▀▄▀▄█▄▀ █ █▄█▄▄▄▄▄▄▄████
████  █▀▄ ▄▀█  █▀▄ ▄███▄▄  ▄▄▀ █▄  ▀  █▀▀▀▀ █▄ ▄▄████
████ ▄▄▄█▄▄▄█▄█ ▄█ ▀ █▄█  ▄██▀▀  █ ▄▀▄ ▄██▀▀▀██▄▀████
████▄█▀  ▀▄▀  █▄▄▀▄███▄▄▄▀ ██▄▀█▀█▀ ▀█▄█ ▀ █▄▀ ▀█████
████▀▄▄█▀█▄ █▀  ▀▄  █▀██  ▄█▀█  ▀ ██  ▄▄▄█ █▀▄█▀ ████
████ ▀▀█▀█▄▀ █▄  ▀▀▀▀█ ▄█▀ █▀▄  █ ▀▀  ▄ ▀▄▀ ███▀▄████
█████▀█▄▄▀▄▄▀ ▀   ▄▄█▀▄▀▀ ▄   ▀▀ █ ▄█▄▀▀█▄▀▀▄ █ █████
████ █▀▀ ▄▄▄ ▄▄▄█  ▀█▄▄▄ ▄▄▄ ▀  █ ▄█  ▀█ ▄▄▄ ▀▀ ▀████
████▄ █  █▄█   ▀ ▀█▀ ▀▀  █▄█ █▄   ▄█▀▄   █▄█ ████████
██████ █▄ ▄  █▄▀▄▄ ▄█▄   ▄  ▄ ▄▀█▄▀█  ██▄ ▄▄  █▀ ████
████ ██▄▄█▄▄▄▀█▄ ▄▄▀ ▄▄▀█▀█▄█  ▀▄▄ ███▀▄▀██▄▄▀▀ ▀████
██████  ▄ ▄█▄ ▄▀▀ ▄█ ▄▄█ ██▄ ▄▀▀ ▄  ▄█▄▀▄  ▀▄█  █████
████ ▄▄ █▀▄▄▄▀ ▀▀▄ █▀▀▀█ ▀█▄▀▀ █  ▄▄█ ▄▄█ ▀▀▀▄▄▀▀████
████ ▀█   ▄██▀█▄ ▀▀▀▀██▀▄▄█ ▄ ▄▄▀█ ▀▄▄█ █▀█▀ ▀██▀████
█████▀▀▀ █▄▄▀ ▀▀█▄ ▄█▀▄█▄▀▀▄█▀▀▀ █ █ ▄▀▄ ▄▀▄█▀▀▄▀████
████▄██▄▄█▄▄▀ ██▄▀ ████  ▄▄▄  ███ ▄█▀ ▀▀ ▄▄▄ ▀  ▄████
████ ▄▄▄▄▄ █▀██▄▀▀█▄ ▄██ █▄█ █▀▀▄▄▀▄█    █▄█ ▄▄█▄████
████ █   █ █▄█ ▀▄▄ ██▄ █ ▄▄  ██▄█▄ ▄ ██▄   ▄ ▀█▀█████
████ █▄▄▄█ █▀▄ ▄ ▄▄  █ ▄  █ ▀▀   ▄ ▄▄█▀ █▀▄█ █▀██████
████▄▄▄▄▄▄▄█▄▄▄██▄██▄█▄▄█▄▄██▄▄█▄██▄▄█▄▄▄▄██████▄████
█████████████████████████████████████████████████████
█████████████████████████████████████████████████████