Okay so basically we are in 2018, Linux is soon turning 30, Debian (as long as CentOS, I heard you starting complaining at the back of the room :wink:) are recognized and almost fully-tested environments, but systemd is still a f*cking problem for our distributions and softwares.

Today problem : Using OpenVPN with DNS “PUSH-ed” by configuration, on recent systems.

Note to readers : This article could actually be set into many of the categories above.

IMPORTANT NOTE : If you are looking for a solution which doesn’t change the way the name resolution works on your system, you can directly close this tab and keep wandering the WEB few more hours.

Where we start from

Let’s say you are trying to connect to a service whose IP is supposed to be given by a DNS server, itself supposed to be PUSHed by your OpenVPN connection configuration while you opened the tunnel.

Where we arrive

If you have ended up there, not very far, isn’t it ?
It’s very likely that the PUSHed DNS has not been “pushed” at all, because of (guess what ?) : systemd.

The workaround

The workaround is not very a workaround, but mostly a long trip around the globe as it is actually a 400-line long script developed by a very experienced Linux user.

Why this long ? Because it uses a “new” API provided by systemd to interact with some of its services, via DBus :no_mouth:

So basically we set this script as a “hook” for OpenVPN, to tell it to set its PUSHed DNS(s) via the magnificent systemd-resolved binary (Yes… One of the 70 systemd provides, thank God).

You perfectly understood, this solution implies we move forward from resolvconf or any other resolution services, to systemd’s resolved.

How to make the workaround… Working around

Did you really think this could be easy as installing the thing and re-connect to the VPN (that’s what I’ve done) ? We are talking about systemd !
Don’t forget… Ever.

So let’s follow the guy’s README instructions, and set up everything !

Installation

# For Debian
apt install openvpn-systemd-resolved
# If you were using `resolvconf` for instance, it won't be necessary anymore
#apt purge resolvconf

# Generally
systemctl enable --now systemd-resolved.service

Configuration

Once it’s done, let’s begin the configuration tweaking.

First, open up /etc/nsswitch.conf, and replace the host line by :

hosts: files resolve dns myhostname

Next, open up /etc/resolv.conf and replace the content by :

search home
nameserver 127.0.0.53

:warning: If your system is running NetworkManager, you WILL experience issues sooner or later. Don’t forget to follow the procedure below. :warning:

As you will be now using a host-based resolver, I’d advise you to tweak your DNS resolution configuration.
The point is, as it will be now centralized (due to resolved usage), all you have to do is tweaking /etc/systemd/resolved.conf (!) :

[Resolve]
# Quad9's DNSs first
DNS=9.9.9.9 149.112.112.112 2620:fe::fe 2620:fe::9
# OpenDNS's DNSs as backup
FallbackDNS=208.67.222.222 208.67.220.220 2620:0:ccc::2 2620:0:ccd::2

Note : It’s a personal choice (#GTFO_Google), feel free to adapt it for your own system !

If everything looks good to you :

systemctl reload systemd-resolved

Connection (!)

You can now try to open again your OpenVPN connection, but you’ll need some additional flags (you could send them in the connection configuration, but I’d rather use parameters) :

openvpn --config openvpn-configuration.ovpn --script-security 2 --up /etc/openvpn/update-systemd-resolved --down /etc/openvpn/update-systemd-resolved --down-pre

And what about NetworkManager ??

Oh yeah, thanks, I almost forgot…

So as always, it’s a mess.

Explanations : Even if you have perfectly followed this walk-through, if you are using NetworkManager, it may break anyway next time you reboot or so.

So the workaround (again…), is to tell NetworkManager not to handle the DNS configuration, and thus, not overriding the /etc/resolv.conf settings, EVER.

:warning: If you are counting on NetworkManager to handle connection-specific DNS configuration, I regret having to inform you it won’t be possible anymore… :warning:

This could be achieved by tweaking /etc/NetworkManager/NetworkManager.conf :

[main]
dns=none

:warning: Now, if you simply reload the NetworkManager daemon, you’ll end up pulling your hairs out from your head as the /etc/resolv.conf would be overridden, again and again…

SO, the ultimate workaround is (the following of the sentence has not been 100%-proved) to restart the daemon, and not reloading it :

systemctl restart NetworkManager

:warning: All your connections will go down for a bit, wait for the end of your background downloads before running it :wink:

Conclusion

As always, I hope this helped you.

It is very complicated to keep using “old” (even basic) features with new distributions running systemd. Although everything has been re-thought, everything is not necessarily working as expected.