dotlinux guide

Understanding DNS Resolver Configuration on Linux Systems

The Domain Name System (DNS) is the backbone of the internet, translating human-readable domain names (e.g., example.com) into machine-readable IP addresses (e.g., 93.184.216.34). A DNS resolver is a critical client-side component that initiates and manages these translation requests. On Linux systems, configuring the DNS resolver properly ensures reliable, fast, and secure name resolution—essential for everything from web browsing to server communication. This blog explores DNS resolver configuration on Linux in depth, covering fundamental concepts, key configuration files, practical usage methods, common practices, and best practices. Whether you’re a system administrator, developer, or Linux enthusiast, this guide will help you master resolver setup and troubleshooting.

Table of Contents

  1. Fundamental Concepts
  2. Key Configuration Files
  3. Usage Methods
  4. Common Practices
  5. Best Practices
  6. Troubleshooting Common Issues
  7. Conclusion
  8. References

Fundamental Concepts

What is a DNS Resolver?

A DNS resolver (or “recursive resolver”) is software running on your Linux system that acts as an intermediary between client applications (e.g., browsers, curl) and DNS authoritative servers. Its primary role is to:

  1. Accept domain name queries from applications.
  2. Recursively query authoritative DNS servers to resolve the domain to an IP.
  3. Cache results to speed up future queries.

Linux systems typically use resolvers like systemd-resolved, dnsmasq, or the legacy BIND resolver. Modern distributions often default to systemd-resolved for integration with systemd services.

How DNS Resolution Works

DNS resolution follows a step-by-step process:

  1. Local Cache Check: The resolver first checks its local cache for a recent entry. If found, it returns the IP immediately.
  2. Recursive Query: If not cached, the resolver sends a query to a root DNS server, which directs it to a top-level domain (TLD) server (e.g., .com).
  3. TLD and Authoritative Server Query: The TLD server points to the domain’s authoritative server, which holds the final IP address.
  4. Response and Caching: The resolver returns the IP to the client and caches the result for future use.

Example: Resolving example.com involves queries to root servers (.), TLD servers (.com), and example.com’s authoritative server.

Key Configuration Files

Linux resolver behavior is controlled by several critical files and services. Below are the most important ones.

/etc/resolv.conf: The Classic Resolver File

The /etc/resolv.conf file is the traditional configuration point for DNS resolvers. It defines:

  • DNS servers to query (nameserver).
  • Search domains for unqualified names (e.g., hosthost.example.com via search).
  • Timeouts and retry logic (options).

Example resolv.conf:

# Define primary and secondary DNS servers
nameserver 8.8.8.8       # Google DNS
nameserver 8.8.4.4       # Google DNS (secondary)

# Search domain for unqualified names (e.g., "server" → "server.example.com")
search example.com sub.example.com

# Resolver options: timeout (5s), 2 retries, enable DNSSEC validation
options timeout:5 attempts:2 edns0 trust-ad

Key Directives:

  • nameserver <IP>: IP address of a DNS resolver (max 3 entries).
  • search <domains>: Space-separated list of domains to append to unqualified names.
  • domain <domain>: Single search domain (overridden by search if present).
  • options <flags>: Resolver behavior (e.g., timeout:N for query timeout, attempts:N for retries, edns0 for DNS extensions, trust-ad to trust DNSSEC signatures).

systemd-resolved: Modern Resolver Management

Most modern Linux distributions (e.g., Ubuntu 20.04+, Fedora, Debian 11+) use systemd-resolved as the primary resolver. It integrates with systemd and manages /etc/resolv.conf dynamically, often via a symlink:

ls -l /etc/resolv.conf
# Output: lrwxrwxrwx 1 root root 39 Aug 1 12:00 /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf

systemd-resolved provides:

  • A stub resolver (listening on 127.0.0.53:53) that forwards queries to configured DNS servers.
  • Per-interface DNS configuration (e.g., different DNS for Wi-Fi vs. Ethernet).
  • Built-in caching and DNSSEC support.

To check resolver status:

resolvectl status

NetworkManager: Dynamic Network Configuration

NetworkManager (used by most desktop and server distributions) manages network connections and often controls DNS resolver settings. It overrides /etc/resolv.conf by default, pushing DNS servers from DHCP or user-defined settings to systemd-resolved.

Key NetworkManager concepts:

  • Connections: Stored profiles for networks (e.g., “Wired Connection 1”).
  • Per-connection DNS: Set DNS servers for specific networks.

/etc/nsswitch.conf: Name Service Switch

The nsswitch.conf file defines the order in which Linux looks up names (e.g., users, hosts). For DNS, the hosts line determines resolution priority:

# /etc/nsswitch.conf excerpt
hosts:          files dns myhostname
  • files: Check /etc/hosts first.
  • dns: Use DNS resolver next.
  • myhostname: Resolve the local hostname (via systemd-resolved).

Changing the order (e.g., dns files) prioritizes DNS over /etc/hosts, but this is rarely recommended.

Usage Methods

Manual Configuration with /etc/resolv.conf

Warning: On systems with NetworkManager or systemd-resolved, manual edits to /etc/resolv.conf may be overwritten. Use this method only for static, non-network-managed environments.

Steps:

  1. Edit /etc/resolv.conf with a text editor:
    sudo nano /etc/resolv.conf
  2. Add nameserver, search, and options directives (see example above).
  3. Save and exit.

Persistence Note:

To prevent overwrites, set chattr +i /etc/resolv.conf (immutable flag), but this is not recommended for dynamic networks.

Configuring systemd-resolved

systemd-resolved is configured via resolvectl (command-line tool) or drop-in files.

Set Global DNS Servers:

Override the default DNS servers for all interfaces:

# Create a drop-in configuration for systemd-resolved
sudo mkdir -p /etc/systemd/resolved.conf.d/
sudo nano /etc/systemd/resolved.conf.d/custom-dns.conf

Add:

[Resolve]
DNS=1.1.1.1 1.0.0.1  # Cloudflare DNS
FallbackDNS=8.8.8.8 8.8.4.4  # Google DNS (fallback)
Domains=example.com  # Default search domain
DNSSEC=yes  # Enable DNSSEC validation

Restart systemd-resolved to apply:

sudo systemctl restart systemd-resolved

Set Per-Interface DNS:

Override DNS for a specific interface (e.g., wlan0):

resolvectl dns wlan0 9.9.9.9 149.112.112.112  # Quad9 DNS
resolvectl domain wlan0 "home.lan"  # Search domain for wlan0

NetworkManager Integration

Use nmcli (NetworkManager CLI) to configure DNS for a connection.

Example: Set DNS for “Wired Connection 1”

# List connections to find the name/UUID
nmcli con show

# Set DNS servers and disable auto-DNS from DHCP
nmcli con mod "Wired Connection 1" \
  ipv4.dns "8.8.8.8,8.8.4.4" \
  ipv4.ignore-auto-dns yes \
  ipv4.dns-search "example.com"  # Search domain

# Apply changes
nmcli con up "Wired Connection 1"

Verify with resolvectl:

resolvectl dns "Wired Connection 1"
# Output: Link 2 (enp0s3): 8.8.8.8 8.8.4.4

Common Practices

Testing DNS Resolution

Use these tools to validate resolver behavior:

dig: DNS Lookup Tool

# Basic lookup (uses system resolver)
dig example.com

# Query a specific DNS server (e.g., Cloudflare)
dig @1.1.1.1 example.com

# Check DNSSEC status (look for "ad" flag in response)
dig +dnssec example.com

nslookup/host: Simpler Alternatives

nslookup example.com  # Uses system resolver
host example.com 8.8.8.8  # Query Google DNS

Check Caching:

# First query (no cache)
dig example.com | grep "Query time"

# Second query (cached, faster)
dig example.com | grep "Query time"

Setting Up Local Caching

Local caching reduces latency and DNS traffic. Most modern resolvers (e.g., systemd-resolved, dnsmasq) cache by default.

Verify systemd-resolved Caching:

resolvectl statistics
# Look for "Cache hits" and "Cache misses" under "DNSSEC supported"

Advanced: Use dnsmasq as a Local Cache

For more control, install dnsmasq (lightweight DNS forwarder/cache):

sudo apt install dnsmasq  # Debian/Ubuntu
sudo yum install dnsmasq  # RHEL/CentOS

# Configure dnsmasq to listen on localhost and forward to Cloudflare
echo "listen-address=127.0.0.1" | sudo tee -a /etc/dnsmasq.conf
echo "server=1.1.1.1" | sudo tee -a /etc/dnsmasq.conf
echo "server=1.0.0.1" | sudo tee -a /etc/dnsmasq.conf

sudo systemctl restart dnsmasq

# Set resolver to 127.0.0.1 (via systemd-resolved or resolv.conf)
resolvectl dns lo 127.0.0.1

Using Public DNS Servers

Public DNS servers often offer faster speeds, better security, or privacy compared to ISP-provided resolvers. Popular options:

ProviderPrimary DNSSecondary DNSFeatures
Cloudflare1.1.1.11.0.0.1Fast, privacy-focused
Google8.8.8.88.8.4.4Reliable, global
Quad99.9.9.9149.112.112.112Blocks malicious domains
OpenDNS208.67.222.222208.67.220.220Family filtering options

To use Quad9, configure via resolvectl:

resolvectl dns enp0s3 9.9.9.9 149.112.112.112

Best Practices

Avoid Hardcoding Resolvers

Hardcoding /etc/resolv.conf is error-prone (e.g., overwritten by NetworkManager). Instead:

  • Use systemd-resolved drop-in files for global settings.
  • Use NetworkManager per-connection DNS for dynamic networks.

Secure DNS Queries with DNSSEC, DoT, and DoH

DNS is vulnerable to spoofing and eavesdropping. Mitigate risks with:

DNSSEC (Domain Name System Security Extensions)

Validates DNS responses to prevent tampering. Enable via systemd-resolved:

# /etc/systemd/resolved.conf.d/security.conf
[Resolve]
DNSSEC=yes  # "yes" = enforce, "allow-downgrade" = soft enforcement

DNS over TLS (DoT, RFC 7858)

Encrypts DNS queries between resolver and server (port 853). Configure with systemd-resolved:

# /etc/systemd/resolved.conf.d/dot.conf
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 9.9.9.9#dns.quad9.net  # DoT servers
DNSOverTLS=yes  # "yes" = enforce, "opportunistic" = try but allow plaintext

DNS over HTTPS (DoH, RFC 8484)

Encrypts DNS over HTTPS (port 443). Use tools like cloudflared (Cloudflare’s DoH proxy):

sudo cloudflared proxy-dns  # Runs on 127.0.0.1:53
# Configure resolver to use 127.0.0.1

Monitor and Log Resolver Activity

Logging helps debug resolution issues and detect abuse.

systemd-resolved Logs:

journalctl -u systemd-resolved -f  # Follow live logs
journalctl -u systemd-resolved --since "10m ago"  # Logs from last 10 minutes

Key Log Entries to Watch:

  • DNSSEC validation failed: Indicates invalid DNSSEC records.
  • Timeout resolving: Slow or unresponsive DNS servers.

Handle Dynamic Networks Gracefully

In mobile or VPN environments, DNS servers may change frequently. Use:

  • NetworkManager or systemd-networkd to auto-update resolvers.
  • Split DNS (per-domain resolvers) for VPNs:
    # Example: Route *.corp.example.com queries to VPN DNS
    resolvectl domain tun0 "corp.example.com"
    resolvectl dns tun0 10.0.0.1  # VPN DNS server

Troubleshooting Common Issues

1. /etc/resolv.conf is Overwritten

Cause: NetworkManager or systemd-resolved manages the file.
Fix: Use the service’s native configuration (e.g., nmcli for NetworkManager, resolvectl for systemd-resolved).

2. DNS Resolution Fails

Checklist:

  • Verify nameservers: cat /etc/resolv.conf or resolvectl dns.
  • Test with a public DNS: dig @8.8.8.8 example.com.
  • Ensure resolver service is running: systemctl status systemd-resolved.
  • Check firewall rules (allow UDP/TCP port 53).

3. Slow DNS Queries

Fixes:

  • Use closer DNS servers (e.g., Cloudflare/Google instead of ISP).
  • Enable caching (ensure systemd-resolved or dnsmasq is running).
  • Reduce timeout/attempts in resolv.conf options:
    options timeout:2 attempts:1  # 2-second timeout, 1 retry

4. DNSSEC Validation Errors

Cause: Misconfigured DNSSEC or untrusted records.
Fix:

  • Use DNSSEC=allow-downgrade in systemd-resolved for soft enforcement.