WireGuard DNS Configuration for Systemd
The DNS
setting of a standard WireGuard config file can be used to specify the DNS resolvers to query when the WireGuard interface is up, as well as the domains to search for unqualified hostnames. On Linux, the wg-quick program expects to be able to use the traditional resolvconf utility for this; however, most modern Linux distributions use systemd-resolved instead.
On distros that use systemd-resolved, you might see an error message like the following if you try to start up a WireGuard interface with wg-quick (or your WireGuard DNS settings might just be silently ignored, if the distro has an partial resolvconf stub installed instead):
resolvconf: command not found
Fortunately, it’s easy to configure wg-quick to apply your desired DNS settings to systemd-resolved directly, using a custom PostUp
command. This article will show you how:
Check for systemd-resolved
To check if your system is using systemd-resolved, inspect the contents of the /etc/resolv.conf
file. If the file starts with a line like the following, it’s using systemd-resolved:
$ cat /etc/resolv.conf
# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).
...
Override DNS for Specific Domains
If you use WireGuard to connect to an internal network, and that network includes a custom DNS resolver which resolves an internal domain name for hosts on that network, you can configure systemd-resolved to use that resolver for that particular domain name.
For example, if the resolver’s IP address is 10.0.0.2
, and the domain name is internal.example.com
, you might normally use the following DNS
settting:
DNS = 10.0.0.2, internal.example.com
With systemd-resolved, however, instead of using the DNS
setting, add the following PostUp
command to the [Interface]
section of your WireGuard config file:
PostUp = resolvectl dns %i 10.0.0.2; resolvectl domain %i ~internal.example.com
When you start your WireGuard interface up, this command will direct systemd-resolved to use the DNS server at 10.0.0.2
to resolve queries for the internal.example.com
domain name (such as queries for mail.internal.example.com
or chat.internal.example.com
etc).
If you also want to use internal.example.com
as a search domain (so that systemd-resolved will attempt to resolve queries for unqualified hostnames like mail
or chat
as if they were fully-qualified hostnames like mail.internal.example.com
or chat.internal.example.com
) remove the tilde (~
) from the front of internal.example.com
:
PostUp = resolvectl dns %i 10.0.0.2; resolvectl domain %i internal.example.com
If you have multiple custom domains (like example.com
, example.net
, and example.org
) that you want your internal resolver to resolve, specify them together in the same command, separated by whitespace:
PostUp = resolvectl dns %i 10.0.0.2; resolvectl domain %i ~example.com ~example.net ~example.org
Override DNS Globally
If you use WireGuard to connect to the Internet — or just to a network with a recursive DNS resolver that you prefer to use over your default resolver — you can configure systemd-resolved to use that resolver globally.
For example, if you wanted to use the Quad9 resolver for all Internet DNS queries when your WireGuard interface is up, you’d normally use the following DNS
setting:
DNS = 9.9.9.9, 149.112.112.112
With systemd-resolved, however, instead of using that DNS
setting, add the following PostUp
command to the [Interface]
section of your WireGuard config file:
PostUp = resolvectl dns %i 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net; resolvectl domain %i ~.
When you start your WireGuard interface up, this command will direct systemd-resolved to use the DNS server at 9.9.9.9
(or at 149.112.112.112
, if 9.9.9.9
is not available) to resolve queries for any domain name.
Avoid DNS Settings From DHCP
If you also use Network Manager, and you connect to networks that you don’t trust, you may also want to adjust Network Manager’s settings for those networks to prevent them from changing your DNS settings (which they may do via DHCP, the Dynamic Host Configuration Protocol).
For example, to modify Network Manager’s settings for your saved Rando Coffee Shop
connection to ignore any DNS settings it may push to you over DHCP, run this command:
nmcli connection modify 'Rando Coffee Shop' ipv4.ignore-auto-dns yes ipv6.ignore-auto-dns yes
Alternately, you can use the Network Manager UI for this: edit your Rando Coffee Shop
connection, switch to its IPv4 Settings
tab, and select the Automatic (DHCP) addresses only
method:
If you don’t allow DNS to be configured via DHCP, and you don’t configure any DNS servers through Network Manager, systemd-resolved will use the DNS resolvers configured in its base DNS
setting from the /etc/systemd/resolved.conf
file. There you can configure your preferred DNS servers; for example, to use Quad9:
# /etc/systemd/resolved.conf
DNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net
DNSOverTLS=opportunistic
This base DNS
setting will be overridden by any per-connection customizations you make with the PostUp
commands above (or any per-connections settings you configure via Network Manager).