DNS poisoning represents one of the most common censorship techniques employed by governments and network administrators to block access to specific websites or services. When you type a domain name into your browser, your device performs a DNS lookup to translate that human-readable address into an IP address. In censored networks, intercepting and manipulating these lookups allows blockers to redirect users away from forbidden content or simply return no result at all.
Encrypted DNS protocols—primarily DNS-over-HTTPS (DoH) and DNS-over-TLS (DoT)—solve this problem by encrypting your DNS queries so network operators cannot see or manipulate them. This guide walks you through setting up encrypted DNS on various platforms, with practical configurations you can implement immediately.
Understanding DNS Poisoning
Traditional DNS queries travel in plaintext across the network. Anyone in the communication path—your ISP, government surveillance systems, or WiFi hotspot operators—can intercept these packets and modify the responses. This technique, called DNS cache poisoning or DNS spoofing, works by injecting false records into the DNS resolver’s cache.
In practice, DNS poisoning manifests as:
- Domain names failing to resolve (NXDOMAIN errors)
- Domains resolving to incorrect IP addresses
- Certain websites becoming completely inaccessible
Countries with extensive internet censorship, including China, Iran, Russia, and Turkey, actively employ DNS poisoning alongside other filtering techniques. TheEncrypting your DNS queries prevents this interception by ensuring only your chosen DNS resolver can see and respond to your requests.
DNS-over-HTTPS (DoH) Configuration
DoH wraps DNS queries in HTTPS traffic, making them indistinguishable from regular web browsing. This provides both encryption and obfuscation—network observers cannot even tell you’re performing DNS lookups.
Using curl for DoH Testing
Before configuring your system, you can test DoH resolution manually using curl:
# Query Cloudflare DoH
curl -sH 'accept: application/dns-json' \
'https://cloudflare-dns.com/dns-query?name=example.com&type=A' \
--resolve cloudflare-dns.com:443:104.16.249.249
This command sends a DNS query to Cloudflare’s DoH endpoint and returns JSON-formatted DNS records. The --resolve flag ensures curl connects to the correct IP, bypassing any local DNS poisoning.
System-Level DoH Configuration
On macOS:
# Set DoH via networksetup (example for Wi-Fi service)
networksetup -setdnsservers "Wi-Fi" "https://dns.google/dns-query"
networksetup -setwebproxystate "Wi-Fi" off
On Linux with systemd-resolved:
Edit /etc/systemd/resolved.conf:
[Resolve]
DNS=1.1.1.1#dns.cloudflare.com
DNSOverHTTPS=1
DNSSEC=yes
Then restart the service:
sudo systemctl restart systemd-resolved
On Windows:
Navigate to Settings → Network & Internet → Wi-Fi → Hardware Properties → Edit DNS settings, and add these DoH servers:
- Preferred:
1.1.1.1(Cloudflare) - Alternate:
8.8.8.8(Google)
DNS-over-TLS (DoT) Configuration
DoT uses TLS encryption directly on port 853, creating a dedicated encrypted channel for DNS queries. While slightly less obfuscated than DoH (the TLS handshake is visible on the wire), DoT offers broader compatibility with existing DNS infrastructure.
Testing DoT with openssl
Verify a DoT server’s availability:
openssl s_client -connect dns.google:853 -servername dns.google </dev/null
A successful connection returns certificate information and confirms the server accepts DoT connections.
DoT Configuration Examples
Using the getent utility:
# Install getent with DoT support
# On Debian/Ubuntu: sudo apt install dnsutils
# Query using DoT
dig @dns.google +tls +short example.com A
Python implementation for custom applications:
import socket
import ssl
def query_dot(hostname, query_type='A'):
"""Query DNS over TLS directly."""
context = ssl.create_default_context()
with socket.create_connection(('dns.google', 853)) as sock:
with context.wrap_socket(sock, server_hostname='dns.google') as ssock:
# Construct DNS query (simplified)
domain = hostname.encode() + b'\x00'
qtype = b'\x00\x01' # A record
# Build DNS message
transaction_id = b'\x00\x01'
flags = b'\x01\x00'
qdcount = b'\x00\x01'
ancount = b'\x00\x00'
nscount = b'\x00\x00'
arcount = b'\x00\x00'
dns_query = (transaction_id + flags + qdcount + ancount
+ nscount + arcount + domain + qtype + b'\x00\x00\x01')
ssock.send(dns_query)
response = ssock.recv(4096)
return response
# Example usage
result = query_dot('example.com')
print(f"Response length: {len(result)} bytes")
Choosing Your DNS Resolver
Selecting a trustworthy DNS resolver matters significantly. Your chosen resolver sees all your DNS queries, so opt for providers with strong privacy policies.
| Provider | DoH Endpoint | DoT Hostname | Logging Policy |
|---|---|---|---|
| Cloudflare | cloudflare-dns.com | 1dot1dot1dot1.cloudflare-dns.com | No logging |
| dns.google | dns.google | Minimal (24h) | |
| Quad9 | dns.quad9.net:5053 | dns.quad9.net | No personal data |
| NextDNS | dns.nextdns.io | dns.nextdns.io | Configurable |
For maximum privacy, consider running your own DoH resolver using technologies like AdGuard Home or Pi-hole, which can be deployed on a Raspberry Pi or cloud VPS.
Advanced: Obfsproxy for Additional Obfuscation
In extremely restrictive environments where DoH itself might be blocked, additional obfuscation layers help. The obfsproxy project wraps traffic in obfuscation protocols:
# Install obfs4
pip install obfs4
# Create obfs4 bridge configuration
obfs4proxy -nodeID 0000000000000000000000000000000000000000 \
-privateKey /path/to/private.key \
-cert 0000000000000000000000000000000000000000+0000000000000000000000000000000000000000= \
-bindAddr 0.0.0.0:443 \
-extORPort auto
This runs an obfs4 bridge accepting connections on port 443, making encrypted DNS traffic appear as random noise to deep packet inspection systems.
Verifying Your Configuration
After configuration, verify your DNS queries are actually encrypted:
-
Browser-based verification: Visit https://dnsleaktest.com to confirm your DNS resolver matches your configured provider.
-
Command-line verification:
# Check which DNS server your system is using
scutil --dns | grep 'resolver'
# For DoH, capture traffic and confirm encryption
sudo tcpdump -i any -A port 443 | grep -i cloudflare
Encrypted DNS should show only TLS handshake traffic with no readable DNS content in plaintext packets.
Limitations and Considerations
Encrypted DNS addresses DNS poisoning but does not make you invisible online. Your browsing activity still traverses your ISP’s network, and they can see the IP addresses you connect to. For privacy, combine encrypted DNS with a VPN or Tor network.
Additionally, some networks implement SNI (Server Name Indication) filtering, which can block access to DoH servers by inspecting HTTPS handshake metadata. In these cases, VPN-based solutions provide more circumvention.
Related Articles
- How To Set Up Dnscrypt Proxy For Authenticated Encrypted Dns
- How to Set Up Encrypted DNS-over-HTTPS (DoH) on All Devices
- Set Up DNS-Based Ad Blocking on Travel Router GL-Inet for
- How to Set Up Private DNS on Android for All Apps
- Encrypted Dns Messaging Combination How To Layer Privacy Pro
Built by theluckystrike — More at zovo.one