DNS Security Guide
A comprehensive reference for Manjaro Linux and openSUSE Tumbleweed
1. Understanding What You're Configuring
Security Features Enabled
- DNS over TLS (DoT): Encrypts DNS queries between your system and DNS resolver using TCP port 853
- DNSSEC: Validates cryptographic signatures on DNS responses to detect tampering
- ECH (Encrypted Client Hello): Hides website names during TLS handshake (Firefox-specific)
- Privacy hardening: Disables LLMNR and mDNS to prevent local network information leaks
Important Limitations
- Your ISP can still see: Destination IP addresses you connect to
- Your DNS provider sees: All your DNS queries (choose a trusted provider)
- ECH availability: Depends on website, CDN, resolver, and browser support
- Not a VPN: This doesn't hide your traffic or location
2. Initial Diagnosis
Check current DNS configuration
# View resolver status
resolvectl status
# Check DNS resolution
resolvectl query www.cloudflare.com
# List network interfaces
ip addr show
# Show active NetworkManager connections
nmcli connection show --active
# Verify IPv6 status (0=enabled, 1=disabled)
cat /proc/sys/net/ipv6/conf/all/disable_ipv6
Test for DNS leaks (plaintext traffic)
First, identify your network interface:
ip route get 1.1.1.1
# Look for "dev <interface>" (e.g., enp42s0, wlan0)
Then monitor for unencrypted DNS:
# Replace <interface> with your actual interface name
sudo timeout 15 tcpdump -ni <interface> 'port 53' &
sleep 2
resolvectl flush-caches
resolvectl query www.cloudflare.com
wait
# Expected result: "0 packets captured" if DoT is working
Verify systemd-resolved status
systemctl is-active systemd-resolved
readlink -f /etc/resolv.conf
# Should point to: /run/systemd/resolve/stub-resolv.conf
3. Base Configuration (All Users)
Step 1: Enable systemd-resolved
sudo systemctl enable --now systemd-resolved
Step 2: Configure stub resolver (critical)
# Force /etc/resolv.conf to use the stub resolver
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
# Verify
readlink -f /etc/resolv.conf
Why this matters: Without the stub resolver, applications may bypass your DoT configuration and use plaintext DNS.
Step 3: Configure NetworkManager (if you use it)
# Check if NetworkManager is active
systemctl is-active NetworkManager
# Configure NetworkManager to use systemd-resolved
sudo mkdir -p /etc/NetworkManager/conf.d
sudo nano /etc/NetworkManager/conf.d/10-dns-systemd-resolved.conf
Add:
[main]
dns=systemd-resolved
Save and restart:
sudo systemctl restart NetworkManager
4. DNS Provider Configuration
Find your connection name
nmcli connection show
# Note the NAME column (e.g., "Wired connection 1", "Main")
Option A: IPv4 + IPv6 (Dual Stack)
When to use: If your ISP supports IPv6 (test with ping -6 2606:4700:4700::1111)
Configure NetworkManager
# Replace "Main" with your connection name
nmcli connection modify "Main" ipv6.method auto
nmcli connection modify "Main" ipv4.dns ""
nmcli connection modify "Main" ipv6.dns ""
nmcli connection modify "Main" ipv4.ignore-auto-dns yes
nmcli connection modify "Main" ipv6.ignore-auto-dns yes
nmcli connection up "Main"
Configure systemd-resolved
sudo mkdir -p /etc/systemd/resolved.conf.d
sudo nano /etc/systemd/resolved.conf.d/secure-dns.conf
Add this configuration:
[Resolve]
# Cloudflare (primary) + Quad9 (fallback with malware filtering)
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com
FallbackDNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net
# Enable encryption and validation
DNSOverTLS=yes
DNSSEC=true
# Route all DNS through configured servers
Domains=~.
# Disable local network protocols
LLMNR=no
MulticastDNS=no
Option B: IPv4 Only
When to use: If your ISP doesn't support IPv6 or you experience IPv6 connectivity issues
Disable IPv6
# Replace "Main" with your connection name
nmcli connection modify "Main" ipv6.method disabled
nmcli connection modify "Main" ipv4.dns ""
nmcli connection modify "Main" ipv4.ignore-auto-dns yes
nmcli connection up "Main"
Configure systemd-resolved
sudo mkdir -p /etc/systemd/resolved.conf.d
sudo nano /etc/systemd/resolved.conf.d/secure-dns.conf
Add this configuration:
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com
FallbackDNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net
DNSOverTLS=yes
DNSSEC=true
Domains=~.
LLMNR=no
MulticastDNS=no
Apply changes
sudo systemctl restart systemd-resolved
resolvectl flush-caches
5. Alternative DNS Providers
Replace the DNS= line in your configuration with one of these:
Cloudflare Options
# Standard (no filtering)
DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com
# Malware blocking (1.1.1.2)
DNS=1.1.1.2#security.cloudflare-dns.com 1.0.0.2#security.cloudflare-dns.com
# Malware + adult content blocking (1.1.1.3)
DNS=1.1.1.3#family.cloudflare-dns.com 1.0.0.3#family.cloudflare-dns.com
Other Providers
# Quad9 (malware/phishing blocking)
DNS=9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net
# Google Public DNS (no filtering)
DNS=8.8.8.8#dns.google 8.8.4.4#dns.google
# AdGuard (ad blocking)
DNS=94.140.14.14#dns.adguard-dns.com 94.140.15.15#dns.adguard-dns.com
# Control D (unfiltered)
DNS=76.76.2.0#p0.freedns.controld.com 76.76.10.0#p0.freedns.controld.com
Important: The #hostname suffix is required for certificate validation in strict DoT mode.
6. Verification and Testing
Check resolver configuration
resolvectl status
Look for:
- Current DNS Server: Should show your configured servers with
#hostname - Protocols: Should indicate
+DNSOverTLSandDNSSEC=yes/supported - DNS Domain: Should show
~.
Test DNS resolution
resolvectl flush-caches
resolvectl query cloudflare.com
Expected output should include:
Data is authenticated: yes(for DNSSEC-signed domains)
Critical: Verify no plaintext DNS leaks
# Monitor port 53 (traditional DNS uses UDP/53; should be silent)
sudo timeout 15 tcpdump -ni <interface> 'port 53' &
sleep 2
resolvectl flush-caches
resolvectl query www.cloudflare.com
resolvectl query github.com
wait
# Expected: "0 packets captured"
Verify encrypted DNS traffic
# Monitor port 853 (DoT uses TCP/853; should show activity)
sudo timeout 15 tcpdump -ni <interface> 'tcp port 853' &
sleep 2
resolvectl flush-caches
resolvectl query www.cloudflare.com
wait
# Expected: packets captured on port 853
Test DNSSEC validation
# Valid DNSSEC domain (should work)
resolvectl query cloudflare.com
# Intentionally broken DNSSEC (should fail)
resolvectl query dnssec-failed.org
# Expected: SERVFAIL or validation error
7. Firefox Configuration for ECH
Enable DNS over HTTPS
- Open Firefox and go to:
about:preferences#privacy - Scroll to DNS over HTTPS
- Select Max Protection
- Choose Cloudflare as provider
Note: Firefox DoH operates independently of system DNS. When enabled, Firefox uses its own encrypted DNS path.
Verify ECH is enabled
- Type in address bar:
about:config - Accept the warning
- Search for:
network.dns.echconfig.enabled - Ensure value is: true
Optional (for HTTP/3 support):
network.dns.http3_echconfig.enabled → true
Test ECH functionality
Visit: https://www.cloudflare.com/ssl/encrypted-sni/
Expected green checkmarks:
- ✅ Secure DNS
- ✅ DNSSEC
- ✅ TLS 1.3
- ✅ Secure SNI (ECH)
Important: Not all websites support ECH. Green checkmarks for all tests depend on the specific website, CDN, and configuration.
8. Troubleshooting
DNS resolution fails
# Check service status
sudo systemctl status systemd-resolved
# View recent logs
sudo journalctl -u systemd-resolved -n 50
# Restart services
sudo systemctl restart systemd-resolved
sudo systemctl restart NetworkManager
resolvectl flush-caches
Verify no conflicting DNS services
# Check what's listening on port 53
sudo ss -tulpn | grep ':53'
# Should only show systemd-resolved on 127.0.0.53
Reset DNS configuration
# Clear NetworkManager DNS settings
nmcli connection modify "Main" ipv4.dns ""
nmcli connection modify "Main" ipv6.dns ""
nmcli connection up "Main"
# Reset systemd-resolved
sudo systemctl restart systemd-resolved
resolvectl reset-server-features
resolvectl flush-caches
DNSSEC validation issues
If DNSSEC causes problems (some routers interfere):
sudo nano /etc/systemd/resolved.conf.d/secure-dns.conf
Temporarily change:
DNSSEC=allow-downgrade
View detailed statistics
resolvectl statistics
9. openSUSE Tumbleweed Specific Notes
NetworkManager vs Wicked
openSUSE may use wicked instead of NetworkManager by default.
Check which is active:
systemctl is-active NetworkManager
systemctl is-active wicked
If using NetworkManager
All commands in this guide work identically.
If using wicked
The nmcli commands won't work. Instead:
# Find your interface configuration
ls /etc/sysconfig/network/
# Edit the interface config (example: ifcfg-eth0)
sudo nano /etc/sysconfig/network/ifcfg-eth0
Remove or comment out DNS-related lines:
#NAMESERVER=
#BOOTPROTO=dhcp4 # Change to dhcp if using IPv4 only
Configure netconfig for systemd-resolved
sudo nano /etc/sysconfig/network/config
Find and modify:
NETCONFIG_DNS_POLICY="STATIC systemd-resolved"
Apply changes:
sudo netconfig update -f
sudo systemctl restart wicked
sudo systemctl restart systemd-resolved
Package installation differences
# Install diagnostic tools on openSUSE
sudo zypper install bind-utils tcpdump
# Compare with Manjaro/Arch
sudo pacman -S bind-tools tcpdump
10. Security Checklist
After configuration, verify all security features:
# 1. Check DNS servers
resolvectl status | grep -i "DNS Server"
# Should show: 1.1.1.1#cloudflare-dns.com (or your chosen provider)
# 2. Check protocols
resolvectl status | grep -iE "^\s*(DNS Over TLS|DNSSEC)"
# Should show: DNSOverTLS=yes and DNSSEC=yes/supported
# 3. Verify stub resolver
readlink -f /etc/resolv.conf
# Should be: /run/systemd/resolve/stub-resolv.conf
# 4. Test for DNS leaks (critical)
sudo timeout 10 tcpdump -ni <interface> 'port 53' & sleep 2; resolvectl flush-caches; resolvectl query github.com; wait
# 5. Verify encrypted DNS
sudo timeout 10 tcpdump -ni <interface> 'tcp port 853' & sleep 2; resolvectl flush-caches; resolvectl query github.com; wait
# Should show: packets captured
# 6. Test DNSSEC
resolvectl query cloudflare.com
# Should show: authenticated: yes
# 7. Test ECH in Firefox
# Visit: https://www.cloudflare.com/ssl/encrypted-sni/
11. What You've Achieved
| Feature | Status |
|---|---|
| DNS Encryption (DoT) | ✅ Port 853, TLS encrypted |
| DNSSEC Validation | ✅ Cryptographic integrity |
| Privacy Protection | ✅ LLMNR/mDNS disabled |
| Router DNS Bypass | ✅ Direct to chosen provider |
| Zero Plaintext DNS | ✅ Verified by tcpdump |
| Secure Fallback | ✅ Secondary provider configured |
| Firefox ECH | ✅ Website name encryption |
| Dual-stack Ready | ✅ IPv4 + IPv6 when available |
12. Additional Resources
Online Testing
- DNS leak test: https://dnsleaktest.com/
- DNSSEC validator: https://dnssec.vs.uni-due.de/
- ECH test: https://www.cloudflare.com/ssl/encrypted-sni/
- Cloudflare diagnostics: https://1.1.1.1/help
Documentation
- systemd-resolved manual: https://www.freedesktop.org/software/systemd/man/latest/systemd-resolved.service.html
- RFC 7858 (DoT): https://datatracker.ietf.org/doc/html/rfc7858
- RFC 4033-4035 (DNSSEC): https://datatracker.ietf.org/doc/html/rfc4033
- DNS providers:
- Cloudflare: https://1.1.1.1/
- Quad9: https://www.quad9.net/
- AdGuard: https://adguard-dns.io/
Advanced Tools
# Install kdig for DoT-aware DNS queries
# Manjaro/Arch:
sudo pacman -S knot
# openSUSE:
sudo zypper install knot-utils
# Test DoT directly
kdig +tls @1.1.1.1 cloudflare.com
Key Technical Notes
DoT vs DoH: This guide uses DoT (DNS over TLS, port 853, RFC 7858) for system-wide encryption. Firefox uses DoH (DNS over HTTPS, port 443) independently when configured, primarily to enable ECH support.
DNSSEC limitations: Provides validation of DNS data integrity but doesn't encrypt queries. Always use DNSSEC with DoT for both encryption and validation.
ECH requirements: Requires DoH in Firefox, website/CDN support, and TLS 1.3. Not all sites support it yet.
The #hostname requirement: When using strict DoT (DNSOverTLS=yes), you must include the hostname for TLS certificate validation (e.g., 1.1.1.1#cloudflare-dns.com). Without it, certificate verification fails.
Port 53 warning: Any tool that queries a specific IP directly (like dig @1.1.1.1) bypasses DoT and uses plaintext DNS. Use resolvectl or kdig +tls for encrypted testing.