Geek Igor

OpenVPN and DNSes on Ubuntu

One of the VPNs I connect to sets the DNS server for the link. It is an OpenVPN with DNS option. The problem is that is doesn’t really work out of the box in Ubuntu (at least 18.04 and 18.10) — the VPN DNS is not consulted.

At the time of writing, I’m on 18.10, and I write it from that perspective. Ubuntu uses systemd-resolved service to provide a local DNS resolution. We need to “push” the VPN DNS address to this service. We can do it using jonathanio/update-systemd-resolved helper script.

systemd-resolved for DNS resolution

Consult its readme for details, but the steps are these:

git clone https://github.com/jonathanio/update-systemd-resolved.git
cd update-systemd-resolved
sudo make  # By default it installs the script to /etc/openvpn/scripts/update-systemd-resolved, so you need root permissions

Make sure the systemd-resolved is up and running (and autostarts).

systemctl enable systemd-resolved.service
systemctl start systemd-resolved.service

And that you have resolve somewhere in the hosts section of /etc/nssswitch.conf:

$ cat /etc/nsswitch.conf  | grep hosts
hosts:          files resolve mdns4_minimal [NOTFOUND=return] dns

Note This may not be needed as ubuntu moved to use /etc/resolv.conf and DNS stub directly; this may also result in a weird “bug” if your 18.10 is updated from a previous version. See the last section

Interlude: Why is this helper script needed?

OpenVPN (at least on Ubuntu 18.10), comes with its own helper script /etc/openvpn/update-resolv-conf, but the problem is that the script relies on resolvconf service which is replaced with systemd-resolved. This is why we need the helper.

.ovpn client configuration

Now that we have the helper script setup, we need to make the *.ovpn profiles us it. We can either edit the files directly and add the lines below to the *.ovpn:

script-security 2
up /etc/openvpn/scripts/update-systemd-resolved
down /etc/openvpn/scripts/update-systemd-resolved
down-pre

Or, if you don’t want to edit it, you can pass them to the openvpn call:

# Something like:
sudo openvpn --config ${NAME}.ovpn \
     --script-security 2 \
     --up /etc/openvpn/scripts/update-systemd-resolved \
     --down /etc/openvpn/scripts/update-systemd-resolved \
     --down-pre

Troubleshooting

You’ve followed all the steps, but the DNS is not being consulted.

Conflict between resolvconf and systemd-resolved

This is common if your Ubuntu 18.10 is migrated from the older version, or if you’ve installed resolvconf package manually.

If the systemd-resolved.service log reports something along the lines of

Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying

You can check it like that:

$ systemctl status systemd-resolved.service 
● systemd-resolved.service - Network Name Resolution
   Loaded: loaded (/lib/systemd/system/systemd-resolved.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2019-01-08 10:05:11 CET; 1 day 4h ago
     Docs: man:systemd-resolved.service(8)
           https://www.freedesktop.org/wiki/Software/systemd/resolved
           https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
           https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
 Main PID: 1087 (systemd-resolve)
   Status: "Processing requests..."
    Tasks: 1 (limit: 4915)
   Memory: 6.5M
   CGroup: /system.slice/systemd-resolved.service
           └─1087 /lib/systemd/systemd-resolved

Jan 09 13:13:27 p51 systemd-resolved[1087]: Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying 
Jan 09 13:13:55 p51 systemd-resolved[1087]: Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying 
# (...)

It may indicate a conflict between resolvconf and systemd-resolvd. Make sure that resolv.conf points to the systemd version:

$ ll /etc/resolv.conf 
lrwxrwxrwx 1 root root 32 Jan  9 13:40 /etc/resolv.conf -> /run/systemd/resolve/resolv.conf

If there is some other target of the symlink, then:

cd /etc
sudo rm resolv.conf
sudo ln -s /run/systemd/resolve/resolv.conf

Will do the trick.

See this ask ubuntu post which put me on the right track.