What's Actually Happening

Dnsmasq DNS forwarder fails to resolve domain names. Clients receive SERVFAIL or no response to queries.

The Error You'll See

```bash $ dig @localhost google.com

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

No response:

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

Local resolution fails:

```bash $ dig @localhost myhost.local

;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN ```

Configuration error:

bash
dnsmasq: bad option at line 10 of /etc/dnsmasq.conf

Why This Happens

  1. 1.Upstream DNS unreachable - Cannot reach configured DNS servers
  2. 2.Configuration errors - Syntax errors in dnsmasq.conf
  3. 3.Port conflict - Another service using port 53
  4. 4.Hosts file issues - Malformed /etc/hosts entries
  5. 5.Permission issues - Cannot read configuration files
  6. 6.DNSSEC validation - Failing DNSSEC checks
  7. 7.Cache corruption - Corrupted DNS cache

Step 1: Check Dnsmasq Status

```bash # Check dnsmasq service: systemctl status dnsmasq

# Check process: ps aux | grep dnsmasq

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

# Check UDP port: ss -ulnp | grep :53

# Check logs: journalctl -u dnsmasq -f

# Check configuration: dnsmasq --test

# Check version: dnsmasq -v

# Start dnsmasq: systemctl start dnsmasq

# Check config file: cat /etc/dnsmasq.conf

# Check additional configs: ls -la /etc/dnsmasq.d/

# Check hosts file: cat /etc/hosts ```

Step 2: Check Configuration

```bash # Test configuration syntax: dnsmasq --test

# Main configuration: cat /etc/dnsmasq.conf

# Common settings: # Listen on interfaces: listen-address=127.0.0.1,192.168.1.1

# Bind to interfaces: bind-interfaces

# Set port: port=53

# Upstream DNS: server=8.8.8.8 server=8.8.4.4

# Domain: domain=local

# DNS range: dhcp-range=192.168.1.50,192.168.1.150,12h

# Log queries: log-queries

# Check for included files: grep conf-dir /etc/dnsmasq.conf

# List included configs: ls -la /etc/dnsmasq.d/

# Check all configs: for f in /etc/dnsmasq.d/*; do echo "=== $f ===" cat $f done

# Common errors: # 1. Missing equals sign # 2. Invalid option name # 3. Wrong format for IP ranges ```

Step 3: Check Upstream DNS

```bash # Check configured upstream servers: grep "^server=" /etc/dnsmasq.conf

# Test upstream servers: ping 8.8.8.8 ping 8.8.4.4

# Test DNS resolution on upstream: dig @8.8.8.8 google.com

# Check port: nc -zuv 8.8.8.8 53

# If upstream unreachable: # Check firewall: iptables -L -n | grep 53

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

# Add multiple upstream servers: server=8.8.8.8 server=8.8.4.4 server=1.1.1.1

# Use specific server for domain: server=/example.com/192.168.1.1

# Check for upstream errors: journalctl -u dnsmasq | grep -i "upstream|forward"

# Test forwarding: dig @localhost google.com +trace ```

Step 4: Check Local Resolution

```bash # Dnsmasq uses /etc/hosts for local names

# Check hosts file: cat /etc/hosts

# Format: # IP hostname alias 192.168.1.10 server1.local server1 192.168.1.11 server2.local server2

# Check for syntax errors: # - Missing IP address # - Missing hostname # - Invalid characters

# Add hosts file entry: echo "192.168.1.100 myhost.local" >> /etc/hosts

# Reload dnsmasq: systemctl reload dnsmasq

# Test local resolution: dig @localhost myhost.local

# Check hosts file permissions: ls -la /etc/hosts

# Additional hosts file: addn-hosts=/etc/hosts.dnsmasq

# Check address entries: grep "^address=" /etc/dnsmasq.conf

# Static address: address=/myhost.local/192.168.1.100 ```

Step 5: Check Port Binding

```bash # Check what's listening on port 53: ss -ulnp | grep :53 ss -tlnp | grep :53

# If another service using port 53: # Check systemd-resolved: systemctl status systemd-resolved

# Stop resolved if needed: systemctl stop systemd-resolved systemctl disable systemd-resolved

# Check for bind-utils: lsof -i :53

# Configure dnsmasq to bind: bind-interfaces listen-address=127.0.0.1

# Or listen on all: listen-address=0.0.0.0

# For specific interface: interface=eth0

# Check interface IP: ip addr show eth0

# Restart: systemctl restart dnsmasq

# Verify binding: ss -ulnp | grep dnsmasq ```

Step 6: Check DNSSEC Configuration

```bash # Check DNSSEC settings: grep -i dnssec /etc/dnsmasq.conf

# Disable DNSSEC (if issues): dnssec-off

# Or comment out DNSSEC options

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

# DNSSEC trust anchor: dnssec-trust-anchor=...

# Test with DNSSEC disabled: # Stop dnsmasq systemctl stop dnsmasq

# Edit config, disable DNSSEC # Start dnsmasq systemctl start dnsmasq

# Test resolution: dig @localhost google.com

# If DNSSEC required: # Ensure trust anchors valid # Check for expired keys

# Forward DNSSEC: proxy-dnssec

# Check DNSSEC validation: dig @localhost google.com +dnssec ```

Step 7: Check Cache Settings

```bash # Check cache size: grep cache-size /etc/dnsmasq.conf

# Default cache size: cache-size=150

# Increase cache: cache-size=1000

# Clear cache: # Send SIGHUP to reload: kill -HUP $(cat /run/dnsmasq/dnsmasq.pid)

# Or restart: systemctl restart dnsmasq

# Check cache stats: dig @localhost example.com # Then: dig @localhost example.com # Second query should be cached

# Check cache in logs: # Enable logging: log-queries log-facility=/var/log/dnsmasq.log

# Monitor cache: watch "dig @localhost google.com +stats"

# No-negcache option: # Don't cache negative responses no-negcache

# Cache negative TTL: neg-ttl=60 ```

Step 8: Check DHCP Integration

```bash # If dnsmasq provides DHCP:

# Check DHCP range: grep dhcp-range /etc/dnsmasq.conf

# DHCP configuration: dhcp-range=192.168.1.50,192.168.1.150,12h

# Check DHCP leases: cat /var/lib/dnsmasq/dnsmasq.leases

# Or: cat /var/lib/misc/dnsmasq.leases

# DHCP option: dhcp-option=3,192.168.1.1 # Gateway dhcp-option=6,192.168.1.1 # DNS

# DNS from DHCP clients: # dnsmasq reads /etc/hosts for local names

# Enable DHCP: dhcp-authoritative

# Check for DHCP errors: journalctl -u dnsmasq | grep -i dhcp

# DHCP script: dhcp-script=/etc/dnsmasq.d/dhcp-script.sh

# Test DHCP: dhclient -v eth0 ```

Step 9: Debug Resolution Issues

```bash # Enable debug logging: log-queries log-dhcp

# In config: log-facility=/var/log/dnsmasq.log

# Restart: systemctl restart dnsmasq

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

# Test specific query: dig @localhost google.com +short

# Test with debug: dnsmasq --no-daemon --log-queries

# Check response codes: dig @localhost google.com +stats

# Test TCP: dig @localhost google.com +tcp

# Force specific record: dig @localhost example.com A dig @localhost example.com MX dig @localhost example.com TXT

# Check for timeouts: dig @localhost google.com +time=10

# Use tcpdump: tcpdump -i any port 53 -n

# Check response time: dig @localhost google.com | grep "Query time" ```

Step 10: Dnsmasq Verification Script

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

echo "=== Dnsmasq Service ===" systemctl status dnsmasq 2>/dev/null | head -5 || echo "Service not running"

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

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

echo "" echo "=== Configuration Test ===" dnsmasq --test 2>&1 || echo "Configuration errors"

echo "" echo "=== Upstream Servers ===" grep "^server=" /etc/dnsmasq.conf 2>/dev/null || echo "No upstream servers configured"

echo "" echo "=== Listen Address ===" grep "^listen-address" /etc/dnsmasq.conf 2>/dev/null || echo "No listen address configured"

echo "" echo "=== Cache Size ===" grep "^cache-size" /etc/dnsmasq.conf 2>/dev/null || echo "Using default cache size"

echo "" echo "=== Hosts File ===" cat /etc/hosts 2>/dev/null | grep -v "^#" | grep -v "^$" | head -10

echo "" echo "=== Additional Configs ===" ls -la /etc/dnsmasq.d/ 2>/dev/null || echo "No additional config directory"

echo "" echo "=== Test Resolution ===" echo "Testing external DNS:" dig @localhost google.com +short 2>/dev/null | head -3 || echo "External resolution failed"

echo "" echo "Testing local DNS:" 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 dnsmasq --no-pager -n 10 2>/dev/null || tail /var/log/dnsmasq.log 2>/dev/null | tail -10 || echo "No logs"

echo "" echo "=== Recommendations ===" echo "1. Verify upstream DNS servers are reachable" echo "2. Check dnsmasq.conf syntax with dnsmasq --test" echo "3. Ensure port 53 is available (not used by systemd-resolved)" echo "4. Allow UDP/TCP port 53 in firewall" echo "5. Check /etc/hosts for local entries" echo "6. Disable DNSSEC if validation errors" echo "7. Increase cache size if needed" EOF

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

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

Dnsmasq DNS Resolution Checklist

CheckExpected
Service runningdnsmasq process active
Port listeningUDP 53 accessible
Config validdnsmasq --test passes
Upstream reachableCan query upstream DNS
Hosts file validNo syntax errors
No port conflictPort 53 not used by other
Firewall openPort 53 allowed

Verify the Fix

```bash # After fixing Dnsmasq DNS

# 1. Check service systemctl status dnsmasq // Active running

# 2. Test external dig @localhost google.com // Returns A record

# 3. Test local dig @localhost myhost.local // Returns local IP

# 4. Check config dnsmasq --test // No errors

# 5. Monitor logs journalctl -u dnsmasq -f // Queries logged

# 6. Test from client dig @dnsmasq-server google.com // Resolution works ```

  • [Fix BIND DNS Resolution Failed](/articles/fix-bind-dns-resolution-failed)
  • [Fix PowerDNS Query Failed](/articles/fix-powerdns-query-failed)
  • [Fix Unbound DNS Not Responding](/articles/fix-unbound-dns-not-responding)