Skip to main content

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 +DNSOverTLS and DNSSEC=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

  1. Open Firefox and go to: about:preferences#privacy
  2. Scroll to DNS over HTTPS
  3. Select Max Protection
  4. 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

  1. Type in address bar: about:config
  2. Accept the warning
  3. Search for: network.dns.echconfig.enabled
  4. 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

FeatureStatus
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

Documentation

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.