Setting up WireGuard VPN

How-to on setting up a WireGuard VPN and using clients

Posted by J├╝rgen on 12 December 2022

Intro

I don't trust other WiFi networks than my own. Period! Also I have some services running that don't necessarily need to be exposed to the Internet. So I have an always on VPN running on my phone. All my phone traffic passes through my home network. This VPN is WireGuard, a sturdy and secure VPN. I used to have an IKE L2TP VPN in place, but that had some issues with the Always On part silently losing it's connection. Probably a configuration error on my part, but this does WireGuard also address by being simple to use.

Pre-requisites

  • A static IP (Perhaps some dynamic DNS could work, but more on that later)
  • Some server able to run Docker containers
  • Android (I don't own an iPhone, it could still work)

Docker

Below the docker-compose.yaml I use on my Docker Swarm installation in order to start the WireGuard server. 51820 is the UPD port on which you can start your VPN, this port will need to be exposed to the outside world. The NET_ADMIN capability is added to provide more control over the IP stack. This is needed to create network bridges inside the container.


version: '3'
services:
  vpnserver:
    deploy:
      mode: replicated
      replicas: 1
      restart_policy:
        condition: any
        delay: 5s
        max_attempts: 3
        window: 5s
      resources:
        limits:
          cpus: '1.0'
          memory: 1024M
    environment:
      - reschedule=on-node-failure
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - PEERS=10
      - LOG_CONFS=true
    image: lscr.io/linuxserver/wireguard:latest
    ports:
      - "51820:51820/udp"
    volumes:
      - /etc/localtime:/etc/localtime
      - ./config:/config
    cap_add:
      - NET_ADMIN

Setup WireGuard on Android

Install WireGuard from F-Droid, Play Store or your store of preference, after that, you can start setting up the VPN.

This is quite straight-forward; After you've started the VPN service, you can check to container logs to reveal some neat ASCII QR codes of which one you can scan with your phone. Note that when you restart your container, due to the config retention, you might lose your logs containing the QR codes. You can open a shell into the container and execute a /app/show-peer <peer number> to generate the QR code.

When you've scanned the QR code and the WireGuard client is configured then you can check the Always-on VPN option in your VPN config, and optionally you can the check the Block connections without VPN.

A note on dynamic DNS

Technically it should be possible to use a dynamic DNS service when you have a non-static IP, just make sure that you do not enable Block connections without VPN since that would mean that when you get disconnected from your VPN during an IP switch, you'll be completely offline and will never receive the updated DNS record needed to reconnect.

Another note on server availability over VPN

If you have some streaming devices in your home, like a chromecast, you'll notice poor performance or that the device can't even be detected, this is because even on your network, traffic is being routed over the VPN. In the case of poor performance you'll want to check the Exclude private IPs checkbox and separately add servers you want to be able to access over the VPN. For instance, if you have a web server (eg. 192.168.1.1) you want to access through VPN you add 192.168.1.1/32 to the (extensive) list of Allowed IP's.

Why is that list that extensive? Well, when you check that private IPs should be excluded, rather than excluding those IPs, every non-private range gets included.

Setup WireGuard on debian-based Linux

Install WireGuard:


sudo apt install -y wireguard wireguard-tools

On your Docker host which has the WireGuard server running, go to the config volume directory and copy the contents of one of the unused ./peer?/peer?.conf as /etc/wireguard/wg0 on your Linux client.

Starting the VPN can be done using:


sudo systemctl start wg-quick@wg0.service

Note: Some distributions have resolvectl instead of resolvconf. These are compatible, by executing ln -s /usr/bin/resolvectl /usr/local/bin/resolvconf the resolvconf requirement of wg-quick can be satisfied.

And finally, should you want to, you can start the VPN on start using:


sudo systemctl enable wg-quick@wg0.service