I run a mix of servers and workstations where DNS privacy and integrity matter. Relying on plain UDP DNS leaves queries exposed to interception and manipulation. That’s why I configure systemd-resolved to use DNS-over-TLS (DoT) and DNSSEC validation. It encrypts traffic to upstream resolvers and verifies response authenticity. This isn’t just for laptops—any Linux host exposed to untrusted networks benefits.
Why use systemd-resolved for DoT and DNSSEC
systemd-resolved is the local stub resolver shipped with most modern distros. Applications talk to it via the localhost DNS stub (127.0.0.53), and it forwards queries using configured protocols. By enabling DoT, I prevent eavesdropping on DNS traffic between the host and the resolver. DNSSEC adds cryptographic validation, ensuring responses haven’t been tampered with. Together, they close two major gaps in legacy DNS.
I’ve seen networks where DNS hijacking redirected users to fake login pages. With DoT and DNSSEC active, such attacks fail because the resolver either encrypts the query or discards invalid signatures. This setup pairs well with other hardening steps I’ve covered, like restricting SSH access or monitoring audit logs.
Installing and enabling systemd-resolved
On Debian/Ubuntu, the package is usually installed by default. If not:
sudo apt update
sudo apt install systemd-resolved
Enable and start the service:
sudo systemctl enable --now systemd-resolved
Verify it’s active:
systemctl status systemd-resolved
journalctl -u systemd-resolved --since "10 minutes ago"
Check what DNS stub address applications see:
resolvectl status
You should see a line like Current DNS Server: 127.0.0.53. If you still see ISP-assigned servers, check /etc/resolv.conf—it should point to 127.0.0.53 via a symlink or static config. On some minimal installs, you may need to adjust Netplan or NetworkManager to avoid overwriting it.
Configuring DNS-over-TLS upstream
I edit /etc/systemd/resolved.conf to define DoT servers. Cloudflare and Quad9 offer reliable DoT endpoints with DNSSEC validation.
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 9.9.9.9#dns.quad9.net
FallbackDNS=8.8.8.8#dns.google 8.8.4.4#dns.google
DNSOverTLS=yes
DNSSEC=yes
The #hostname syntax tells resolved to verify the TLS certificate against that hostname—critical for preventing MITM. After saving, restart the service:
sudo systemctl restart systemd-resolved
Test the configuration:
resolvectl query example.com
Look for DNSSEC: yes and Transaction ID: ... in the output. If you see DNSSEC: no or validation failures, double-check the upstream server’s DoT hostname spelling.
Verifying encryption and validation
To confirm DoT is active, I use tcpdump on port 853 (the standard DoT port):
sudo tcpdump -i any port 853 -n
Run a DNS query in another terminal—you should see TLS handshake packets. No plain UDP port 53 traffic to the upstream should appear.
For DNSSEC validation, I test with a known-bad domain:
resolvectl query dnssec-failed.org
A properly configured resolver returns DNSSEC: no and marks the result as insecure or bogus, depending on policy. You can adjust how strictly resolved treats failures via the DNSSEC option (options: no, allow-downgrade, yes, validate). I use yes for strict validation.
Troubleshooting common issues
- Resolution fails after config change: Check
journalctl -u systemd-resolvedfor TLS handshake errors. Often, it’s a typo in the DoT hostname or blocked port 853. - Local services ignore resolved: Some containers or chroots bypass 127.0.0.53. Ensure they inherit the host’s network namespace or explicitly set their DNS.
- High latency on first query: DoT adds a TLS handshake overhead. Subsequent queries reuse the connection, so latency normalizes. If your uplink is high-latency, consider caching locally with
dnscrypt-proxyorunboundas a forwarder—but that adds complexity. - Conflicts with NetworkManager or netplan: These tools can overwrite
/etc/resolv.conf. I either let resolved manage it via symlink (ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf) or disable DNS processing in those tools.
When this setup makes sense
I enable DoT and DNSSEC on:
- Laptops connecting to public Wi-Fi
- Edge servers in DMZs
- Workstations in zero-trust environments
- Any host where DNS integrity is part of compliance
It’s not a replacement for endpoint firewalls or encrypted SNI, but it’s a foundational layer. As I mentioned before, combining this with DNS-based threat prevention (like blocking known-malware domains at the resolver level) raises the cost of attacks significantly.
Final notes
systemd-resolved isn’t perfect—it lacks some advanced features of dedicated resolvers—but its tight integration with systemd makes it the simplest way to get DoT and DNSSEC working without extra daemons. Once configured, it runs quietly in the background, encrypting and validating every DNS query unless explicitly bypassed.
If you’re managing multiple hosts, consider rolling out the config via Ansible or a similar tool. I keep a template in my ops repo that includes fallback servers and periodic validation checks via cron.
For more on Linux networking hardening, see my post on [VoIP DSCP marking with tc](https://furkanikkan.com/urun/linux-tc-ile-voip-dscp-ef-isaretleme-ve-oncelik-kuyrugu-yapilandirmasi-104).
Cover image: USDAgov · PDM (Openverse / kamu malı) · https://www.flickr.com/photos/41284017@N08/52288969818
