My Wiki!

OpenVPN DNS update

1. Using systemd-resolve

1.1 Theory

1.2 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).

Navigation