====== OpenVPN DNS update ====== * opensuse: https://www.gabriel.urdhr.fr/2020/03/17/systemd-revolved-dns-configuration-for-vpn/ * Ubuntu: https://www.ricmedia.com/set-permanent-dns-nameservers-ubuntu-debian-resolv-conf/ ===== - Using systemd-resolve ===== ==== - Theory ==== .https://github.com/systemd/systemd/pull/17678/files?short_path=ae87a27 ==== - Manual configuration ==== === Prerequisites === First check if you have systemd-resolved installed and running: systemctl status systemd-resolved Check if you have the resolvectl too: resolvectl An alternative is to use systemd-resolve: systemd-resolve --status Check if have the resolve mechanism enabled in nssswitch.conf: cat /etc/nsswitch.conf | grep ^hosts: | grep resolve Install the needed libraries. For example on Debian or Ubuntu AMD64 systems: dpkg -l | grep libnss-resolve Note: I'm installing both the 64 bit and 32 bit libraries. If you do not install the 32 bit libraries, proper DNS resolution might fail for 32 programs. Symlink /etc/resolv.conf is a symlink to /var/run/netconfig/resolv.conf autogenerated by netconfig! Call to force adjusting of /etc/resolv.conf. netconfig update -f === Summary === If you are using a Linux system with systemd-resolved, a quick fix is something like this (your need to adjust these values): # Configure internal corporate domain name resolvers: resolvectl dns tun0 192.0.2.53 192.0.2.54 # Only use the internal corporate resolvers for domain names under these: resolvectl domain tun0 "~foo.example.com" "~bar.example.com" # Not super nice, but might be needed: resolvectl dnssec tun0 off If you don't have the resolvectl commands, you might use instead: systemd-resolve -i tun0 \ --set-dns=192.0.2.53 --set-dns=192.0.2.54 \ --set-domain=foo.example.com --set-domain=bar.example.com \ --set-dnssec=off # <- Not super nice, but might be needed. ==== Details ==== === Configure DNS resolution === If all these prerequisites are satisfied, you can configure the DNS resolution with something like: resolvectl dns tun0 192.0.2.53 192.0.2.54 resolvectl domain tun0 "~foo.example.com" "~bar.example.com" Alternatively, if you don't have resolvectl: systemd-resolve -i tun0 \ --set-dns=192.0.2.53 --set-dns=192.0.2.54 \ --set-domain=~foo.example.com --set-domain=~bar.example.com This configures systemd-resolved to use the corporate internal resolvers 192.0.2.53 and 192.0.2.54 for resolving all domain names under foo.example.com and bar.example.com (eg. some-service.foo.example.com). tun0 is network interface of the VPN. You have to adjust these parameters (IP address, domain names). Note: the ~ in front of a domain prevents the domain to be added to the search list (i.e. trying to resolve the test host name will not search test.foo.example.com if a ~ was used in front of foo.example.com). You can check your system-resolved configuration with: resolvectl If you don't have resolvectl: systemd-resolve --status You can now test domain name resolution (assuming some-service.foo.example.com actually exists): resolvectl query some-service.foo.example.com If you don't have resolvectl: systemd-resolve some-service.foo.example.com If this works, you should have: some-service.foo.example.com: 192.0.2.22 -- link: tun0 -- Information acquired via protocol DNS in 1.7ms. -- Data is authenticated: no In my case, this failed because of: some-service.foo.example.com: resolve call failed: DNSSEC validation failed: failed-auxiliary A quick/dirty fix is to disabled DNSSEC: resolvectl dnssec tun0 off If you don't have resolvectl: systemd-resolve -i tun0 \ --set-dns=192.0.2.53 --set-dns=192.0.2.54 \ --set-domain=foo.example.com --set-domain=bar.example.com \ --set-dnssec=off === Hooking with OpenVPN (CLI) === If you are using OpenVPN directly from the CLI (not through Network Manager), you can automate this with the --up options. For example: openvpn --config client.ovpn --script-security 2 --up ./manual-config where ./manual-config is a shell script such as: #!/bin/sh set -e resolvectl dns $dev 192.0.2.53 192.0.2.54 resolvectl domain $dev "~foo.example.com" "~bar.example.com" resolvectl dnssec $dev off or #!/bin/sh systemd-resolve -i $dev \ --set-dns=192.0.2.53 --set-dns=192.0.2.54 \ --set-domain=foo.example.com --set-domain=bar.example.com \ --set-dnssec=off # <- Not super nice, but might be needed. OpenVPN sets the dev environment variable to the name of the VPN TUN/TAP (i.e. virtual) network device (eg. tun0) when calling the hooks. Don't forget to make this script executable. Using update-systemd-resolved An alternative is to use the update-systemd-resolved script (on Debian and Ubuntu it is in the openvpn-systemd-resolved package): openvpn \ --config client.ovpn \ --up /etc/openvpn/update-systemd-resolved \ --down /etc/openvpn/update-systemd-resolved \ --down-pre \ This automatically pulls configuration advertised by the VPN server: resolver to used; domain names; whether to disable DNSSEC. If this fails, the previous section might help you pinpoint to the problem: check the configuration (resolvectl); test internal/external names resolution (resolvectl query some-service.foo.example.com) disable DNSSEC if needed (resolvectl dnssec tun0 off).