DNS over HTTPS and DNS over TLS: Encrypting the Internet's Phone Book
Every website you visit starts with a DNS lookup. Your browser asks a resolver “what’s the IP address for github.com?” and gets an answer. For most of the internet’s history, this exchange happened in plaintext over UDP — visible to your ISP, your network provider, anyone on the path between you and the resolver.
DNS over HTTPS (DoH) and DNS over TLS (DoT) fix this. Both protocols encrypt DNS queries, preventing eavesdropping and tampering. They differ in how they do it, which has implications for deployment, privacy, and control.
This guide covers why encrypted DNS matters, how both protocols work under the hood, running your own DoH/DoT resolver, configuring clients across platforms, and the nuanced debate around whether centralizing DoH at the browser level is actually better for privacy.
Why Plain DNS Is a Problem
Your ISP Can Read Every Query
DNS traffic to your ISP’s resolver — or to 8.8.8.8 — is unencrypted UDP on port 53. Your ISP can:
- Log every domain you query, building a browsing profile
- Sell that data (legal in many jurisdictions)
- Inject responses (DNS hijacking for monetization or censorship)
- Block domains by returning NXDOMAIN
Even when you use a VPN, the VPN provider sees your DNS queries unless your VPN also handles DNS.
On-Path Attackers
On public Wi-Fi, an attacker doing ARP spoofing can intercept and modify DNS responses — pointing bank.example.com to a phishing server. Since DNS has no authentication by default (DNSSEC helps but has low adoption), your device accepts whatever the “resolver” says.
DNS Leaks
With split tunneling or misconfigured VPN clients, DNS queries can leak outside the VPN tunnel, revealing browsing activity to the local ISP even when you believe traffic is encrypted.
HTTPS encrypts the HTTP body and verifies server identity, but the DNS lookup that precedes it has historically been in the clear. DoH/DoT close this gap.
DNS over TLS (DoT)
How It Works
DoT wraps standard DNS protocol in a TLS connection:
Client Resolver
| |
|── TCP connect → port 853 ─────>|
|<──────────── TLS handshake ───>|
|── DNS query (inside TLS) ─────>|
|<── DNS response (inside TLS) ──|
|── DNS query ───────────────────>| (reuse TLS session)
|<── DNS response ────────────────|
Key properties:
- Port 853: DoT uses a dedicated port, making it identifiable (and blockable)
- Same DNS wire format: The DNS protocol doesn’t change — it’s just transported inside TLS
- Connection reuse: Multiple queries share one TLS connection, amortizing handshake cost
- Certificate validation: The resolver’s certificate is verified against a CA, preventing spoofing
The dedicated port means DoT is easy for network administrators to allow or block. Enterprise environments can permit DoT to trusted resolvers while blocking everything else. Conversely, restrictive networks can block port 853 entirely.
DoT Query Flow
1. TCP handshake to resolver:853
2. TLS handshake (SNI: dns.resolver.example.com)
3. DNS query (2-byte length prefix + standard DNS message)
4. DNS response (2-byte length prefix + standard DNS message)
5. Connection kept alive for subsequent queries
The 2-byte length prefix distinguishes DoT from plain DNS-over-TCP — it allows multiple queries to be multiplexed on one connection without delimiters.
DNS over HTTPS (DoH)
How It Works
DoH sends DNS queries as HTTPS requests to a web endpoint:
POST /dns-query HTTP/2
Host: dns.example.com
Accept: application/dns-message
Content-Type: application/dns-message
[binary DNS message]
Or via GET with base64url encoding:
GET /dns-query?dns=AAABAAABAAAAAAAAB... HTTP/2
Key properties:
- Port 443: DoH uses standard HTTPS port, indistinguishable from normal web traffic
- HTTP/2 or HTTP/3: Modern implementations support multiplexing many DNS queries over one TLS connection, or QUIC for HTTP/3
- Existing web PKI: Uses the same certificate infrastructure as HTTPS
- Can’t be easily blocked: Blocking port 443 would break the entire web
The inability to selectively block DoH without breaking HTTPS is both a feature (censorship resistance) and a concern (enterprise network visibility).
DoH Query Flow (HTTP/2)
1. TLS handshake to port 443 (standard HTTPS)
2. HTTP/2 connection established
3. POST /dns-query with binary DNS message body
4. 200 OK with binary DNS message body
5. HTTP/2 connection multiplexes subsequent queries
DNS over HTTPS/3 (DoH3)
Newer resolvers support DoH over HTTP/3 (QUIC). Benefits:
- Faster connection establishment (0-RTT for known servers)
- No head-of-line blocking (each DNS query is an independent QUIC stream)
- Connection migration (queries survive IP changes)
Cloudflare’s 1.1.1.1 and Google’s 8.8.8.8 both support DoH3.
DoT vs DoH: Practical Differences
| Property | DoT | DoH |
|---|---|---|
| Port | 853 (dedicated) | 443 (shared with HTTPS) |
| Blockable | Yes, block port 853 | No, would break all HTTPS |
| Protocol visibility | Identifiable as DNS | Looks like HTTPS traffic |
| Network admin control | Easy to manage | Difficult to intercept |
| Client support | OS-level (systemd-resolved) | Browser + OS level |
| Latency | Slightly lower (DNS-native) | Slightly higher (HTTP overhead) |
| Firewall friendliness | Variable | High |
For homelab use: DoT is excellent. You control your network, so there’s no need for DoH’s port-443 bypass. Your DNS traffic stays DNS-shaped.
For public-facing privacy: DoH provides stronger censorship resistance. Even on restrictive networks, DoH queries blend into HTTPS traffic.
For enterprise: DoT on port 853 allows controlled rollout to a specific resolver while maintaining network visibility. DoH bypass in browsers (Firefox’s canary domain approach) can undermine enterprise DNS policies.
DoH vs DoT vs DNSSEC
These solve different problems:
| Technology | Protects Against | Does NOT Protect Against |
|---|---|---|
| DoH/DoT | Eavesdropping on query/response | Malicious resolver returning wrong answers |
| DNSSEC | Tampered responses (validator verifies signatures) | Eavesdropping on queries |
| DoH/DoT + DNSSEC | Both | Nothing (best current practice) |
DNSSEC is complementary. It ensures the resolver didn’t lie about the answer; DoH/DoT ensures nobody on the path can read the question.
Running Your Own Encrypted Resolver
Public DoH/DoT resolvers (Cloudflare, Google, NextDNS) solve the ISP problem but shift trust to those providers. For maximum privacy, run your own resolver that queries authoritative nameservers directly.
Architecture Options
Option 1: Forwarder (Simpler)
Client → Local DoT/DoH resolver → Upstream DoT resolver (Cloudflare/NextDNS)
Your local resolver encrypts queries to an upstream. The upstream still sees your queries, but your ISP doesn’t.
Option 2: Recursive Resolver (Full Control)
Client → Local DoT/DoH resolver → Root nameservers → TLD nameservers → Authoritative nameservers
Your resolver queries root servers directly. No upstream provider sees your query patterns. More setup, but no third-party trust required.
Option A: Unbound (Recursive, Self-Hosted)
Unbound is a validating, caching resolver that can serve as the authoritative recursive resolver for your network. Pair it with stunnel or nginx to add TLS.
|
|
|
|
Add DoH support via nginx proxy:
|
|
You’ll need an intermediate DNS-to-HTTP adapter like dnsdist or Cloudflare’s doh-proxy.
Option B: dnsdist (Flexible Frontend)
dnsdist is a DNS load balancer that handles DoH and DoT natively and forwards to upstream resolvers:
|
|
|
|
This gives you a single service handling plain DNS, DoT, and DoH, all forwarding to a local Unbound for recursive resolution.
Option C: AdGuard Home (All-in-One, Recommended for Homelab)
AdGuard Home combines a DNS resolver, ad blocker, DoH/DoT server, and web UI in one package. It’s the easiest path to an encrypted home resolver.
|
|
After initial setup via the web UI:
- Encryption: Settings → Encryption → Enable. Upload your TLS certificate and private key. Set the server name to
dns.yourdomain.com. - Upstream DNS: Settings → DNS → Upstream DNS servers. Add
https://dns.cloudflare.com/dns-query(DoH) ortls://1.1.1.1(DoT) as upstream. For full recursion, use Unbound as upstream. - Bootstrap DNS: Plain DNS for resolving the upstream DoH hostname itself (before encrypted DNS is established):
1.1.1.1,9.9.9.9 - Blocklists: Use AdGuard’s built-in lists or import Pi-hole compatible lists.
Your DoH endpoint becomes: https://dns.yourdomain.com/dns-query
Your DoT endpoint becomes: tls://dns.yourdomain.com
Option D: Pi-hole + cloudflared (DoH Upstream Only)
If you already run Pi-hole, add cloudflared as a DoH proxy to encrypt upstream queries:
|
|
This doesn’t give you DoT/DoH to clients — Pi-hole still accepts plain DNS from the local network. But all upstream queries from Pi-hole to Cloudflare are encrypted.
For full DoH/DoT to clients, use AdGuard Home or dnsdist as described above.
Obtaining TLS Certificates
Your DoT/DoH server needs a valid TLS certificate. Options:
Let’s Encrypt (Recommended)
|
|
Set up auto-renewal and reload your DNS service:
|
|
Self-Signed (Internal Use Only)
For a fully internal resolver not accessible from the internet:
|
|
Distribute ca.crt to all clients as a trusted root. You’ll need to do this manually for each device.
Client Configuration
Linux (systemd-resolved)
Modern systemd versions support DoT natively:
|
|
|
|
macOS
macOS 11+ supports DoH and DoT via Configuration Profiles. The easiest way is to generate a profile:
|
|
Save as homelab-doh.mobileconfig and double-click to install. Or deploy via MDM.
Windows 11
Windows 11 has native DoH support in Settings → Network & Internet → Wi-Fi/Ethernet → DNS server assignment:
|
|
iOS and iPadOS
iOS 14+ supports DoH/DoT via Configuration Profiles (same .mobileconfig format as macOS). Generate one at tools like dns.notjakob.com or write it manually as above.
For system-wide DoH on iOS without a profile:
Settings → Wi-Fi → (your network) → Configure DNS → Manual only sets plain DNS. You need a profile or a VPN/DNS app for encrypted DNS.
Popular options: NextDNS app, AdGuard DNS app — both create a local VPN tunnel that routes DNS queries over DoH/DoT.
Android
Android 9+ has “Private DNS” (DoT) built in:
Settings → Network & Internet → Private DNS → Private DNS provider hostname
Enter: dns.yourdomain.com
Android will connect to port 853 with TLS. If it can’t establish a DoT connection, it falls back to plain DNS (with a warning icon). To force strict mode only, use a third-party app.
For DoH on Android, use:
- AdGuard: Creates a local VPN, routes DNS over DoH
- Intra (Google/Jigsaw): DoH-only
- NextDNS app: DoH/DoT to NextDNS
Firefox
Firefox has its own DoH implementation, independent of the OS:
about:preferences → Privacy & Security → DNS over HTTPS
Options:
- Default protection: DoH when system DNS might be compromised
- Increased protection: DoH, fall back to OS DNS if unavailable
- Max protection: DoH only, fail if DoH unavailable
Set a custom resolver URL to use your own:
https://dns.yourdomain.com/dns-query
The canary domain: Firefox checks for use-application-dns.net. If this domain returns NXDOMAIN or a specific response, Firefox disables its built-in DoH — this is used by enterprise DNS policies to prevent DoH bypass. If you want Firefox to use your OS DoH configuration instead, return NXDOMAIN for use-application-dns.net from your local resolver.
Chrome / Chromium
Chrome uses DoH if the system’s DNS server is a known DoH provider:
chrome://settings/security → Use secure DNS
It recognizes providers like Cloudflare (1.1.1.1), Google (8.8.8.8), NextDNS, etc. For a custom resolver, enter the URL directly:
https://dns.yourdomain.com/dns-query
Chrome’s DoH implementation “upgrades” known providers automatically — if your system DNS is 1.1.1.1, Chrome automatically uses https://1.1.1.1/dns-query.
Testing and Verification
Verify DoT
|
|
Verify DoH
|
|
Check for DNS Leaks
Even with DoH/DoT configured, misconfigured fallbacks can leak queries:
- Visit dnsleaktest.com
- Run the Extended test
- All DNS servers shown should be your resolver (or your chosen upstream provider), not your ISP
If you see ISP DNS servers, there’s a leak somewhere:
- Check browser-specific DNS settings
- Check for hardcoded DNS in apps
- Verify the OS is actually using your configured resolver
Verify DNSSEC
|
|
Monitoring
Query Metrics with AdGuard Home
AdGuard Home’s dashboard shows:
- Total queries per day/week
- Blocked queries (ads, malware)
- Query response time distribution
- Top queried domains
- Top blocked domains
- Per-client query breakdown
Prometheus Metrics
Both AdGuard Home and dnsdist export Prometheus metrics:
|
|
For AdGuard Home, use the adguardhome-sync sidecar or a dedicated exporter.
Query Logging
For troubleshooting, enable query logging in AdGuard Home (Settings → General → Query log). Be aware that logging all DNS queries creates a significant privacy record — disable it after debugging.
For Unbound:
|
|
Privacy Considerations and the DoH Centralization Debate
DoH has generated genuine controversy in the security community. The technical properties that make it good for end-user privacy create complications elsewhere.
The Centralization Problem
When browsers implement DoH with hardcoded public resolvers (Firefox defaulting to Cloudflare), it concentrates DNS traffic at large providers. Cloudflare can see query patterns for all Firefox users using the default setting — a significant surveillance opportunity regardless of their stated privacy policies.
The alternative — querying root servers recursively — distributes trust across the DNS hierarchy but is slower and doesn’t encrypt queries to TLD nameservers or authoritative servers.
Running your own recursive resolver (Unbound + DoH/DoT frontend) gets the best of both worlds: encrypted client-to-resolver queries, no single provider seeing all your queries, and DNS responses validated with DNSSEC.
ISP vs. Provider Visibility
DoH/DoT moves trust from your ISP to your resolver provider. This is often (not always) an improvement:
- ISP: Has contractual relationship, knows your physical address, is subject to local law enforcement data requests, may sell data
- Cloudflare/Google/NextDNS: Larger target for legal requests, but typically in different jurisdiction, may have stronger privacy policies, subject to public scrutiny
Self-hosting eliminates this entirely.
ESNI / ECH: The Remaining Gap
Even with DoH/DoT, the SNI (Server Name Indication) in the TLS handshake reveals which website you’re connecting to. Encrypted Client Hello (ECH, formerly ESNI) encrypts this field, plugging the remaining metadata leak.
ECH is gradually rolling out (Cloudflare supports it, Firefox supports it). When combined with DoH/DoT, it leaves very little DNS and connection metadata visible on the network path.
What DoH/DoT Doesn’t Hide
- IP addresses: Traffic to 140.82.112.4 (GitHub’s IP) is visible even if the hostname lookup was encrypted
- TLS SNI (until ECH is universal): Hostname in TLS handshake
- Connection timing: Patterns of connections reveal behavior even without content
- Authoritative nameserver queries: Your recursive resolver’s queries to authoritative servers are still plaintext (though yours is on a server you control)
DoH/DoT is a meaningful privacy improvement, not a complete solution. Combined with a VPN or Tor for the traffic itself, it closes most passive monitoring vectors.
Putting It All Together: Recommended Homelab Setup
For a homelab that balances privacy, control, and simplicity:
Clients (DoT/DoH) ──→ AdGuard Home ──→ Unbound (recursive, DNSSEC)
│
├── Ad/malware blocking
├── Query logging
└── Split-horizon for local names
1. Deploy Unbound for recursive resolution with DNSSEC validation. Unbound queries root servers directly — no upstream provider involved.
2. Deploy AdGuard Home as the frontend, with:
- Unbound at
127.0.0.1:5300as the upstream - DoT enabled on port 853 with a Let’s Encrypt certificate
- DoH enabled on port 443
- Blocklists for ads and malware
- Rewrites for local hostnames (
nas.home → 192.168.1.50)
3. Configure clients:
- Android: Private DNS →
dns.yourdomain.com - Linux: systemd-resolved DNSOverTLS
- macOS/iOS: Configuration Profile with DoH URL
- Browsers: Custom DoH URL
4. Fallback: Configure 1.1.1.1 as a fallback in case your local resolver is down — encrypted DNS even in degraded states.
The result: all DNS queries from your devices are encrypted in transit, validated against DNSSEC, and filtered for ads and malware. No ISP DNS visibility, no single-provider trust dependency. The phone book is finally sealed.
Comments