Whilst we were putting together some content about DNS privacy recently, we learned that recent distributions of Linux ship with support for making DNS queries over TLS. We therefore decided to give Ubuntu 18.10 a try on a laptop.
More recent versions of Ubuntu employ a special service for name resolution called ‘system-resolved.service(8)’. The configuration file ‘resolved.conf(5)’ specifies most of the details for name resolution, including which protocols and resolvers should be employed, whilst the ‘/etc/systemd/network/*.network’ configuration files (see ‘systemd.network(5)’ for details) of the ‘systemd-networkd.service(8)’ specify any per-link specific settings.
The default configuration of ‘systemd-resolved’ is selected at compile time, and ‘/etc/systemd/resolved.conf’ normally contains commented-out lines describing such defaults. For example, the contents of the aforementioned file on a fresh Ubuntu 18.10 installation are:
As may be inferred from the file, DNS-over-TLS (DoT) is supported, but disabled by default. At the time of writing, only opportunistic DoT is supported according to the manual, which means that the resolver will first try resolution using DoT before falling back to traditional DNS in the event of failure – thus allowing for downgrade attacks where an attacker intentionally causes a DoT failure in order to cause name resolution to downgrade to traditional DNS.
We decided to give DoT at try by changing three configuration variables in ‘/etc/systemd/resolved.conf’:
- Set ‘DNS’ to the IP address of the DoT server
- Set ‘DNSOverTLS’ to ‘opportunistic’
- Set ‘Domains’ to ‘~.’
The ‘DNS’ variable contains the list of IP addresses that correspond to the DoT recursive resolver (you can find a list of public recursive resolvers here).
Setting ‘DNSOverTLS’ to ‘opportunistic’ enables DoT in opportunistic mode – this means that DoT will be employed if possible, but the stub resolver will fall back to traditional DNS if it fails.
Finally, setting ‘Domains’ to ‘~.’ instructs ‘systemd-resolved’ to prefer the specified nameserver over any per-link DNS server that may be available. This is an important setting as otherwise a non-DoT per-link DNS resolver could take precedence over the DoT resolver.
Our resulting configuration therefore becomes:
Once these changes have been applied, you need to make them take effect by executing the command:
sudo systemctl restart systemd-resolved
With this done, we then decided to double-check that DoT rather than traditional DNS was being employed. So we simply ran a sniffer on the Ubuntu laptop, and did a DNS query for ‘fgont.go6lab.si’ which revealed:
Our query generated both traditional DNS and DoT traffic in parallel. In fact, when we later ran a sniffer on the authoritative nameserver itself, it confirmed that both the local resolver on our network (192.168.3.1) and Cloud-flare’s resolver were issuing queries for the above domain.
In response to this finding, we tried to figure out why we were seeing traditional DNS traffic in parallel, instead of just DoT traffic, or at least DoT traffic followed by traditional DNS traffic on the assumption that DoT failed? In addition, why was the local resolver being employed for DNS resolution even when the ‘Domains’ variable instructs ‘systemd-resolved’ to employ the specified DoT resolver over any other resolver.
It would seem that the ‘systemd-resolved’ implementation for opportunistic DoT does not employ traditional DNS only as a result of DoT failures, but rather in parallel to DoT queries. On the other hand, a discussion on the GitHub repository for ‘systemd’ notes that the documentation for the ‘Domains’ variable is actually incorrect and simply specifies that the DoT resolver should be employed for domains matching the specified suffix (“.”, in our case), which does not mean this resolver should be the only one employed for resolving matching domains.
Based on the tests we’ve carried out, we can only conclude that there is a flaw in the DoT implementation of ‘systemd-resolved’. Quite clearly using a DoT resolver only makes sense if DNS queries are sent exclusively over an encrypted channel, or at the very least, traditional DNS is only employed in response to DoT failures (and possibly after acknowledgment from the user that traditional DNS should be employed).
We therefore currently recommend that if DoT needs to be employed, alternative implementations such as Stubby should be used until this issue is resolved with ‘systemd’.
We would like to thank Sara Dickinson for her help in debugging these issues.