Ubuntu 16.04 Leaks DNS Requests With OpenVPN Tunnels and IPv6

Recently I noticed, much to my dismay, that when using OpenVPN over network interfaces for which IPv4 and IPv6 is configured, Ubuntu 16.04 doesn’t configure DNS lookups correctly. As a result, DNS requests that should only be sent inside the OpenVPN tunnel are sent on the outside network interface thus massively compromising security and privacy. Read on for the details and a temporary fix.

In Ubuntu 16.04 when I start an OpenVPN tunnel via the NetworkManager GUI over an outer interface for which only IPv4 is configured, only the DNS server that is reachable through the new tun0 interface is configured by network manager. This is correct, no DNS leakage outside the tunnel occurs, everything is fine!

However, if I start OpenVPN and use an outer interface (over which tun0 flows) that has both IPv4 and IPv6 configured, the NetworkManager configures a DNS server of the outer interface and a DNS server of the tun0 interface to dnsmasq/resolvconf. This leads to DNS leakage outside tun0 which is a massive privacy and security issue as DNS queries are done inside and outside the tunnel.

I’ve reported the issue a few days ago on Ubuntu Launchpad but so far there hasn’t been a lot of activity to find and fix the bug.

So until they do fix this here’s my quick and dirty hack to live with it: As I have no idea how to change the way NetworkManager configures the DNS resolver after a network interfaces comes up or goes down, I decided to take matters into my own hands and write two scripts to change /etc/resolv.conf when tun0 comes up or goes down. When the OpenVPN interface comes up, I replace the content of the file by a hard coded DNS server IP address of which I know that it is routed through the OpenVPN tunnel:

sudo -s
cd /etc/network/if-up.d/
nano 999martin

--->

#!/bin/sh

logger "martin - checking if new interface is a VPN tunnel"

if [ $IFACE = "tun0" ];
then
    logger "martin - new interface is tun0 - writing a new resolv.conf file"
    echo "nameserver 10.8.0.1" > /etc/resolv.conf
fi

When it goes down I swap the original resolv.conf back into position that points to localhost:

cd if-post-down.d/
nano 999martin 

-->
#!/bin/sh

logger "martin - checking if removed interface is a VPN tunnel"

if [ $IFACE = "tun0" ];
then
    logger "martin - removed interface was tun0 - restoring original resolv.conf file"
    cp /etc/resolv.conf.standard /etc/resolv.conf
fi

Don’t forget to perform a chmod +x to both script files to make them executable and to copy /etc/resolv.conf to /etc/resolv.conf.standard. The ‘logger’ command outputs my debug text to the system log system so it is easy to see if the fix works.

Yes, this is far from pretty but I can’t wait until someone fixed this upstream