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 thehome0
interface, and - associate the
home
domain to thehome0
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:
Thewg-quick(8)
manpage documents the DNS setting of the WireGuard interface which has the same purpose, but only works if you haveresolveconf
installed. Ubuntu systems by default don’t, and rely onsystemd-resolved
instead.
Adding another peer
To add another peer to an existing WireGuard setup, we have to:
- Generate a new keypair for the new peer
- Create a new
[Peer]
section on the “other side” of the WireGuard setup - 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, thesystemctl 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 thatwg-quick
does. Depending on your setup, you might need a full restart so thatwg-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!