Your DNS is Leaking (And Everyone’s Watching)
You’ve likely spent hours hardening your firewalls, rotating SSH keys, and configuring WireGuard. Yet, you’re probably still ignoring the most basic leak in your stack: DNS. For decades, DNS queries have bounced across the internet in plain text via UDP port 53. This means anyone sitting between your Linux server and the resolver—whether it’s your ISP or a public Wi-Fi admin—knows exactly which domains you visit.
The reality is that even with HTTPS, your initial DNS handshake is an open book. This metadata allows providers to build a creepily accurate profile of your activity. After running a production environment for the last six months with full encryption, I’ve found that securing DNS isn’t just a privacy ‘nice-to-have.’ It is about data integrity. If you care about modern Linux security, this is a setup you can’t afford to skip.
Choosing Your Shield: DoT vs. DoH
Encryption comes in two main flavors. Both wrap your queries in a layer of TLS, but they handle the actual traffic very differently. Here is the breakdown based on my testing.
DNS over TLS (DoT)
DoT uses a dedicated port (TCP 853). It’s clean and easy for network admins to monitor or shape. It is also the native choice for systemd-resolved. However, because it uses a specific port, a restrictive firewall can block it with a single rule. I use this primarily for backend servers where I control the network edge.
DNS over HTTPS (DoH)
DoH hides your queries inside standard HTTPS traffic on port 443. To any observer, your DNS requests look like normal web browsing. This makes it the ultimate tool for bypassing censorship or strict corporate filters. The trade-off? It’s slightly heavier to implement at the OS level, usually requiring a local proxy like cloudflared.
Over the last half-year, my data shows that DoT is the winner for server infrastructure. For workstations or servers in ‘hostile’ networks, DoH is the only reliable way to stay hidden.
Enabling DNS over TLS with systemd-resolved
If you’re on Ubuntu 22.04, Fedora, or Debian, you already have systemd-resolved. It’s the simplest way forward. Here is how I configured my fleet to use Cloudflare and Google as encrypted upstream resolvers.
1. Edit the Config
Open your configuration file:
sudo nano /etc/systemd/resolved.conf
Update the [Resolve] section. Don’t just add one IP; use multiple providers for redundancy.
[Resolve]
DNS=1.1.1.1 8.8.8.8 1.0.0.1 8.8.4.4
FallbackDNS=9.9.9.9
DNSOverTLS=yes
DNSSEC=yes
2. Apply and Audit
Restart the service to pull in the new settings:
sudo systemctl restart systemd-resolved
Now, verify the status. You aren’t looking for ‘active’—you’re looking for the encryption flag:
resolvectl status
Check for +DNSOverTLS under your active interface. If it’s there, every query your system makes is now encrypted before it hits the wire.
Deploying DNS over HTTPS with Cloudflared
When port 853 is blocked, I switch to a local proxy. cloudflared (from Cloudflare) acts as a bridge between your local apps and the DoH endpoint.
1. Get the Binary
For Debian-based systems, grab the latest release:
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
2. Configure the Proxy
Create your config file:
sudo mkdir -p /etc/cloudflared
sudo nano /etc/cloudflared/config.yaml
Point it to the DoH endpoints:
proxy-dns: true
proxy-dns-port: 5053
proxy-dns-upstream:
- https://1.1.1.1/dns-query
- https://1.0.0.1/dns-query
3. Automate the Service
Install it as a system service so it survives a reboot:
sudo cloudflared service install
sudo systemctl start cloudflared
sudo systemctl enable cloudflared
Finally, set your system DNS to 127.0.0.1 in your network settings or resolved.conf. Your traffic now flows through the local proxy at port 5053 and out to the web via port 443.
The Smoke Test: Is it Actually Working?
Never trust a status message. The biggest mistake is assuming you’re safe while your system quietly falls back to port 53. You need to verify that no plain-text traffic is escaping.
Run tcpdump in one terminal to watch for leaks:
sudo tcpdump -ni any port 53
Now, trigger a lookup in a second terminal: dig google.com. If tcpdump stays silent, your encryption is solid. If you see scrolling text, your system is still leaking queries in the clear.
The Good, The Bad, and The Latency
Half a year of production use has revealed a few quirks you should prepare for:
- Captive Portal Hell: Airport and hotel Wi-Fi often hijack DNS to show login pages. If DoT is ‘Hard’ enabled, you won’t get a connection. I keep a quick alias to toggle
DNSOverTLSto ‘opportunistic’ for travel. - The Latency Tax: TLS handshakes aren’t free. I measured an average increase of 12ms to 18ms for the first query. However, once the connection is persistent and cached locally, the perceived speed is identical to standard DNS.
- Redundancy is King: Don’t rely solely on one provider. I once saw a 45-minute outage where Cloudflare’s DoH was unreachable from my Frankfurt node. My fallback to Quad9 (9.9.9.9) kept my services alive without a single dropped query.
The peace of mind knowing my ISP isn’t harvesting my metadata for their advertising arm is worth every minor hurdle. If you manage servers handling sensitive data, encrypted DNS is no longer a luxury—it’s a requirement.
Final Verdict
In today’s environment, plain-text DNS is a liability. Whether you choose the native simplicity of DoT or the stealth of DoH, you’re closing a massive gap in your server’s defense. Start by testing on a single dev machine, verify with tcpdump, and then roll it out to your fleet. Your future self will appreciate the extra layer of armor.

