Implementing DNS-over-HTTPS (DoH) for Home Networks
Complete guide to deploying DNS-over-HTTPS on your home network for enhanced privacy and security, with multiple implementation approaches
The ISP Letter That Started Everything
A few years back, I became aware that many ISPs monetize DNS query data for targeted advertising. This privacy concern motivated me to research DNS-over-HTTPS implementations.
After implementing DoH on my personal home network, I've achieved complete DNS privacy. The ISP only sees encrypted HTTPS traffic, protecting browsing patterns from commercial exploitation.
Requirements
To run the code examples in this post, you'll need to install the following packages:
pip install base64 dns hashlib requests ssl statistics
Or create a requirements.txt
file:
base64
dns
hashlib
requests
ssl
statistics
If you're tired of being the product, here's how to take back control of your DNS privacy. It's easier than you think, and I'll show you three different ways to do it.
How It Works
graph TB
subgraph "Threat Actors"
TA1[External Attackers]
TA2[Insider Threats]
TA3[Supply Chain]
end
subgraph "Attack Vectors"
AV1[Network]
AV2[Application]
AV3[Physical]
end
subgraph "Defenses"
D1[Prevention]
D2[Detection]
D3[Response]
end
TA1 & TA2 & TA3 --> AV1 & AV2 & AV3
AV1 & AV2 & AV3 --> D1
D1 -->|Bypass| D2
D2 --> D3
style D1 fill:#4caf50
style D2 fill:#ff9800
style D3 fill:#f44336
Understanding the DNS Privacy Problem
Traditional DNS has several privacy and security issues:
- Plain Text Queries: ISPs and network observers see all DNS lookups
- DNS Hijacking: Malicious actors can redirect your traffic
- ISP Monetization: Many ISPs sell DNS query data
- Censorship: DNS blocking is a common censorship technique
- Man-in-the-Middle: Unencrypted DNS is vulnerable to tampering
DNS-over-HTTPS solves these by:
- Encrypting all DNS queries with HTTPS
- Authenticating the DNS server
- Hiding DNS queries from network observers
- Preventing DNS-based censorship and filtering
Implementation Approaches
I'll cover three approaches, from simple to advanced:
- Device-Level: Configure individual devices
- Router-Level: Protect your entire network
- Self-Hosted: Maximum control and privacy
Approach 1: Device-Level DoH
Browser Configuration
Most modern browsers support DoH natively:
Firefox:
// about:config settings
network.trr.mode = 2 // Enable DoH with fallback
network.trr.uri = "https://cloudflare-dns.com/dns-query"
network.trr.bootstrapAddress = "1.1.1.1"
Chrome/Edge:
Settings → Privacy and Security → Security → Use secure DNS
Select provider or enter custom: https://dns.google/dns-query
System-Wide DoH on Linux
For system-wide protection, I use cloudflared
:
# Install cloudflared
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
# Configure as DNS proxy
# ... (additional implementation details)
sudo systemctl restart systemd-resolved
Windows DoH Setup
Windows 11 has native DoH support:
# Enable DoH for network adapter
netsh dns add encryption server=1.1.1.1 dohtemplate=https://cloudflare-dns.com/dns-query
netsh dns add encryption server=8.8.8.8 dohtemplate=https://dns.google/dns-query
# Configure network adapter to use DoH
# GUI: Settings → Network → Ethernet/WiFi → DNS server assignment → Manual
# Set preferred DNS encryption to "Encrypted only"
Approach 2: Router-Level DoH
Protecting your entire network requires a DoH-capable router or custom firmware.
Using Dream Machine Professional
Dream Machine Professional doesn't natively support DoH, but we can use a clever workaround:
# Install required packages in Dream Machine Professional
pkg install dnscrypt-proxy2
# Configure dnscrypt-proxy for DoH
cat > /usr/local/etc/dnscrypt-proxy/dnscrypt-proxy.toml << 'EOF'
# ... (additional implementation details)
# DNS Servers: 127.0.0.1:5353
# Uncheck "Allow DNS server list to be overridden"
OpenWrt with DoH
OpenWrt makes DoH implementation straightforward:
# Install packages
opkg update
opkg install https-dns-proxy luci-app-https-dns-proxy
# Configure DoH providers
# ... (additional implementation details)
uci commit dhcp
/etc/init.d/dnsmasq restart
Approach 3: Self-Hosted DoH Server
For maximum privacy and control, run your own DoH server:
Pi-hole with DoH
Transform Pi-hole into a DoH server:
# Install Pi-hole (if not already installed)
curl -sSL https://install.pi-hole.net | bash
# Install cloudflared for DoH upstream
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64
# ... (additional implementation details)
# Custom 1: 127.0.0.1#5053
# Uncheck all other DNS servers
Advanced: DoH Server with nginx
Serve DoH directly to clients using nginx and dnsdist:
# Install required packages
sudo apt-get update
sudo apt-get install -y nginx dnsdist certbot python3-certbot-nginx
# Configure dnsdist
# ... (additional implementation details)
sudo nginx -t && sudo systemctl restart nginx
sudo systemctl enable dnsdist && sudo systemctl start dnsdist
Monitoring and Validation
Verify DoH is Working
# Test using curl
curl -H 'content-type: application/dns-message' \
--data-binary @<(echo -n 'q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB' | base64 -d) \
https://cloudflare-dns.com/dns-query | hexdump -C
# Test using dog (better than dig for DoH)
dog example.com @https://cloudflare-dns.com/dns-query
# Check for DNS leaks
# Visit: https://dnsleaktest.com
# Should only show your configured DoH provider
Performance Monitoring
#!/usr/bin/env python3
import time
import dns.resolver
import requests
from statistics import mean, stdev
# ... (additional implementation details)
benchmark_dns(traditional_dns_query, test_domains, "Traditional DNS")
benchmark_dns(doh_query, test_domains, "DNS-over-HTTPS")
Logging and Analytics
# Parse dnscrypt-proxy logs
cat << 'EOF' > /usr/local/bin/analyze-doh-logs.sh
#!/bin/bash
LOG_FILE="/var/log/dnscrypt-proxy/query.log"
# ... (additional implementation details)
chmod +x /usr/local/bin/analyze-doh-logs.sh
Security Considerations
1. DoH Provider Selection
Not all DoH providers are equal. Consider:
Provider Comparison:
Cloudflare (1.1.1.1):
Privacy: Excellent (audited no-logs policy)
Performance: Fastest globally
Features: Malware blocking option (1.1.1.2)
# ... (additional implementation details)
Performance: Good
Features: Extensive filtering options
2. Preventing DoH Bypass
Ensure all DNS queries use DoH:
# iptables rules to force DoH
# Block standard DNS (port 53) except from DoH proxy
iptables -A OUTPUT -p udp --dport 53 -m owner ! --uid-owner cloudflared -j DROP
iptables -A OUTPUT -p tcp --dport 53 -m owner ! --uid-owner cloudflared -j DROP
# Block DNS-over-TLS (port 853)
iptables -A OUTPUT -p tcp --dport 853 -j DROP
# Allow only DoH proxy to make HTTPS connections to DNS providers
iptables -A OUTPUT -p tcp --dport 443 -d 1.1.1.1 -m owner ! --uid-owner cloudflared -j DROP
iptables -A OUTPUT -p tcp --dport 443 -d 8.8.8.8 -m owner ! --uid-owner cloudflared -j DROP
3. Certificate Pinning
For self-hosted DoH, implement certificate pinning:
import ssl
import hashlib
import base64
class SecureDoHClient:
# ... (additional implementation details)
return context
Troubleshooting Common Issues
1. Slow Initial Queries
# Implement DNS caching
# For dnsmasq
echo "cache-size=10000" >> /etc/dnsmasq.conf
echo "min-cache-ttl=3600" >> /etc/dnsmasq.conf
# For systemd-resolved
[Resolve]
Cache=yes
CacheLimit=2048
2. Connection Timeouts
# Increase timeout values
# cloudflared config
timeout: 10s
max-upstream-conns: 5
# Multiple upstream servers for redundancy
proxy-dns-upstream:
- https://1.1.1.1/dns-query
- https://1.0.0.1/dns-query
- https://dns.quad9.net/dns-query
3. Corporate Network Compatibility
Some corporate networks block DoH. Implement fallback:
# Detect corporate network and adjust
if ping -c 1 corp-gateway.local > /dev/null 2>&1; then
echo "Corporate network detected, using standard DNS"
systemctl stop cloudflared
else
systemctl start cloudflared
fi
Advanced Configurations
Load Balancing Multiple DoH Providers
upstream doh_providers {
server 1.1.1.1:443 weight=3;
server dns.google:443 weight=2;
server dns.quad9.net:443 weight=1;
keepalive 32;
}
Geo-based DoH Selection
def select_doh_provider(client_ip):
"""Select optimal DoH provider based on location"""
# Simplified geo-detection
if client_ip.startswith('192.168.'):
return "https://local-doh.home.arpa/dns-query"
elif is_asian_ip(client_ip):
return "https://dns.google/dns-query" # Better in Asia
else:
return "https://cloudflare-dns.com/dns-query" # Global default
The Bottom Line: Is DoH Worth It?
After running DoH for years, here's what changed for me:
The Good:
- ISP can't sell my browsing habits anymore (take that, "anonymous" marketing data)
- No more DNS hijacking to ISP "search assistance" pages
- Kids' devices automatically protected from DNS-based malware
- That warm fuzzy feeling of actual privacy
The Annoying:
- Some corporate networks break (had to create a work profile that disables DoH)
- Slightly slower initial connections (we're talking 10-20ms)
- Explaining to family why "the internet is broken" when DoH server is down
- Captive portals at coffee shops require temporary disabling
My Verdict: Absolutely worth it. The privacy gains far outweigh the minor inconveniences.
Your Next Steps
Don't try to boil the ocean. Here's your weekend project path:
- Right now (5 minutes): Enable DoH in your browser. Just do it.
- This weekend (2 hours): Set up Pi-hole with DoH on a Raspberry Pi
- Next month: Configure your router for network-wide protection
- Eventually: Consider self-hosting if you're a control freak like me
Remember: DNS privacy is just one piece of the puzzle. But it's a big piece. Every DNS query you encrypt is data your ISP can't monetize, a profile that can't be built, and a step toward the internet we deserve.
The internet was built on open protocols, but that doesn't mean we have to accept surveillance as the price of connectivity.
Take back your DNS privacy. This weekend. I'll wait.
Further Reading
For more in-depth information on the topics covered in this post:
Running DoH in production? Hit me up to share experiences and optimization tips. Privacy is a community effort!
Related Posts
Vulnerability Management at Scale with Open Source Tools
Build an enterprise-grade vulnerability management program using only open source tools. From scanni...
eBPF for Security Monitoring: A Practical Guide
Learn how to leverage eBPF for real-time security monitoring in Linux environments with practical ex...
Building a Security Mindset: Lessons from the Field
After 15+ years in cybersecurity, here are the key lessons about developing a security-first mindset...