What's Actually Happening
DNS resolution timeouts occur when DNS queries fail to receive responses within the expected time. Applications cannot resolve hostnames, leading to connection failures and service disruptions.
The Error You'll See
nslookup timeout:
```bash $ nslookup example.com
;; connection timed out; no servers could be reached ```
dig timeout:
```bash $ dig example.com
;; communications error to 8.8.8.8#53: timed out ;; no servers could be reached ```
Application error:
java.net.UnknownHostException: example.com: Temporary failure in name resolution
System error: Name or service not knowncurl error:
```bash $ curl https://example.com/
curl: (6) Could not resolve host: example.com ```
Why This Happens
- 1.DNS server unreachable - DNS server down or blocked
- 2.Firewall blocking port 53 - UDP/TCP port 53 blocked
- 3.Network connectivity - Network issues preventing DNS queries
- 4.Wrong DNS server - Incorrect DNS server configured
- 5.DNS cache issues - Corrupt or stale DNS cache
- 6.High latency - Network latency causing timeouts
Step 1: Test DNS Resolution
```bash # Test with nslookup nslookup example.com nslookup example.com 8.8.8.8
# Test with dig dig example.com dig @8.8.8.8 example.com
# Test with host host example.com host example.com 8.8.8.8
# Test specific record type dig example.com A dig example.com MX dig example.com NS
# Test with timeout dig +time=5 +tries=2 example.com
# Test reverse DNS dig -x 93.184.216.34
# Check DNS response time dig +stats example.com | grep "Query time" ```
Step 2: Check DNS Configuration
```bash # Check current DNS servers cat /etc/resolv.conf
# Typical content: # nameserver 8.8.8.8 # nameserver 8.8.4.4 # search example.com
# Check for multiple DNS servers grep nameserver /etc/resolv.conf
# Test each configured DNS server while read -r server; do echo "Testing $server:" dig @$server example.com +short +time=5 done < <(grep nameserver /etc/resolv.conf | awk '{print $2}')
# Check systemd-resolved status systemctl status systemd-resolved
# Check NetworkManager DNS nmcli dev show | grep DNS
# For Ubuntu with netplan: cat /etc/netplan/*.yaml | grep nameservers ```
Step 3: Test DNS Server Connectivity
```bash # Test if DNS port is reachable nc -uvz 8.8.8.8 53 nc -uvz 1.1.1.1 53
# Test TCP DNS (for large responses) nc -tvz 8.8.8.8 53
# Test with ping ping -c 3 8.8.8.8
# Check firewall rules iptables -L -n -v | grep 53 iptables -L -n -v | grep domain
# Allow DNS outbound iptables -I OUTPUT -p udp --dport 53 -j ACCEPT iptables -I OUTPUT -p tcp --dport 53 -j ACCEPT
# Allow DNS responses iptables -I INPUT -p udp --sport 53 -j ACCEPT iptables -I INPUT -p tcp --sport 53 -j ACCEPT
# Check ufw ufw status | grep 53 ufw allow out 53/udp ufw allow out 53/tcp ```
Step 4: Change DNS Servers
```bash # Temporary change (until reboot) echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf echo "nameserver 8.8.4.4" | sudo tee -a /etc/resolv.conf
# Or use Cloudflare DNS echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf echo "nameserver 1.0.0.1" | sudo tee -a /etc/resolv.conf
# Permanent change - NetworkManager nmcli con mod <connection-name> ipv4.dns "8.8.8.8 8.8.4.4" nmcli con up <connection-name>
# Permanent change - netplan (Ubuntu) # Edit /etc/netplan/*.yaml network: ethernets: eth0: nameservers: addresses: [8.8.8.8, 8.8.4.4]
# Apply netplan apply
# For systemd-resolved: # Edit /etc/systemd/resolved.conf [Resolve] DNS=8.8.8.8 8.8.4.4 FallbackDNS=1.1.1.1
# Restart systemctl restart systemd-resolved ```
Step 5: Clear DNS Cache
```bash # Flush systemd-resolved cache systemd-resolve --flush-caches # Or resolvectl flush-caches
# Restart systemd-resolved systemctl restart systemd-resolved
# For nscd systemctl restart nscd nscd -i hosts
# For dnsmasq systemctl restart dnsmasq kill -HUP $(pidof dnsmasq)
# For BIND rndc flush
# Clear local application cache # Firefox: about:networking#dns > Clear DNS Cache # Chrome: chrome://net-internals/#dns > Clear host cache
# Flush Windows DNS cache ipconfig /flushdns
# Check DNS cache status systemd-resolve --statistics ```
Step 6: Check for DNS Hijacking
```bash # Check if DNS queries are being intercepted dig +short example.com @8.8.8.8 dig +short example.com @1.1.1.1
# Compare results - should be same IP
# Check for unexpected DNS responses dig example.com +trace
# Check hosts file for overrides cat /etc/hosts | grep -v "^#" | grep -v "^$"
# Remove unwanted entries # /etc/hosts should not have entries for external domains
# Check for DNS-over-HTTPS or DNS-over-TLS # These can cause issues if misconfigured systemctl status systemd-resolved | grep -i "dns over"
# Disable DoT if causing issues # In /etc/systemd/resolved.conf: DNSOverTLS=off ```
Step 7: Increase DNS Timeout
```bash # Increase timeout in /etc/resolv.conf # Add options: options timeout:10 options attempts:5 options rotate
# Full example: nameserver 8.8.8.8 nameserver 8.8.4.4 options timeout:10 attempts:5 rotate
# Test with increased timeout dig +time=10 +tries=5 example.com
# For glibc resolver (most Linux): # /etc/resolv.conf options: # timeout:n - timeout in seconds (default 5) # attempts:n - number of tries (default 2) # rotate - rotate through nameservers # single-request - disable parallel queries ```
Step 8: Debug DNS Issues
```bash # Enable DNS query logging # For systemd-resolved: resolvectl log-level debug
# Check journal for DNS logs journalctl -u systemd-resolved -f
# For BIND named: rndc querylog on tail -f /var/log/named/query.log
# Use tcpdump to capture DNS traffic tcpdump -i any port 53 -nn
# Capture to file tcpdump -i any port 53 -w dns.pcap
# Analyze with wireshark wireshark dns.pcap
# Check for DNS amplification attacks tcpdump -i any port 53 -nn | grep "A?" # Too many queries could indicate attack ```
Step 9: Set Up Local DNS Cache
```bash # Install dnsmasq apt install dnsmasq
# Configure /etc/dnsmasq.conf server=8.8.8.8 server=8.8.4.4 cache-size=1000 listen-address=127.0.0.1
# Set as local resolver echo "nameserver 127.0.0.1" > /etc/resolv.conf
# Restart dnsmasq systemctl restart dnsmasq
# Test dig example.com @127.0.0.1
# Second query should be cached (Query time: 0 msec) dig example.com @127.0.0.1
# Or use systemd-resolved caching # Already enabled by default on many systems # /etc/systemd/resolved.conf: Cache=yes ```
Step 10: Monitor DNS Performance
```bash # Create DNS monitoring script cat << 'EOF' > /usr/local/bin/check_dns.sh #!/bin/bash DOMAINS="example.com google.com github.com" DNS_SERVER="8.8.8.8"
for domain in $DOMAINS; do START=$(date +%s%N) RESULT=$(dig @$DNS_SERVER $domain +short +time=5 2>&1) END=$(date +%s%N) DURATION=$(( ($END - $START) / 1000000 ))
if [ -z "$RESULT" ]; then echo "FAIL: $domain (timeout after ${DURATION}ms)" else echo "OK: $domain (${DURATION}ms)" fi done EOF
chmod +x /usr/local/bin/check_dns.sh
# Add to cron echo "*/5 * * * * root /usr/local/bin/check_dns.sh | mail -s 'DNS Check' admin@company.com" > /etc/cron.d/dns-check
# Use Prometheus node exporter for DNS metrics # Or dnsmasq metrics ```
DNS Troubleshooting Checklist
| Check | Command | Expected |
|---|---|---|
| DNS resolves | dig example.com | IP returned |
| DNS server reachable | nc -uvz 8.8.8.8 53 | Connected |
| resolv.conf | cat /etc/resolv.conf | Valid servers |
| Firewall | iptables -L | Port 53 allowed |
| Cache | systemd-resolve --stats | Cache working |
Verify the Fix
```bash # After fixing DNS configuration
# 1. Test DNS resolution dig example.com # Should return IP quickly
# 2. Check response time dig example.com | grep "Query time" # Should be < 100ms
# 3. Test all configured servers for s in $(grep nameserver /etc/resolv.conf | awk '{print $2}'); do echo "Testing $s:" dig @$s example.com +short done
# 4. Verify application connectivity curl -I https://example.com # Should connect without DNS error
# 5. Test from application # Application should resolve hostnames successfully
# 6. Monitor for recurring issues /usr/local/bin/check_dns.sh ```
Related Issues
- [Fix DNS Server Not Responding](/articles/fix-dns-server-not-responding)
- [Fix DNS Propagation Delay](/articles/fix-dns-propagation-delay)
- [Fix DNS Cache Poisoning](/articles/fix-dns-cache-poisoning)