What's Actually Happening

BIND DNS server fails to resolve domain names. Queries return SERVFAIL, NXDOMAIN, or timeout errors.

The Error You'll See

```bash $ dig @localhost example.com

;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 12345 ```

Query refused:

bash
status: REFUSED

No answer:

```bash ;; QUESTION SECTION: ;example.com. IN A

;; AUTHORITY SECTION: . 3600 IN SOA a.root-servers.net. ```

Timeout:

bash
;; connection timed out; no servers could be reached

Why This Happens

  1. 1.Zone configuration errors - Syntax errors in zone files
  2. 2.Missing zones - Zone not configured or loaded
  3. 3.Forwarding issues - Upstream DNS not reachable
  4. 4.Permission errors - BIND cannot read zone files
  5. 5.DNSSEC issues - Signature validation failures
  6. 6.Recursion disabled - Server not allowing recursive queries
  7. 7.Firewall blocking - Port 53 not accessible

Step 1: Check BIND Status

```bash # Check BIND service: systemctl status named systemctl status bind9

# Check process: ps aux | grep named

# Check configuration: named-checkconf

# Check zone files: named-checkzone example.com /etc/bind/zones/example.com.zone

# Check logs: journalctl -u named -f tail -f /var/log/named.log

# Check listening ports: netstat -tlnp | grep named ss -tlnp | grep named

# DNS ports: # 53 - UDP and TCP # 953 - RNDC control

# Check version: named -v

# Test configuration: named -g -u bind # Runs in foreground with debug ```

Step 2: Check Zone Configuration

```bash # List configured zones: rndc zonestatus example.com

# Or from config: grep "zone" /etc/named.conf grep "zone" /etc/bind/named.conf.local

# Check zone file: cat /etc/bind/zones/example.com.zone

# Verify zone syntax: named-checkzone example.com /etc/bind/zones/example.com.zone

# Zone file example: $TTL 86400 @ IN SOA ns1.example.com. admin.example.com. ( 2024010101 ; Serial 3600 ; Refresh 1800 ; Retry 604800 ; Expire 86400 ) ; Minimum

@ IN NS ns1.example.com. @ IN A 192.168.1.10 ns1 IN A 192.168.1.1

# Check zone loaded: rndc status

# Reload zones: rndc reload systemctl reload named

# Check for zone errors: journalctl -u named | grep -i zone

# Zone configuration in named.conf: zone "example.com" { type master; file "/etc/bind/zones/example.com.zone"; allow-update { none; }; };

# Slave zone: zone "example.com" { type slave; file "/var/lib/bind/example.com.zone"; masters { 192.168.1.1; }; }; ```

Step 3: Fix Configuration Errors

```bash # Check main config: named-checkconf /etc/named.conf named-checkconf /etc/bind/named.conf

# Common errors:

# 1. Missing semicolons: # Wrong: allow-query { localhost } # Right: allow-query { localhost; };

# 2. Missing braces: options { recursion yes; };

# 3. Wrong file paths: file "/etc/bind/zones/example.com.zone"; # Check file exists: ls -la /etc/bind/zones/

# 4. Permission issues: ls -la /etc/bind/zones/example.com.zone chown bind:bind /etc/bind/zones/*.zone chmod 644 /etc/bind/zones/*.zone

# Check options: options { directory "/var/cache/bind"; recursion yes; allow-query { any; }; forwarders { 8.8.8.8; 8.8.4.4; }; dnssec-validation auto; };

# Check for include files: grep include /etc/named.conf

# Test after fix: named-checkconf && echo "Config OK" ```

Step 4: Check Recursion Settings

```bash # Check recursion enabled: grep recursion /etc/named.conf

# Enable recursion: options { recursion yes; allow-recursion { any; }; }

# Restrict recursion to specific networks: allow-recursion { 192.168.0.0/16; 10.0.0.0/8; };

# Check allow-query: allow-query { any; }; # Or restrict: allow-query { localhost; 192.168.0.0/16; };

# For authoritative only: recursion no;

# Test recursion: dig @localhost google.com

# Should return answer if recursion works

# Test with specific type: dig @localhost example.com A dig @localhost example.com MX

# Check cache: rndc dumpdb -cache # View: /var/named/data/cache_dump.db ```

Step 5: Fix Forwarding Issues

```bash # Check forwarders: grep forwarder /etc/named.conf

# Configure forwarders: options { forwarders { 8.8.8.8; 8.8.4.4; }; forward only; }

# Or forward first (try forwarders, then resolve directly): forward first;

# Test forwarder reachable: ping 8.8.8.8 nc -zuv 8.8.8.8 53

# Test forwarder works: dig @8.8.8.8 google.com

# Check forwarding logs: journalctl -u named | grep -i forward

# Conditional forwarding: zone "internal.example.com" { type forward; forwarders { 192.168.1.1; }; };

# Check forwarder statistics: rndc stats cat /var/named/data/named.stats ```

Step 6: Check DNSSEC Configuration

```bash # Check DNSSEC settings: grep dnssec /etc/named.conf

# DNSSEC validation: dnssec-validation auto;

# Disable DNSSEC validation (for testing): dnssec-validation no;

# Check for DNSSEC errors: journalctl -u named | grep -i dnssec

# DNSSEC keys: ls -la /etc/bind/keys/

# Signed zone file: # example.com.zone.signed

# Check DNSSEC chain: dig @localhost example.com DNSKEY dig @localhost example.com DS

# DNSSEC troubleshooting: # Check signature: dig @localhost example.com +dnssec

# Disable DNSSEC temporarily: rndc validation off

# Re-enable: rndc validation on

# Check for expired signatures: dnssec-signzone -A example.com.zone ```

Step 7: Check Firewall and Network

```bash # Check firewall for DNS: iptables -L -n | grep 53

# Allow DNS: iptables -I INPUT -p udp --dport 53 -j ACCEPT iptables -I INPUT -p tcp --dport 53 -j ACCEPT

# Using ufw: ufw allow 53/udp ufw allow 53/tcp

# Using firewalld: firewall-cmd --add-service=dns --permanent firewall-cmd --reload

# Test port: nc -zuv localhost 53

# Check if listening: ss -ulnp | grep :53

# Check from client: dig @server-ip example.com

# Check network: ping server-ip traceroute server-ip

# Check for NAT issues: # DNS over TCP sometimes blocked # Check with: dig @server-ip example.com +tcp ```

Step 8: Debug Resolution Issues

```bash # Enable debug logging: # In named.conf: logging { channel default_debug { file "data/named.run"; severity dynamic; }; };

# Or: logging { channel query.log { file "/var/log/query.log"; severity debug 3; }; category queries { query.log; }; };

# Reload: rndc reload

# Watch logs: tail -f /var/log/named.log

# Query with debug: dig @localhost example.com +trace

# Check response: dig @localhost example.com +stats

# Check authoritative servers: dig example.com NS +short

# Trace resolution: dig @localhost example.com +trace

# Check SERVFAIL reason: dig @localhost example.com +dnssec +cd # +cd disables DNSSEC check

# If +cd works, DNSSEC issue ```

Step 9: Fix Common Issues

```bash # Fix NXDOMAIN for existing domain: # Check zone serial: # Must increment serial after changes # Before: 2024010101 # After: 2024010102

# Fix SERVFAIL: # 1. Check zone syntax: named-checkzone example.com zonefile

# 2. Check DNSSEC # 3. Check file permissions # 4. Check logs

# Fix REFUSED: # Check allow-query: allow-query { any; };

# Fix timeout: # 1. Check firewall # 2. Check recursion enabled # 3. Check forwarders

# Clear cache: rndc flush

# Reload configuration: rndc reload

# Restart BIND: systemctl restart named

# Check for slave transfer issues: # On master: allow-transfer { slave-ip; };

# On slave: masters { master-ip; };

# Force zone transfer: rndc retransfer example.com

# Check transfer: dig @localhost example.com AXFR ```

Step 10: BIND Verification Script

```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-bind.sh #!/bin/bash

echo "=== BIND Service ===" systemctl status named 2>/dev/null || systemctl status bind9 2>/dev/null || echo "Service not running"

echo "" echo "=== Process ===" ps aux | grep named | grep -v grep || echo "No named process"

echo "" echo "=== Configuration Check ===" named-checkconf 2>&1 || echo "Configuration errors found"

echo "" echo "=== Listening Ports ===" netstat -tlnp 2>/dev/null | grep :53 || ss -tlnp | grep :53 || echo "Not listening on port 53"

echo "" echo "=== UDP Listening ===" ss -ulnp | grep :53 || netstat -ulnp | grep :53 || echo "Not listening on UDP 53"

echo "" echo "=== Zone Files ===" grep -h "file " /etc/named.conf /etc/bind/named.conf.local 2>/dev/null | head -10

echo "" echo "=== Zone Check ===" for zonefile in $(grep -h "file " /etc/named.conf /etc/bind/named.conf.local 2>/dev/null | grep -oE '"[^"]+"|'"'"'[^'"'"']+'"'"'' | tr -d "\"'" | head -5); do if [ -f "$zonefile" ]; then zonename=$(basename $zonefile .zone 2>/dev/null || echo "unknown") echo "Checking: $zonefile" named-checkzone $zonename $zonefile 2>&1 | head -3 fi done

echo "" echo "=== Recursion Setting ===" grep -E "^[\t ]*recursion" /etc/named.conf /etc/bind/named.conf.options 2>/dev/null | head -3

echo "" echo "=== Forwarders ===" grep -A 5 "forwarders" /etc/named.conf /etc/bind/named.conf.options 2>/dev/null | head -10

echo "" echo "=== Test Resolution ===" dig @localhost google.com +short 2>/dev/null | head -3 || echo "Resolution test failed"

echo "" echo "=== Test Local Zone ===" dig @localhost localhost +short 2>/dev/null || echo "Local resolution failed"

echo "" echo "=== Firewall ===" iptables -L -n 2>/dev/null | grep 53 || ufw status 2>/dev/null | grep 53 || echo "Check firewall manually"

echo "" echo "=== Recent Logs ===" journalctl -u named --no-pager -n 10 2>/dev/null || tail /var/log/named.log 2>/dev/null | tail -10 || echo "No logs"

echo "" echo "=== Recommendations ===" echo "1. Run named-checkconf to verify configuration" echo "2. Check zone files with named-checkzone" echo "3. Ensure recursion enabled for caching server" echo "4. Verify firewall allows port 53 UDP/TCP" echo "5. Check DNSSEC configuration if issues" echo "6. Increment serial after zone changes" echo "7. Check file permissions on zone files" EOF

chmod +x /usr/local/bin/check-bind.sh

# Usage: /usr/local/bin/check-bind.sh ```

BIND DNS Resolution Checklist

CheckExpected
Service runningnamed process active
Port listeningUDP/TCP 53 accessible
Zone filesSyntax valid
RecursionEnabled for caching
ForwardersReachable
DNSSECValid or disabled
FirewallPort 53 allowed

Verify the Fix

```bash # After fixing BIND DNS resolution

# 1. Check config named-checkconf // No errors

# 2. Check zones named-checkzone example.com /etc/bind/zones/example.com.zone // Zone OK

# 3. Test local dig @localhost example.com // Returns A record

# 4. Test external dig @localhost google.com // Returns answer (recursion works)

# 5. Check logs journalctl -u named -f // No errors

# 6. Test from client dig @server-ip example.com // Resolution works ```

  • [Fix DNS Server Not Responding](/articles/fix-dns-server-not-responding)
  • [Fix DNS Propagation Issues](/articles/fix-dns-propagation-issues)
  • [Fix PowerDNS Query Failed](/articles/fix-powerdns-query-failed)