How to Force dnsmasq to Bind DNS Service Exclusively to localhost (127.0.0.1)


4 views

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 interface
  • bind-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