
What Is DNS over TLS (DoT), and How Does It Differ from DoH?
If you've ever turned on Android's "Private DNS" setting or configured Unbound to forward securely to an upstream resolver, you've used DNS over TLS (DoT). Like its better-known cousin, DNS over HTTPS, DoT encrypts the queries your device sends to its resolver so nobody on the network can read or tamper with them. The difference is how it gets there: DoT wraps DNS directly in TLS on its own dedicated port, while DoH hides DNS inside ordinary web traffic. That one design choice shapes where each protocol is used, who can see it, and how easy it is to manage.
This article explains how DoT works on the wire, how to test it with kdig, dig, openssl, and Python, how to enable it on Android, Linux, and your own resolver, and a detailed comparison with DoH so you can decide which fits your situation.
How DNS over TLS Works
DoT is specified in RFC 7858. The mechanics are straightforward:
- The client opens a TCP connection to the resolver on port 853, a port reserved specifically for DNS over TLS.
- It performs a TLS handshake, ideally verifying the resolver's certificate against a hostname such as
cloudflare-dns.comordns.google. - Once the encrypted channel is up, it sends standard DNS messages exactly as it would over plain TCP — each message prefixed with a two-byte length field.
- The connection stays open and can carry many queries and responses, which avoids paying the handshake cost for every lookup.
There's no HTTP layer at all. The payload inside TLS is just ordinary DNS-over-TCP, the same format described in RFC 1035 and used when DNS falls back from UDP to TCP. The TLS ALPN identifier for DoT is dot.
Strict versus opportunistic privacy
RFC 8310 defines two usage profiles that matter in practice:
- Strict privacy. The client must authenticate the resolver — usually by validating its certificate against a configured hostname. If authentication fails, the client refuses to send queries. This protects against an active attacker who intercepts port 853 and presents their own certificate.
- Opportunistic privacy. The client tries DoT, but if it can't authenticate the server (or can't connect at all), it falls back to unauthenticated TLS or even plain DNS. This defeats passive eavesdropping but not an active attacker.
Most real-world misconfigurations come down to running opportunistic mode while believing you have strict protection. When you configure DoT, always supply the resolver's authentication hostname.
Testing DoT from the Command Line
Inspect the TLS endpoint with openssl
Before sending any DNS traffic, you can confirm the resolver presents a valid certificate on port 853:
openssl s_client -connect 1.1.1.1:853 -servername cloudflare-dns.com -verify_return_error </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
This opens a TLS connection to Cloudflare's resolver on port 853, sends the expected server name, fails if the certificate chain doesn't verify, and prints the certificate's subject, issuer, and validity dates. The same check is useful for confirming a resolver you run yourself is serving the right certificate.
Query with kdig
Knot DNS's kdig has long had full DoT support, including strict certificate validation:
kdig @1.1.1.1 +tls-ca +tls-hostname=cloudflare-dns.com example.com A
+tls-ca tells kdig to validate the certificate against the system's trusted CA store, and +tls-hostname sets the name it must match. If either check fails, kdig aborts instead of sending the query. Adding -d prints debug output, including the TLS session details.
Query with dig
BIND's dig supports DoT from version 9.18:
dig @1.1.1.1 +tls example.com A
# Strict: validate the certificate and hostname
dig @1.1.1.1 +tls-ca +tls-hostname=cloudflare-dns.com example.com A
The SERVER line at the bottom of the output shows the port 853 connection and (TLS) as the transport. Plain +tls encrypts the query but doesn't verify the server's identity — fine for a quick test, but not equivalent to strict mode.
Query with Python
dnspython supports DoT natively through dns.query.tls():
import ssl
import dns.message
import dns.query
context = ssl.create_default_context() # verifies certificates against system CAs
query = dns.message.make_query("example.com", "A")
response = dns.query.tls(
query,
"1.1.1.1",
timeout=5,
ssl_context=context,
server_hostname="cloudflare-dns.com",
)
for rrset in response.answer:
print(rrset.to_text())
The script creates a standard TLS context that verifies certificates, sends the query to port 853 (the default for dns.query.tls), and checks that the certificate matches cloudflare-dns.com before printing the answer. If the certificate doesn't match, the call raises an ssl.SSLCertVerificationError instead of returning data — strict privacy in a few lines.
Enabling DoT on Devices and Resolvers
Android Private DNS
Android 9 and later include DoT at the system level. Under Settings → Network & internet → Private DNS (the exact path varies slightly by manufacturer), choose Private DNS provider hostname and enter a hostname such as:
one.one.one.one
dns.google
dns.quad9.net
Because you provide a hostname, Android uses strict mode: it validates the resolver's certificate and won't fall back to plain DNS. The default "Automatic" setting is opportunistic — it uses DoT when the network's resolver supports it and plain DNS otherwise. More platform instructions are in how to change DNS settings on Windows, Mac, iPhone, and Android.
Linux with systemd-resolved
Most modern Linux distributions use systemd-resolved, which can forward upstream over DoT. Edit /etc/systemd/resolved.conf:
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com
DNS=2606:4700:4700::1111#cloudflare-dns.com
DNSOverTLS=yes
Then restart and verify:
sudo systemctl restart systemd-resolved
resolvectl status | grep -iE "DNSOverTLS|DNS Servers"
The #cloudflare-dns.com suffix tells systemd-resolved which name to validate on the certificate. DNSOverTLS=yes enforces encryption and fails rather than falling back; opportunistic would allow fallback to plain DNS.
Unbound as a local DoT forwarder
If you run a local resolver — on a server, a router, or alongside Pi-hole — Unbound can forward all queries upstream over DoT, so every device on your network benefits without per-device configuration:
# /etc/unbound/unbound.conf.d/dot-forward.conf
server:
tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt
forward-zone:
name: "."
forward-tls-upstream: yes
forward-addr: 1.1.1.1@853#cloudflare-dns.com
forward-addr: 1.0.0.1@853#cloudflare-dns.com
forward-addr: 9.9.9.9@853#dns.quad9.net
tls-cert-bundle points Unbound at the system CA store (the path shown is for Debian and Ubuntu; Red Hat-based systems use /etc/pki/tls/certs/ca-bundle.crt). In the forward zone, each forward-addr uses the IP@port#hostname format so Unbound connects on port 853 and validates the certificate name. Check the file with unbound-checkconf and reload Unbound after editing.
Unbound can also act as a DoT server for your own clients, using interface: 0.0.0.0@853 along with tls-service-key and tls-service-pem pointing at a certificate and key — useful for providing encrypted DNS to managed devices on your network.
DoT vs DoH: A Detailed Comparison
Both protocols encrypt the same thing — the hop between client and resolver — with the same TLS security. The differences are all about transport and visibility.
| DNS over TLS (DoT) | DNS over HTTPS (DoH) | |
|---|---|---|
| Standard | RFC 7858 (2016) | RFC 8484 (2018) |
| Port | TCP 853 (dedicated) | TCP 443, plus UDP 443 with HTTP/3 |
| Layers | DNS → TLS → TCP | DNS → HTTP/2 or HTTP/3 → TLS or QUIC |
| Visible on the network as DNS? | Yes, by port | No, blends with web traffic |
| Easy to block selectively? | Yes, block port 853 | Only by blocking known resolver endpoints |
| Typical clients | Operating systems, routers, resolvers | Browsers, apps, and now operating systems |
| Configuration | Resolver IP plus authentication hostname | Resolver URL template |
| HTTP caching and proxies | Not applicable | Can use HTTP infrastructure |
| Overhead | Slightly lower — no HTTP framing | Slightly higher, offset by HTTP/2 multiplexing |
What the differences mean in practice
- Network visibility is the big one. Because DoT has its own port, network administrators can see that encrypted DNS is happening, allow it to approved resolvers, and block it to others. DoH is deliberately indistinguishable from browsing. That makes DoT friendlier for managed networks and DoH more resistant to censorship and interference.
- Where it lives. DoT fits naturally at the operating system or resolver level — one secure upstream for all applications. DoH took off first inside browsers, where each application can bring its own resolver, though Windows and Apple platforms now support it system-wide too.
- Reliability on restrictive networks. Some hotel, airline, and corporate networks block port 853 outright. A strict DoT client on such a network simply has no DNS, while DoH on port 443 usually gets through.
- Performance. Both reuse long-lived connections, so after the first handshake the performance difference is negligible. Choose based on deployment fit, not speed.
Where DNS over QUIC fits
A newer option, DNS over QUIC (DoQ), defined in RFC 9250, runs DNS directly over QUIC on UDP port 853. It keeps DoT's dedicated-port, no-HTTP design while gaining QUIC's faster connection setup and better behavior on lossy networks. Support is growing in resolvers and some clients, but DoT and DoH remain far more widely deployed.
Which Should You Use?
- On a phone: Android's Private DNS (DoT) is the simplest way to encrypt DNS for every app. On iOS, use a DoH or DoT configuration profile from your chosen provider.
- On a Linux server or workstation: systemd-resolved or Unbound with DoT upstream is clean, transparent, and easy to audit.
- For a home network: a local resolver (Unbound or Pi-hole with Unbound) forwarding over DoT protects every device, including ones you can't configure.
- In a browser on untrusted networks: DoH, since it's built in and less likely to be blocked.
- On a corporate network: DoT to an approved internal or filtering resolver, with port 853 blocked to everything else, gives you encryption and control together.
Whichever you pick, the resolver you send queries to sees everything, so choose one whose privacy practices you trust. The post on Cloudflare DNS vs Google Public DNS vs Quad9 compares the major options.
DNS over TLS FAQ
DoT uses TCP port 853, which is reserved specifically for DNS over TLS. DNS over QUIC also uses port 853, but over UDP.
No. Both use the same TLS encryption and offer the same protection for the client-to-resolver hop. The difference is visibility: DoT is identifiable by its port, while DoH looks like normal HTTPS traffic.
Some networks block TCP port 853. If your device uses strict DoT, it has no fallback and DNS stops working. Switch to automatic or opportunistic mode, or use DoH on that network.
Strict mode requires the resolver's certificate to match a configured hostname and refuses to fall back to plain DNS. Opportunistic mode uses encryption when possible but falls back if it can't authenticate or connect, which protects only against passive eavesdropping.
Android's Private DNS setting uses DNS over TLS. When you enter a provider hostname, Android validates the resolver's certificate and uses strict mode.
No. Your ISP can see that you're connecting to a DoT resolver on port 853, but not the contents of your queries. It can still see the IP addresses you connect to afterward.
No. DoT protects queries in transit between you and your resolver. DNSSEC proves records came from the domain owner. They solve different problems and work best together.
Yes. Unbound, BIND 9.18 and later, Knot Resolver, and dnsdist can all serve DoT with a TLS certificate. This is common for providing encrypted DNS to devices on a network you manage.
Conclusion
DNS over TLS is the most direct way to encrypt DNS: take the normal DNS-over-TCP protocol, wrap it in TLS, and put it on its own port. That simplicity makes it a natural fit for operating systems, routers, and recursive resolvers, where one encrypted upstream connection can protect every application at once. Its dedicated port is both its strength and its weakness — easy for administrators to manage and permit, but also easy for restrictive networks to block.
DoH solves the same problem by blending into web traffic, which makes it harder to block and easier to embed in browsers, at the cost of visibility for network operators. Neither is more secure than the other. Use DoT where you control the network or want system-wide encryption, use DoH where you need it to work everywhere, and in both cases configure strict authentication so the encryption actually protects you against an active attacker.
These references cover DoT and related encrypted DNS standards in more detail:
- RFC 7858: Specification for DNS over Transport Layer Security (TLS) — the core DoT specification.
- RFC 8310: Usage Profiles for DNS over TLS and DNS over DTLS — defines strict and opportunistic privacy profiles.
- RFC 9250: DNS over Dedicated QUIC Connections — the DNS over QUIC specification.
- Cloudflare Developers: DNS over TLS — Cloudflare's DoT endpoints and client setup examples.
- Unbound Documentation: unbound.docs.nlnetlabs.nl — configuration reference for TLS forwarding and serving DoT.


