How to fix OpenVPN DNS Leak on Ubuntu

By | May 19, 2023

DNS Leak

DNS Leak is commonly seen in vpn connections, when all the http traffic goes through the vpn tunnel, however the dns queries go directly to system/isp dns servers bypassing the vpn tunnel, which breaks the privacy protection offered by the vpn.

Unless dns leaks are fixed, you are not fully privacy guarded in the vpn connection (even though you might think you are). The best thing after setting up a vpn is to quickly test and check for leaks and fix them on time.

How to test for DNS Leaks in VPN

You can use the following websites to test for dns leak on your system:

https://ipleak.net/
https://www.dnsleaktest.com/

If you see your isp/system dns servers being used, then there is a dns leak. If you see some other dns server (those provided by your vpn provider) then your dns queries are being tunnelled through vpn and you are protected.

OpenVPN has known issues of dns leaks on linux systems like Ubuntu and in this article we take a look at various methods to fix it. I recently setup surfshark vpn on my ubuntu system using the manual openvpn method and noticed that dns leaks were happening all the time.

OpenVPN DNS Leak Fix

We shall take a look at 3 simple techniques to try and fix the dns leak. If your linux system is using systemd-resolved like latest Ubuntu, then you probably need to use the last Method 3.

These methods should work on all Ubuntu and Debian based distros like Linux Mint, Elementary OS, Pop OS etc.

Method 1

The first method is to use /etc/openvpn/update-resolv-conf script.

OpenVPN ships with a script named "update-resolv-conf" which is supposed to over-write the nameservers in /etc/resolv.conf when it connects to a vpn, and restore them back when the vpn connection is closed.

It can typically be used like this:

$ sudo openvpn --config ovpn/us-kan.prod.surfshark.com_udp.ovpn --auth-user-pass pass.txt --verb 3 --script-security 2 --up /etc/openvpn/update-resolv-conf --down /etc/openvpn/update-resolv-conf --down-pre

However on many Ubuntu systems, the above command does not work. This happens specially when the system is using systemd-resolved service.

Check systemd-resolved dns configuration with the resolvectl status command:

$ resolvectl status
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub

Link 2 (enp0s3)
    Current Scopes: DNS
         Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 8.8.8.8
       DNS Servers: 8.8.8.8 8.8.4.4 192.168.1.1

Link 85 (tun0)
Current Scopes: DNS
     Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
   DNS Servers: 162.252.172.57 149.154.159.92
$

On Fedora you can also use the systemd-resolve --status command. It is not available on Ubuntu however.

In the above example both ethernet interface (enp0s3) and the vpn interface (tun0) have DNS scopes available and each is configured with their own dns servers.

Issues with systemd-resolved
If your system is using systemd-resolved, then the above command will not change the /etc/resolv.conf file. You can verify it by viewing the file contents after running the above command.

$ cat /etc/resolv.conf 
# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).
# Do not edit.
#
# This file might be symlinked as /etc/resolv.conf. If you're looking at
# /etc/resolv.conf and seeing this text, you have followed the symlink.
#
# This is a dynamic resolv.conf file for connecting local clients to the
# internal DNS stub resolver of systemd-resolved. This file lists all
# configured search domains.
#
# Run "resolvectl status" to see details about the uplink DNS servers
# currently in use.
#
# Third party programs should typically not access this file directly, but only
# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a
# different way, replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 127.0.0.53
options edns0 trust-ad
search .
$

In the above example the nameserver still points to 127.0.0.53 which is the internal dns server managed by systemd-resolved.

When using systemd-resolved the /etc/resolv.conf file is a symlink to another file.

$ ls /etc/resolv.conf  -la
lrwxrwxrwx 1 root root 39 Oct 23 11:24 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

There are known issues in systemd (check here and here and here) due to which the background services use the default network interface for dns queries which causes the dns queries to go directly to the dns server instead of via vpn tunnel.

The update-resolv-conf script invokes the "/sbin/resolvconf" script to make changes to dns servers. However in the presence of systemd-resolved the /sbin/resolvconf script points to resolvectl which works with systemd-resolved.service

$ ls -la /sbin/resolvconf 
lrwxrwxrwx 1 root root 19 Jan  5 17:25 /sbin/resolvconf -> /usr/bin/resolvectl
$

Hence the dns changes will ultimately depend on systemd-resolved to take effect properly.

Method 2: openvpn-systemd-resolved

There is a little trick to fix the above problem and prevent dns leaks completely. First install the following package

sudo apt-get install openvpn-systemd-resolved

Now connect to vpn server with the following command

$ sudo openvpn --config ovpn/us-kan.prod.surfshark.com_udp.ovpn --auth-user-pass pass.txt --verb 3 --script-security 2 --up /etc/openvpn/update-systemd-resolved --down /etc/openvpn/update-systemd-resolved --down-pre

Method 3 - Force DNS servers

This particular solution has been highlighted on systemd-resolved site as well. It uses the DOMAIN-ROUTE directive to force all dns queries to be routed through a specific interface.

Adding the following option the configuration file seems to solve the problem.

dhcp-option DOMAIN-ROUTE .
$ sudo openvpn --config ovpn/us-kan.prod.surfshark.com_udp.ovpn --auth-user-pass pass.txt --verb 3 --script-security 2 --up /etc/openvpn/update-systemd-resolved --down /etc/openvpn/update-systemd-resolved --down-pre --dhcp-option DOMAIN-ROUTE .

Now if you check systemd dns policy, it should appear something like this:

$ resolvectl status
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub

Link 2 (enp0s3)
    Current Scopes: DNS
         Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 8.8.8.8
       DNS Servers: 8.8.8.8 8.8.4.4 192.168.1.1

Link 87 (tun0)
Current Scopes: DNS
     Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
   DNS Servers: 162.252.172.57 149.154.159.92
    DNS Domain: ~.
$

Note the last line DNS Domain: ~.
It is this line that forces systemd to route all dns queries through the openvpn interface tun0, thereby eliminating dns leaks.

Shorter version of the command:

$ resolvectl dns
Global:
Link 2 (enp0s3): 8.8.8.8 8.8.4.4 192.168.1.1
Link 89 (tun0): 162.252.172.57 149.154.159.92
$

The above output shows each interface with its own configured dns server.

$ resolvectl domain
Global:
Link 2 (enp0s3):
Link 89 (tun0): ~.
$

The above output shows domains assigned to each interface for dns resolution.

Note that /etc/resolv.conf will continue to show the same nameserver systemd-resolved nameserver 127.0.0.53. This implies that dns queries will still be sent to systemd-resolved. However systemd-resolvd would now use dns servers via the vpn tunnel and now the ethernet interface which is directly connected to internet.

This stops dns leaks.

Alternative approach

The dns leak if caused due to systemd-resolved, needs to be fixed using the above shown methods. However, there are other possible solutions as well.

An alternative would be to disable systemd-resolve and manually specify dns servers in /etc/resolv.conf or through Network Manager gui utility. These will then be over-written by /etc/openvpn/update-resolv-conf script, thereby stopping dns leaks.

Here is a github gist and askubuntu discussion showing simple steps on how to do it.

Links and Resources

https://github.com/alfredopalhares/openvpn-update-resolv-conf
https://unix.stackexchange.com/questions/328131/how-to-troubleshoot-dns-with-systemd-resolved
https://askubuntu.com/questions/1116732/how-do-i-list-dns-server-order-in-systemd-resolve
https://unix.stackexchange.com/questions/434916/how-to-fix-openvpn-dns-leak

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

Leave a Reply

Your email address will not be published. Required fields are marked *