Common tasks in WireGuard VPN

Note:
This documentation has moved to a new home! Please update your bookmarks to the new URL for the up-to-date version of this page.

Here are some common tasks and other useful tips that can help you in your WireGuard deployment.

Controlling the WireGuard interface with systemd

The wg-quick tool is a simple way to bring the WireGuard interface up and down. That control is also exposed via a systemd service, which means the standard systemctl tool can be used.

Probably the greatest benefit of this is that it gives you the ability to configure the interface to be brought up automatically on system boot. For example, to configure the wg0 interface to be brought up at boot, run the following command:

$ sudo systemctl enable wg-quick@wg0

The name of the systemd service follows the WireGuard interface name, and multiple such services can be enabled/started at the same time. You can also use the systemctl status, start, stop, reload and restart commands to control the WireGuard interface and query its status:

$ sudo systemctl reload wg-quick@wg0

The reload action does exactly what we expect: it reloads the configuration of the interface without disrupting existing WireGuard tunnels. To add or remove peers, reload is sufficient, but if wg-quick options, such as PostUp, Address, or similar are changed, then a restart is needed.

DNS resolving

Let’s say when you are inside the home network (literally – at home), you can connect to your other systems via DNS names, because your router at 10.10.10.1 can act as an internal DNS server. It would be nice to have this capability also when connected via the WireGuard VPN.

To do that, we can add a PostUp command to the WireGuard configuration to run a command for us right after the VPN is established. This command can be anything you would run in a shell (as root). We can use that to adjust the DNS resolver configuration of the laptop that is remotely connected to the home network.

For example, if we have a WireGuard setup as follows:

  • home0 WireGuard interface.
  • .home DNS domain for the remote network.
  • 10.10.10.1/24 is the DNS server for the .home domain, reachable after the VPN is established.

We can add this PostUp command to the home0.conf configuration file to have our systemd-based resolver use 10.10.10.1 as the DNS server for any queries for the .home domain:

[Interface]
...
PostUp = resolvectl dns %i 10.10.10.1; resolvectl domain %i \~home

For PostUp (and PostDown – see the wg-quick(8) manpage for details), the %i text is replaced with the WireGuard interface name. In this case, that would be home0.

These two resolvectl commands tell the local systemd-resolved resolver to:

  • associate the DNS server at 10.10.10.1 to the home0 interface, and
  • associate the home domain to the home0 interface.

When you bring the home0 WireGuard interface up again, it will run the resolvectl commands:

$ sudo wg-quick up home0
[#] ip link add home0 type wireguard
[#] wg setconf home0 /dev/fd/63
[#] ip -4 address add 10.10.11.2/24 dev home0
[#] ip link set mtu 1420 up dev home0
[#] ip -4 route add 10.10.10.0/24 dev home0
[#] resolvectl dns home0 10.10.10.1; resolvectl domain home0 \~home

You can verify that it worked by pinging some hostname in your home network, or checking the DNS resolution status for the home0 interface:

$ resolvectl status home0
Link 26 (home0)
    Current Scopes: DNS
         Protocols: -DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 10.10.10.1
       DNS Servers: 10.10.10.1
        DNS Domain: ~home

If you are using systemctl to control the WireGuard interface, this is the type of change (adding or changing PostUp) where the reload action won’t be enough, and you actually need to issue a restart.

Note:
The wg-quick(8) manpage documents the DNS setting of the WireGuard interface which has the same purpose, but only works if you have resolveconf installed. Ubuntu systems by default don’t, and rely on systemd-resolved instead.

Adding another peer

To add another peer to an existing WireGuard setup, we have to:

  1. Generate a new keypair for the new peer
  2. Create a new [Peer] section on the “other side” of the WireGuard setup
  3. Pick a new IP for the new peer

Let’s call the new system ontheroad, and generate the keys for it:

$ umask 077
$ wg genkey > ontheroad-private.key
$ wg pubkey < ontheroad-private.key > ontheroad-public.key
$ ls -la ontheroad.*
-rw------- 1 ubuntu ubuntu 45 Aug 22 20:12 ontheroad-private.key
-rw------- 1 ubuntu ubuntu 45 Aug 22 20:13 ontheroad-public.key

As for its IP address, let’s pick 10.10.11.3/24 for it, which is the next one in the sequence from one of the previous examples in our WireGuard guide:

[Interface]
PrivateKey = <contents-of-ontheroad-private.key>
ListenPort = 51000
Address = 10.10.11.3/24

[Peer]
PublicKey = <contents-of-router-public.key>
Endpoint = <home-ppp0-IP-or-hostname>:51000
AllowedIPs = 10.10.11.0/24,10.10.10.0/24

The only difference between this config and one for an existing system in this same WireGuard setup will be PrivateKey and Address.

On the “other side”, we add the new [Peer] section to the existing config:

[Interface]
PrivateKey = <contents-of-router-private.key>
ListenPort = 51000
Address = 10.10.11.1/24

[Peer]
# laptop
PublicKey = <contents-of-laptop-public.key>
AllowedIPs = 10.10.11.2

[Peer]
# ontheroad
PublicKey = <contents-of-ontheroad-public.key>
AllowedIPs = 10.10.11.3

To update the interface with the new peer without disrupting existing connections, we use the reload action of the systemd unit:

$ systemctl reload wg-quick@wg0

Note:
For this case of a “server” or “VPN gateway”, where we are just adding another peer to an existing config, the systemctl reload action will work well enough to insert the new peer into the WireGuard configuration. However, it won’t create new routes, or do any of the other steps that wg-quick does. Depending on your setup, you might need a full restart so that wg-quick can fully do its job.

Adding a smartphone peer

WireGuard can be installed on many different platforms, and smartphones are included. The upstream installation page has links for Android and for iOS apps.

Such a mobile client can be configured more easily with the use of QR codes.

We start by creating the new peer’s config normally, as if it were any other system (generate keys, pick an IP address, etc). Then, to convert that configuration file to a QR code, install the qrencode package:

$ sudo apt install qrencode

Next, run the following command (assuming the config was written to phone.conf):

$ cat phone.conf | qrencode -t ansiutf8 

That will generate a QR code in the terminal, ready for scanning with the smartphone app. Note that there is no need for a graphical environment, and this command can be run remotely over SSH for example.

Note that you need to put the private key contents directly into that configuration file, and not use PostUp to load it from a separate file.

Important
Treat this QR code as a secret, as it contains the private key for the WireGuard interface!

This page was last modified 4 months ago. Help improve this document in the forum.