Protocols that encrypt DNS queries and responses to prevent eavesdropping and tampering, including DNS over TLS (DoT), DNS over HTTPS (DoH), and DNS over QUIC (DoQ).

Table of Contents#

  1. Overview
  2. Legacy DNS (Unencrypted)
  3. DNS over TLS (DoT)
  4. DNS over HTTPS (DoH)
  5. DNS over QUIC (DoQ)
  6. Protocol Comparison
  7. Implementation Examples
  8. Public Encrypted DNS Providers
  9. Troubleshooting
  10. See Also
  11. Sources

1. Overview#

Since its creation in 1987, DNS has been largely unencrypted. Standard DNS uses UDP port 53 in plaintext, allowing anyone between the client and resolver to observe, log, or modify queries and responses. This enables:

  • Surveillance - ISPs and network operators can see every domain a user visits
  • Censorship - Authorities can block domains by intercepting DNS responses
  • Tampering - Attackers can redirect users by forging DNS responses (DNS spoofing)

Three standardized protocols address this by encrypting DNS traffic:

ProtocolRFCPortTransportYear Standardized
DNS over TLS (DoT)RFC 7858853 (TCP)TLS over TCP2016
DNS over HTTPS (DoH)RFC 8484443 (TCP)HTTPS2018
DNS over QUIC (DoQ)RFC 9250853 (UDP)QUIC2022

All three are based on TLS (1.2 or 1.3) and protect the confidentiality and integrity of DNS messages between the client (stub resolver) and the recursive resolver. They do not encrypt the resolver-to-authoritative path (that is addressed by separate efforts like authoritative DoT/DoH and Oblivious DoH).

Note: DNS encryption protects transport confidentiality. DNSSEC protects data integrity (verifying that records have not been tampered with). They are complementary, not alternatives.

2. Legacy DNS (Unencrypted)#

  +-------------------+
  |   DNS Protocol    |
  +-------------------+
  |   UDP Protocol    |
  |   (Port 53)       |
  +-------------------+
  |   IP Protocol     |
  +-------------------+

Standard DNS sends queries and responses in plaintext over UDP port 53. TCP port 53 is used for responses exceeding 512 bytes (or the EDNS0 buffer size) and for zone transfers (AXFR/IXFR).

Anyone on the network path can:

  • Read the queried domain names
  • Inject forged responses (DNS spoofing)
  • Log query patterns for profiling

3. DNS over TLS (DoT)#

DNS over TLS (RFC 7858) wraps standard DNS messages inside a TLS connection over TCP port 853.

  +-------------------+  --+
  |   DNS Protocol    |    |  encrypted
  +-------------------+    +-- traffic
  |   TLS Protocol    |    |  via TLS
  +-------------------+  --+
  |   TCP Protocol    |
  |   (Port 853)      |
  +-------------------+
  |   IP Protocol     |
  +-------------------+

Characteristics#

  • Dedicated port (853) - Easy to identify and block at the network level, which is both a benefit (network admins can manage it) and a drawback (censors can block it)
  • TLS 1.2 or 1.3 - Standard TLS handshake; TLS 1.3 reduces round trips
  • TCP connection reuse - Multiple queries can be pipelined over a single TLS session
  • Authentication - Clients can validate the resolver's certificate using SPKI pin or hostname verification (RFC 8310, "Strict" mode)

Authentication Modes#

ModeBehaviorSecurity
OpportunisticEncrypt if possible, fall back to plaintext if TLS failsProtection from passive eavesdropping only
StrictRequire valid TLS certificate matching a configured hostname or SPKI pinFull protection from active and passive attacks

4. DNS over HTTPS (DoH)#

DNS over HTTPS (RFC 8484) sends DNS queries as HTTPS requests to a resolver endpoint (typically https://resolver.example/dns-query).

  +-------------------+  --+
  |   HTTP/2 Protocol |    |  encrypted
  +-------------------+    +-- traffic
  |   TLS Protocol    |    |  via HTTPS
  +-------------------+  --+
  |   TCP Protocol    |
  |   (Port 443)      |
  +-------------------+
  |   IP Protocol     |
  +-------------------+

Query Encoding Formats#

DoH supports two message encoding formats:

DNS Wire Format (Binary)#

The standard DNS binary message is sent as the HTTP body:

POST /dns-query HTTP/2
Host: dns.example.com
Content-Type: application/dns-message
Accept: application/dns-message

<binary DNS message>

Or via GET with base64url encoding:

GET /dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB HTTP/2
Host: dns.example.com
Accept: application/dns-message

The dns parameter contains the base64url-encoded DNS wire-format query (no padding).

JSON Format (Non-Standard)#

Some resolvers (notably Google and Cloudflare) support a JSON API, though this is not part of RFC 8484:

GET /dns-query?name=example.com&type=A HTTP/2
Host: dns.example.com
Accept: application/dns-json

Response:

{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": true,
  "Answer": [
    {
      "name": "example.com.",
      "type": 1,
      "TTL": 300,
      "data": "93.184.216.34"
    }
  ]
}

Note: The JSON API is resolver-specific and not standardized. The wire format (application/dns-message) is the standard encoding defined in RFC 8484.

Characteristics#

  • Port 443 - Indistinguishable from regular HTTPS traffic, making it very difficult to block without blocking all HTTPS
  • HTTP/2 multiplexing - Multiple queries share a single connection efficiently
  • CDN-friendly - Can leverage existing HTTPS infrastructure, proxies, and load balancers
  • Browser integration - Supported natively in Firefox, Chrome, Edge, and other browsers

Privacy Considerations#

DoH shifts DNS visibility from the network operator to the DoH resolver operator. This has trade-offs:

  • Benefit: Prevents local network snooping and ISP logging
  • Concern: Concentrates DNS data at the resolver provider (e.g., Cloudflare, Google)
  • Enterprise impact: Makes it harder for network administrators to enforce DNS-based security policies

5. DNS over QUIC (DoQ)#

DNS over QUIC (RFC 9250) uses the QUIC transport protocol to encrypt DNS queries over UDP.

  +-------------------+  --+
  |   DNS Protocol    |    |  encrypted
  +-------------------+    +-- traffic
  |   QUIC Protocol   |    |  via QUIC
  |   (TLS 1.3)       |    |
  +-------------------+  --+
  |   UDP Protocol    |
  |   (Port 853)      |
  +-------------------+
  |   IP Protocol     |
  +-------------------+

Characteristics#

  • Lower latency - QUIC combines the transport and TLS 1.3 handshake into a single round trip (1-RTT), or zero round trips for resumed connections (0-RTT)
  • Port 853 over UDP - Same port as DoT but uses UDP instead of TCP
  • Built-in encryption - QUIC natively includes TLS 1.3; all DNS traffic is encrypted by default
  • Connection migration - QUIC supports seamless connection migration when a client changes networks (e.g., Wi-Fi to mobile), keeping the DNS session alive
  • Head-of-line blocking avoidance - Unlike TCP-based DoT/DoH, a lost packet in one QUIC stream does not block other streams

Server Compatibility#

DoQ adoption is still growing. As of 2026:

  • Resolver support: AdGuard DNS, NextDNS, and several smaller resolvers support DoQ. Cloudflare and Google do not yet offer public DoQ endpoints.
  • Client support: AdGuard, dnscrypt-proxy, and some custom stub resolvers support DoQ. systemd-resolved and most OS-level resolvers do not yet.
  • Server software: dnsdist (PowerDNS) supports DoQ. BIND9 and Unbound do not have native DoQ support yet.

6. Protocol Comparison#

FeatureDoTDoHDoQ
RFC785884849250
Port853/TCP443/TCP853/UDP
EncryptionTLS 1.2/1.3TLS 1.2/1.3TLS 1.3 only
BlockableYes (distinct port)Hard (same as HTTPS)Moderate (distinct port, UDP)
Latency (new connection)2-3 RTT (TCP + TLS)2-3 RTT (TCP + TLS + HTTP)1 RTT (QUIC)
Latency (resumed)1-2 RTT1-2 RTT0-1 RTT
Head-of-line blockingYes (TCP)Yes (TCP)No (QUIC streams)
Connection migrationNoNoYes
Browser supportNoYes (Firefox, Chrome, Edge)No
OS supportWide (Android 9+, systemd-resolved)Moderate (Windows 11, browsers)Limited
Server software supportWide (BIND, Unbound, Knot)Wide (Unbound, dnsdist, nginx)Limited (dnsdist)

7. Implementation Examples#

systemd-resolved (DoT)#

systemd-resolved supports DNS over TLS natively:

# Edit resolved configuration
sudo vi /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 9.9.9.9#dns.quad9.net
FallbackDNS=8.8.8.8#dns.google
DNSOverTLS=yes
DNSSEC=allow-downgrade
# Restart resolved
sudo systemctl restart systemd-resolved

# Verify DoT is active
resolvectl status
# Look for: "DNS over TLS: yes"

# Test resolution
resolvectl query example.com

Options for DNSOverTLS:

ValueBehavior
yesStrict mode, fail if TLS is unavailable
opportunisticUse TLS if available, fall back to plaintext
noDisable DoT

Unbound (DoT and DoH)#

Unbound supports both DoT forwarding and serving DoT/DoH to clients.

Forward Queries over DoT#

# /etc/unbound/unbound.conf
server:
    interface: 127.0.0.1
    access-control: 127.0.0.0/8 allow
    tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt

forward-zone:
    name: "."
    forward-tls-upstream: yes
    # Cloudflare
    forward-addr: 1.1.1.1@853#cloudflare-dns.com
    forward-addr: 1.0.0.1@853#one.one.one.one
    # Quad9
    forward-addr: 9.9.9.9@853#dns.quad9.net

Serve DoT to Clients#

server:
    interface: 0.0.0.0@853
    tls-service-key: /etc/unbound/server.key
    tls-service-pem: /etc/unbound/server.crt
    tls-port: 853

Serve DoH to Clients#

server:
    interface: 0.0.0.0@443
    https-port: 443
    tls-service-key: /etc/unbound/server.key
    tls-service-pem: /etc/unbound/server.crt
    http-endpoint: /dns-query

Knot Resolver (DoT and DoH)#

Knot Resolver supports encrypted DNS natively:

-- /etc/knot-resolver/kresd.conf

-- Listen on DoT
net.listen('0.0.0.0', 853, { kind = 'tls' })
net.listen('0.0.0.0', 443, { kind = 'doh2' })

-- TLS certificates
net.tls('/etc/knot-resolver/server.crt', '/etc/knot-resolver/server.key')

-- Forward over DoT
policy.add(policy.all(policy.TLS_FORWARD({
    {'1.1.1.1', hostname='cloudflare-dns.com'},
    {'9.9.9.9', hostname='dns.quad9.net'},
})))

Testing Encrypted DNS#

# Test DoT with kdig (from knot-dnsutils)
kdig @1.1.1.1 +tls example.com A

# Test DoH with curl (wire format)
curl -s -H "Accept: application/dns-message" \
  "https://cloudflare-dns.com/dns-query?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE" \
  | python3 -c "import sys; data=sys.stdin.buffer.read(); print(data.hex())"

# Test DoH with curl (JSON, Cloudflare-specific)
curl -s -H "Accept: application/dns-json" \
  "https://cloudflare-dns.com/dns-query?name=example.com&type=A" | jq .

# Test DoQ with q (DNS client)
q example.com A @quic://dns.adguard-dns.com

# Verify no plaintext DNS leaks
sudo tcpdump -n port 53 -c 10
# Should show no traffic if encrypted DNS is working

8. Public Encrypted DNS Providers#

ProviderDoTDoHDoQ
Cloudflare (1.1.1.1)1.1.1.1:853https://cloudflare-dns.com/dns-queryNo
Google (8.8.8.8)8.8.8.8:853https://dns.google/dns-queryNo
Quad9 (9.9.9.9)9.9.9.9:853https://dns.quad9.net/dns-queryNo
AdGuard94.140.14.14:853https://dns.adguard-dns.com/dns-queryquic://dns.adguard-dns.com
NextDNS<config-id>.dns.nextdns.io:853https://dns.nextdns.io/<config-id>quic://<config-id>.dns.nextdns.io
Mullvad194.242.2.2:853https://dns.mullvad.net/dns-queryNo

Troubleshooting#

IssueCauseSolution
DoT connection refusedPort 853 blocked by firewall or ISPTry DoH on port 443 instead; check firewall rules
Slow DNS resolution after enabling DoT/DoHTLS handshake overhead on every queryEnsure connection reuse is enabled; use a local caching resolver (Unbound, systemd-resolved)
DNSSEC validation failures over DoHResolver not returning DNSSEC recordsSet Accept: application/dns-message (not JSON); enable do flag in queries
systemd-resolved falls back to plaintextDNSOverTLS=opportunistic and TLS failedSet DNSOverTLS=yes for strict mode; check journalctl -u systemd-resolved for errors
DoH not working in browserWrong resolver URL or certificate errorVerify the DoH URL; ensure system clock is correct (TLS certificate validation)
DoQ connection timeoutServer does not support DoQ or UDP 853 blockedVerify server supports DoQ; check that UDP port 853 is open
Queries work but responses are slowResolver is geographically distantChoose a resolver with nearby anycast presence
certificate verify failed on DoTMissing or outdated CA bundleUpdate tls-cert-bundle path; run update-ca-certificates

See Also#

Sources#