Ubuntu – DNS over TLS with systemd-resolved

dnsnetworkingsystemd-resolved

I was trying to enable DNS over TLS via systemd-resolved. I changed /etc/systemd/resolved.conf as follows:

[Resolve]
DNS=1.1.1.1
#FallbackDNS=
Domains=~.
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
DNSOverTLS=opportunistic
#Cache=yes
#DNSStubListener=yes

While monitoring the network (with tcpdump) to see if the resulting behavior was the intended one, it seems that a TLS session is established with the target server; but, then the server closes the connection. I get the same results with 1.1.1.1, 8.8.8.8 and others.

Any ideas on how to fix this?

P.S.: systemd-resolved ends up doing parallel resolution with traditional DNS (despite the setting of "Domains" above). But my main question for this post is what may be going wrong with the TLS one.

Best Answer

Recently I've implemented DNS over TLS for home network (using AsusWRT-Merlin powered router). While exploring approaches to implement DoT for Linux workstations and servers (in the cloud - I mean someone else' computers lol) outside of home network, I found systemd-resolved as recommended by the DNS Privacy Project.

While @opinion-no9 provided a Ubuntu 18.04 specific solution (limited by the systemd version shipped with the LTS), I'd like to share a more generic and close-to-upstream one:

A bit of background - timeline for DNS over TLS support in systemd

  • 236 DNSSEC support for RFC 8080 (ed25519 keys and signatures)
  • 239 systemd-resolved now supports opportunistic DNS-over-TLS, Off by default
  • 243 systemd-resolved gained support for a new strict DNS-over-TLS mode

Oh NO! Ubuntu 18.04 LTS ships systemd 237...

UPDATE - 23 April 2020 Ubuntu 20.04 LTS which ships systemd 245 (without systemd-homed ;-).

Use DNS Over TLS (DoT) on generic Linux systems

So for generic Linux distro with relative close-to-upstream kernel, systemd, glibc, toolchain, GNU utils, etc

  1. edit /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1 1.0.0.1 8.8.8.8
#FallbackDNS=1.1.1.1 9.9.9.10 8.8.8.8 2606:4700:4700::1111 2620:fe::10 2001:4860:4860::8888
#Domains=
#LLMNR=yes
#MulticastDNS=yes
#DNSSEC=allow-downgrade
#DNSOverTLS=opportunistic
DNSSEC=yes
DNSOverTLS=yes
#Cache=yes
#DNSStubListener=yes
#ReadEtcHosts=yes

Ubuntu 20.04 specific resolved.conf

[Resolve]
DNS=1.1.1.1 1.0.0.1 8.8.8.8
FallbackDNS=1.1.1.1 8.8.8.10 8.8.8.8
#Domains=
#LLMNR=no
#MulticastDNS=no
DNSSEC=yes
DNSOverTLS=yes
#Cache=yes
#DNSStubListener=yes
#ReadEtcHosts=yes
  1. Assume systemd-resolved is enabled, restart the service
systemctl restart systemd-resolved.service
  1. Use local stub resolver

systemd-resolved provides a local DNS stub listener on IP address 127.0.0.53 on the local loopback interface, so to use the DNS over TLS capable stub resolver, we'll need to somehow manage /etc/resolv.conf and make sure 127.0.0.53 is used as nameserver.

NOTE: systemd maintains /run/systemd/resolve/stub-resolv.conf for compatibility with traditional Linux programs. We can simply symlink to this file ;-)

ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

NOTE: For Arch Linux, I have to replace openresolvconf with systemd-resolvconf.

Done.

Validation

Generate DNS query, then check TCP connection to specified upstream DNS server via port 853, in the following example we explicitly used Cloudflare's 1.1.1.1.

root@netbook:/etc# uname -a
Linux netbook 5.4.5-arch1-1 #1 SMP PREEMPT Wed, 18 Dec 2019 19:48:51 +0000 x86_64 GNU/Linux

root@netbook:~#  kdig -d github.com
;; DEBUG: Querying for owner(github.com.), class(1), type(1), server(127.0.0.53), port(53), protocol(UDP)
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 55366
;; Flags: qr rd ra; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 0

;; QUESTION SECTION:
;; github.com.                  IN      A

;; ANSWER SECTION:
github.com.             58      IN      A       13.236.229.21

;; Received 44 B
;; Time 2019-12-21 22:55:13 AEDT
;; From 127.0.0.53@53(UDP) in 58.0 ms

root@netbook:~# ss -tuna | grep :853
tcp   ESTAB  0       0        192.168.1.150:50504         1.1.1.1:853
tcp   ESTAB  0       0        192.168.1.150:50506         1.1.1.1:853

Or, if you want to be simple and rough, use tcpdump ;-)

tcpdump -tttt -nn -XX -vv -i <interface> dst 1.1.1.1 and port 853

Conclusion

Last but not least: This is a generic guide to enable DNS over TLS on a Linux host, it is not specific to distro or Desktop Environment (as we haven't even touched NetworkManager or alternatives ;-). Adjustments may be needed for different distros and different DEs/WMs.

Reference