Watch out for DNS leak when using VPN and systemd-resolved

Posted on August 27, 2021

Your VPN connection may not be as safe as you think

Many VPN clients in Linux modify the nameserver record in /etc/resolv.conf to its own DNS server when initiating connection. This will not work on distros using systemd-resolved as DNS resolver. Your DNS queries will go to your normal DNS server which will know every site you visit.

You can read this blogpost for a more in-depth understanding of how systemd-resolved manages DNS queries. In short, /etc/resolv.conf is managed by systemd-resolved and should not be edited manually. Instead, you can configure the DNS server for a particular NIC by resolvectl dns [NIC_NAME] [DNS_IP] command.

Unfortunately for ProtonVpn that I am currently using, there are currently no clients designed with systemd-resolved in mind. Neither the official client nor the community-maintained cli-client handles DNS correctly (there is a PR for the community client though).

Split DNS is useful but may have security implications

As far as DNS is concerned, you can either force a global DNS server or use a different one per link.

The former is easier to manage but cause problems when using VPNs or connecting to public WIFI hotspots. The latter requires more configuration and may surprise you when you find that you are actually using another DNS server then the one you want.

Global DNS

To force a global DNS regardless of network connections. You can your systemd-resolved configuration file and specify global DNS servers and let it take precedence over NIC-specific settings (by setting Domains=~.). Without Domains=~. the global setting will be considered a fallback instead.

[Resolve]
DNS=XX.XX.XX.XX YY.YY.YY.YY
Domains=~.

Beware that there is no way to change the global setting on the fly using the resolvectl command. You will have to edit the config file and restart systemd-resolved for changes to take effect.

Split DNS

Split DNS is “the correct way” to use systemd-resolved. You can specify a global (fallback) DNS (without Domains=~.) and disable link-specific DNS settings in NetworkManager settings for connections that you want your global setting to take effect.

Caveat: in NetworkManager, DNS by DHCP is enabled by default. I would advise you to check your DNS resolver configuration using resolvectl status everytime you connect to a new network as the DHCP server might give you a DNS server that you do not trust.