2026 is here, and it is time to begin technical writing on a regular basis; the complete opposite of the "LLM-ification" of the interweb.

Here is a simple one about DNS setup on Linux, primarily using systemd-resolved and NextDNS recursive resolvers.


NextDNS

Nowadays you have plenty of choices as recursive DNS. The goto, which I don't like, is usually 8.8.8.8 from Google or 1.1.1.1 from CloudFlare.

If you are concerned about sovereignty, you will see that these options are 100% US-based and do not allow you to control filtering, statistics, or security.

Alternatives exist and I have relied on NextDNS since 4y as a paid subscriber.

NetworkManager

NetworkManager is usually the default frontend for managing connections under Linux; as is the case for Raspberry Pi 4 running Debian Trixie (Raspbian).

I won't debate about it versus other configuration tools like networkd, netplan or bare interfaces files.

DNS backend

By default NetworkManager writes acquired DNS resolvers to /etc/resolv.conf and leaves it at that.

This approach lacks configurability and features such as DNSSEC or DoT/DoH. To do so you will need to use another DNS backend.

You can choose between dnsmasq and systemd-resolved.

systemd-resolved

$ # nm generated resolv.conf from dhcp acquired resolvers
$ cat /etc/resolv.conf
# Generated by resolvconf
domain lan
nameserver 45.90.28.0
...
nameserver 192.168.1.1

$ # switching to systemd-resolved backend
$ sudo apt install systemd-resolved
...
Converting /etc/resolv.conf to a symlink to /run/systemd/resolve/stub-resolv.conf...

$ tail -3 /etc/resolv.conf
nameserver 127.0.0.53
options edns0 trust-ad
search lan

By linking systemd-resolved stub resolver to /etc/resolv.conf, NetworkManager enables it as the DNS backend, thus supporting DoT/DoH and caching.

You can now configure selected connections to use any resolver you prefer.

You have the option to configure all interfaces or only specific ones; I prefer the latter for flexibility.

NetworkManager

$ nmcli con
NAME        UUID                                  TYPE      DEVICE
wired       bd073894-9915-3f6d-8daf-3f3372783ae9  ethernet  eth0
tailscale0  2b3c82c5-917b-4781-a148-c9f11dc7cf11  tun       tailscale0
lo          28348d3c-2cdf-46a6-a879-0e6b904df6f7  loopback  lo

$ sudo nmcli con mod wired ipv4.dns 45.90.28.0#raspberry-12345.dns.nextdns.io,45.90.30.0#raspberry-12345.dns.nextdns.io
$ sudo nmcli con mod wired ipv6.dns 2a07:a8c0::#raspberry-12345.dns.nextdns.io,2a07:a8c1::#raspberry-12345.dns.nextdns.io

$ # ignore DHCP DNS servers
$ sudo nmcli con mod wired ipv4.ignore-auto-dns yes
$ sudo nmcli con mod wired ipv6.ignore-auto-dns yes

Let's verify that everything works as expected.

$ resolvectl status
Global
         Protocols: +LLMNR -mDNS +DNSOverTLS DNSSEC=yes/supported
  resolv.conf mode: stub

Link 2 (eth0)
    Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
         Protocols: +DefaultRoute +LLMNR -mDNS +DNSOverTLS DNSSEC=yes/supported
Current DNS Server: 45.90.28.0#raspberry-12345.dns.nextdns.io
       DNS Servers: 45.90.28.0#raspberry-12345.dns.nextdns.io 45.90.30.0#raspberry-12345.dns.nextdns.io 2a07:a8c0::#raspberry-12345.dns.nextdns.io
                    2a07:a8c1::#raspberry-12345.dns.nextdns.io
        DNS Domain: lan
     Default Route: yes
$ resolvectl query google.com
google.com: 142.250.201.14                     -- link: eth0
            2a00:1450:4006:80e::200e           -- link: eth0

-- Information acquired via protocol DNS in 56.9ms.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: yes
-- Data from: network
$ sudo resolvectl statistics
Transactions
                       Current Transactions:  0
                         Total Transactions: 21

Cache
                         Current Cache Size:  4
                                 Cache Hits:  6
                               Cache Misses: 11

Failure Transactions
                             Total Timeouts:  4
         Total Timeouts (Stale Data Served):  0
                    Total Failure Responses:  0
Total Failure Responses (Stale Data Served):  0

DNSSEC Verdicts
                                     Secure:  0
                                   Insecure:  0
                                      Bogus:  0
                              Indeterminate:  0

To make the setup even more explicit, you can configure NetworkManager to always use systemd-resolved

$ head -4 /etc/NetworkManager/NetworkManager.conf
[main]
plugins=ifupdown,keyfile
dns=systemd-resolved
dns-over-tls=yes

DoT with DNSSEC

DNS-over-TLS is a transport security that protects your DNS traffic from tampering. It is basically encryption of the UDP/TCP requests and responses between you and the server. The standard is defined by the RFC 7858.

DNSSEC is a signature mechanism for response integrity, confirming that you get an unaltered response from the domain owner. The standard is defined by the RFC 9364.

systemd-resolved supports both.

systemd-resolved

$ cat /etc/systemd/resolved.conf.d/01-nextdns.conf
[Resolve]
DNS=2a07:a8c0::#pooptop-12345.dns.nextdns.io
DNS=2a07:a8c1::#pooptop-12345.dns.nextdns.io
DNS=45.90.28.0#pooptop-12345.dns.nextdns.io
DNS=45.90.30.0#pooptop-12345.dns.nextdns.io
DNSOverTLS=yes
DNSSEC=true
Cache=no-negative
StaleRetentionSec=60
Domains=~.

There is a catch about Domains. ~. means to route all queries to these DNS servers, giving them top priority over DNS servers acquired via DHCP.

You should now see the secure count increasing. Currently, not all domains support DNSSEC, which explains the insecure count.

 sudo resolvectl statistics
Transactions
                       Current Transactions:    0
                         Total Transactions: 8091

Cache
                         Current Cache Size:   78
                                 Cache Hits: 3905
                               Cache Misses: 7277

Failure Transactions
                             Total Timeouts:   12
         Total Timeouts (Stale Data Served):    0
                    Total Failure Responses:    0
Total Failure Responses (Stale Data Served):    0

DNSSEC Verdicts
                                     Secure: 3530
                                   Insecure: 3675
                                      Bogus:   33
                              Indeterminate:    0

EDNS Client Subnet

ECS is a EDNS0 extension designed to improve performance in a world of anycast IP.

Bear with me, it is implemented by recursive resolver to forward the client's CIDR to the authoritative resolver, providing a hint about the optimal origin.

Without ECS, the authoritative resolver bases its decision on the location of the intermediate recursive resolver, which may be geographically distant from the client.

NextDNS support ECS and I use it despite some privacy concern (on that matter we will see how to use Tailscale exit node as an affordable and permanent VPN)

The standard is defined by the RFC 7871.

Resources

NetworkManager - ArchWiki
NetworkManager is a program for providing detection and configuration for systems to automatically connect to networks.
https://wiki.archlinux.org/title/NetworkManager#DNS_management
Projects/NetworkManager/DNS – GNOME Wiki Archive
https://wiki.gnome.org/Projects/NetworkManager/DNS
dnscheck.tools - check your dns resolvers
A tool to test for DNS leaks, DNSSEC validation, and more
https://dnscheck.tools/


See you in a bit ✌︎㋡