When configuring dnsmasq to listen only on localhost, many administrators encounter an unexpected behavior where the service still binds to external interfaces. This occurs even with explicit configuration like:
listen-address=127.0.0.1
Several factors contribute to this behavior:
1. Automatic interface binding when no explicit listen-address is specified
2. Systemd or init scripts that may override configurations
3. IPv6 binding (::1) that might not be properly disabled
Here's a working configuration that guarantees localhost-only binding:
# Disable DNS server functionality on all interfaces except localhost
listen-address=127.0.0.1
bind-interfaces
# Disable IPv6 completely if not needed
disable-dhcp-interface=eth0
no-dhcp-interface=eth0
no-resolv
# Additional hardening
local-service
no-poll
After applying the configuration, verify the binding:
ss -tulnp | grep 53
# Should only show:
# udp UNCONN 0 0 127.0.0.1:53 0.0.0.0:* users:(("dnsmasq",pid=123,fd=5))
# tcp LISTEN 0 32 127.0.0.1:53 0.0.0.0:* users:(("dnsmasq",pid=123,fd=6))
For systems using systemd, create an override:
sudo systemctl edit dnsmasq.service
Add these directives:
[Service]
ExecStart=
ExecStart=/usr/sbin/dnsmasq -k --bind-interfaces -z \
--listen-address=127.0.0.1 \
--conf-file=/etc/dnsmasq.conf
If the service still binds to external interfaces:
1. Check for multiple configuration files in /etc/dnsmasq.d/
2. Verify no dhcp-range is configured (forces binding to interfaces)
3. Ensure no other DNS services are running
When configuring dnsmasq to only listen on localhost, many administrators encounter unexpected behavior where the service still binds to all available interfaces. The standard listen-address=127.0.0.1
directive doesn't always produce the expected network isolation.
First, check how dnsmasq is currently binding to ports:
sudo netstat -tulnp | grep dnsmasq
# Or alternatively:
sudo ss -tulnp | grep dnsmasq
To enforce strict localhost-only binding, combine these configuration directives:
# /etc/dnsmasq.conf
interface=lo
bind-interfaces
listen-address=127.0.0.1
no-dhcp-interface=
interface=lo
: Explicitly limits to loopback interfacebind-interfaces
: Ensures binding occurs only to specified interfaces- The empty
no-dhcp-interface=
prevents DHCP service entirely
After making changes, test with these commands:
sudo systemctl restart dnsmasq
dig @127.0.0.1 example.com
dig @192.168.1.1 example.com # This should fail
For maximum control, consider using systemd socket activation:
# /etc/systemd/system/dnsmasq.socket
[Socket]
ListenStream=127.0.0.1:53
ListenDatagram=127.0.0.1:53
[Install]
WantedBy=sockets.target
For production systems, add these hardening measures:
user=dnsmasq
group=dnsmasq
no-hosts
filterwin2k
local-service