---
section: 37
x-masysma-name: dns_over_tls_systemd_resolved
title: DNS over TLS (DoT) using systemd-resolved
date: 2026/01/01 19:36:19
lang: en-US
author: ["Linux-Fan, Ma_Sys.ma (info@masysma.net)"]
keywords: ["kb", "systemd", "avahi", "dot", "dns", "linux", "aes67"]
x-masysma-version: 1.1.0
x-masysma-website: https://masysma.net/37/dns_over_tls_systemd_resolved.xhtml
x-masysma-owned: 1
x-masysma-copyright: (c) 2026 Ma_Sys.ma <info@masysma.net>.
---
Introduction
============

Previously, I had been using my ISP's default DNS server. After encountering a
page blocked by CUII, I decided to move to an alternative DNS server without
censoring. This made it necessary to setup DNS over TLS (DoT, RFC7858).

As it was not easily done using the traditional `/etc/resolv.conf` and
`/etc/network/interfaces` style configuration I decided to take this as
an opportunity to move to systemd-networkd and systemd-resolved. Initially,
this broke my AES 67 audio setup such that I subsequently needed to re-enable
Avahi Daemon instead of the mDNS solution integrated into systemd-networkd.

This post summarizes the individual steps for my own reference and for everyone
who may be interested in it.

Alternative DNS Server Providers
================================

The first and most difficult step is to select a suitable replacement DNS
provider. I went with the DNS by _Digitalcourage e.V._, but there are also
other privacy-respecting and uncensored DNS providers:

Provider                        IPv4             IPv6                        Link
------------------------------  ---------------  --------------------------  ------------------------------------------------------------------------------------
AdGuard                         94.140.14.140    2a10:50c0::1:ff             <https://adguard-dns.io/de/public-dns.html>
                                94.140.14.141    2a10:50c0::2:ff              
Artikel 10 e.V.                 217.197.91.153   2001:67c:1401:2120::1       <https://dns.artikel10.org/>
Digitalcourage e.V.             5.9.164.112      2a01:4f8:251:554::2         <https://digitalcourage.de/support/zensurfreier-dns-server>
Digitale Gesellschaft           185.95.218.42    2a05:fc84::42               <https://www.digitale-gesellschaft.ch/dns/>
                                185.95.218.43    2a05:fc84::43                
dns.watch                       84.200.69.80     2001:1608:10:25::1c04:b12f  <https://dns.watch/>
                                84.200.70.40     2001:1608:10:25::9249:d69b   
Foundation for Applied Privacy  146.255.56.98    2a02:1b8:10:234::2          <https://applied-privacy.net/services/dns/>
Freie Netze München e.V.        5.1.66.255       2001:678:e68:f000::         <https://ffmuc.net/wiki/doku.php?id=knb:dohdot>
                                185.150.99.255   2001:678:ed0:f000::          
Mullvad                         194.242.2.2      2a07:e340::2                <https://mullvad.net/en/help/dns-over-https-and-dns-over-tls>
Njalla                          95.215.19.53     2001:67c:2354:2::53         <https://dns.njal.la/>
Restena Foundation              158.64.1.29      2001:a18:1::29              <https://www.restena.lu/en/document/190-configuring-your-server-public-dns-resolver>
Quad9                           9.9.9.9          2620:fe::fe                 <https://quad9.net/service/service-addresses-and-features/>
                                149.112.112.112  2620:fe::9                   
UncensoredDNS                   91.239.100.100   2001:67c:28a4::             <https://blog.uncensoreddns.org/dns-servers/>
xTom / DNS.SB                   185.222.222.222  2a09::                      <https://dns.sb/guide/>
                                45.11.45.11      2a11::                       

I mostly created above table from the sources linked from section
_See Also/Free Uncensored DNS Servers_. This is obviously Europe-centric. If you
are in a different part of the world, consider checking for regional
alternatives if you trust them more.

DNS over TLS
============

Standard DNS runs over UDP and DNS requests are issued by the libraries used
by the applications i. e. there is not necessarily a central daemon that emits
them. The information about which DNS server to consult is typically retrieved
from `/etc/resolv.conf`.

In a standard configuration, the values to put there are obtained from a DHCP
server and typically point to the router on the network which in turn forwards
the DNS requests to the DNS server provided by the ISP.

When using a DNS server which accepts requests via UDP, changing the DNS server
of the system is as simple as replacing the entry in `resolv.conf`, e. g. by
Google's famous DNS 8.8.8.8 or Cloudflare's just as easy to remember 1.1.1.1.

However, this time I wanted to setup a future-proof privacy-respecting choice
of DNS server and many of them newly require DNS over TLS (DoT, or alternatively
DNS over HTTPS, aka. DoT) and do not allow the unencrypted access via UDP
anymore.

This is of course, good for security, but not all applications are individually
capable of contacting a DoT or DoH-based DNS server directly. Hence for this use
case, it is helpful to run a local unencrypted DNS server that translates the
locally incoming UDP-based cleartext requests to TCP-based and encrypted DoT.

Such a local DNS server can be provided by systemd-resolved.

systemd-resolved
================

There are certainly other alternatives, but in recent times I tend to prefer
the solutions offered by the systemd-related tools as sensible default choices.

Often, they implement only a subset of what is technically possible but this is
often sufficient to solve _my_ kind of use cases. Also, I like that the INI
config file format and introspection features (`*ctl`-series of commands) are
somewhat similar across the systemd tools, making them easy to get started with
once one knows how any of the other tools work.

This case here is only the second time that the out-of-the-box feature set of
the systemd tool was not coverying my use case 100% hence I had to substitute
the integrated systemd-resolved feature for mDNS with the proper avahi-daemon
(cf. Section _Recovering avahi-daemon_ further down).

The configuration for systemd-resolved is a straight-forward INI file:

~~~
# /etc/systemd/resolved.conf.d/20-digitalcourage-dot.conf
[Resolve]
DNS=5.9.164.112#dns3.digitalcourage.de 2a01:4f8:251:554::2#dns3.digitalcourage.de
DNSOverTLS=yes
Domains=~.
# disable multicast DNS because we _must_ use avahi-daemon for AES67!
MulticastDNS=no
~~~

The DNS servers to use are configured in line `DNS` and DoT is enabled by
setting `DNSOverTLS=yes`.

If I understood it correctly, for systemd-resolved to run correctly, the
network interface must be known by systemd-networkd. I used the opportunity to
configure systemd-networkd for my primary network interface `eno1` but it would
possibly be enough to only have the `[Match]` and `Name=eno1` lines if the
interface was managed by `/etc/network/interfaces`.

~~~
# /etc/systemd/network/20-masysma-main.network
[Match]
Name=eno1

[Link]
RequiredForOnline=routable

[Network]
DHCP=ipv6
Address=192.168.1.16/24
Gateway=192.168.1.1
~~~

For my use of systemd-networkd, I removed the interface from
`/etc/network/interfaces`, keeping only the loopback interface there:

~~~
# /etc/network/interfaces
auto lo
iface lo inet loopback
~~~

Ensure both of the required systemd services are running:

~~~
# systemctl enable --now systemd-networkd.service
# systemctl enable --now systemd-resolved.service
~~~

Then inspect the status of systemd-resolved with the `resolvectl` command:

~~~
# resolvectl
Global
         Protocols: +LLMNR +mDNS +DNSOverTLS DNSSEC=no/unsupported
  resolv.conf mode: stub
Current DNS Server: 5.9.164.112#dns3.digitalcourage.de
       DNS Servers: 5.9.164.112#dns3.digitalcourage.de
                    2a01:4f8:251:554::2#dns3.digitalcourage.de
        DNS Domain: ~.

Link 2 [...]

Link 5 (eno1)
    Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
         Protocols: +DefaultRoute +LLMNR -mDNS +DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: fe80::1
       DNS Servers: fe80::1
     Default Route: yes

Link 6 [...]
~~~

Note the `-mDNS` and `+mDNS` in the output: If you wanted to setup
systemd-resolved with mDNS support but without avahi-daemon, you could set
the variable `MulticastDNS=yes` in the network interface configuration and the
systemd-resolved configuration to enable its integrated mDNS support.

Check that systemd-resolved works by itself:

~~~
# resolvectl query masysma.net
masysma.net: 2a01:239:241:bf00::1              -- link: eno1
             87.106.179.152                    -- link: eno1

-- Information acquired via protocol DNS in 936us.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: yes
-- Data from: cache
~~~

Once it works OK there, replace `/etc/resolv.conf` by a configuration that
points to the locally running server provided by systemd-resolved:

~~~
# mv /etc/resolv.conf /etc/resolv.conf.bak
# ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
~~~

Check the content of the effective `resolv.conf`:

~~~
$ grep -vE '^#' /etc/resolv.conf

nameserver 127.0.0.53
options edns0 trust-ad
search .
~~~

Confirm that DNS works by running `host`:

~~~
$ host masysma.net
masysma.net has address 87.106.179.152
masysma.net has IPv6 address 2a01:239:241:bf00::1
masysma.net mail is handled by 5 smtpin.rzone.de. 
~~~

Recovering avahi-daemon
=======================

After initially setting up systemd-resolved as a replacement also for
avahi-daemon, I noticed that the audio streams configured in
`aes67-linux-daemon` cf. [aes67_audio_notes(37)](../37/aes67_audio_notes.xhtml)
would no longer be received on the Audio Interface. This was due to the streams
not being announced with mDNS anymore.

In general, it seems the `aes67-linux-daemon` requires avahi-daemon for this
task. Hence I disabled the mDNS support in `systemd-resolved` and instead
re-enabled the `avahi-daemon.service`.

After restarting `aes67-linux-daemon` the audio streams were again discovered
by the interface.

The configuration in the previous section already accounts for this change. If
you don't run AES67 you might get away successfully with setting
`MulticastDNS=yes` in `/etc/systemd/resolved.conf.d` and `/etc/systemd/network`
and could then probably do without the separately running
`avahi-daemon.service`...

See Also
========

 * [RFC7858](https://datatracker.ietf.org/doc/html/rfc7858) - DNS over TLS

## About CUII

 * <https://cuii.info/anordnungen/>
 * <https://cuiiliste.de/>

## Free Uncensored DNS Servers

 * <https://european-alternatives.eu/category/public-dns>
 * <https://www.privacy-handbuch.de/handbuch_93d.htm>
 * <https://github.com/dns-sb/dns.sb/issues/36>

## DNS-over-TLS with systemd-resolved

 * <https://wiki.archlinux.org/title/Systemd-networkd>
 * <https://wiki.debian.org/SystemdNetworkd>
 * <https://wiki.debian.org/resolv.conf>
 * <https://askubuntu.com/questions/1092498/dns-over-tls-with-systemd-resolved>
 * [systemd.network(5)](https://manpages.debian.org/trixie/systemd/systemd.network.5.en.html)
 * [resolved.conf(5)](https://manpages.debian.org/trixie/systemd-resolved/resolved.conf.5.en.html)
