Securing DNSMasq
Author: R Zach FeeserDNSMasq insists on listening on all addresses, port 53. Even when dnsmasq is set to listen to internal interfaces only, it appears to be servicing all interfaces. I’m not the only one that’s living with this. Consider these write-ups:
- Ubiquiti Forums - DNSMasq insists on listening on all interfaces, port 53
- Ubiquiti Forums - DNSmasq listen-on all interfaces
- Stack Exchange - How do I limit dnsmasq listening to only one interface?
There will be a happy ending to this story. I’ll show you that dnsmasq does NOT listen on all interfaces if you tell it not to, but let’s test that theory first.
Here is a test configuration that restricts dnsmasq to one ip address only.
dnsmasq.conf
listen-address=10.10.0.1 <---- JUST LISTEN ON THIS INTERNAL ADDRESS
domain-needed
bogus-priv
server=8.8.8.8
expand-hosts
domain=localdomain
strict-order
dhcp-range=10.10.252.2,10.10.255.255,255.255.0.0,2m
dhcp-fqdn
dhcp-option=3,10.10.0.1
dhcp-option=119,localdomain
dhcp-option=15,localdomain
dhcp-hostsfile=/etc/dnsmasq/hosts.static
dhcp-optsfile=/etc/dnsmasq.d/options
Oh no! The socket statistics (ss
) command says “port 53 is WIDE OPEN. "
ubuntu@router-10-32:~$ sudo ss -antp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 32 0.0.0.0:53 0.0.0.0:* users:(("dnsmasq",pid=1379,fd=7))
So let’s dig the outside interface of the dnsmaq server
$ dig @a.b.c.d example.com (a.b.c.d is my public ip address)
; <<>> DiG 9.11.3-1ubuntu1.12-Ubuntu <<>> @a.b.c.d example.com
; (1 server found)
;; global options: +cmd
;; connection timed out; no servers could be reached
GOOD! dnsmasq is not actually listening on all interfaces as we specified.
So if I comment out the listen-address
line then it should work on all interfaces.
#listen-address=10.10.0.1 <--- commnet out this line!
domain-needed
bogus-priv
server=8.8.8.8
expand-hosts
domain=localdomain
strict-order
dhcp-range=10.10.252.2,10.10.255.255,255.255.0.0,2m
dhcp-fqdn
dhcp-option=3,10.10.0.1
dhcp-option=119,localdomain
dhcp-option=15,localdomain
dhcp-hostsfile=/etc/dnsmasq/hosts.static
dhcp-optsfile=/etc/dnsmasq.d/options
Restart dnsmasq
sudo systemctl restart dnsmasq
Well now, look at that! It works as expected…
; <<>> DiG 9.11.3-1ubuntu1.12-Ubuntu <<>> @a.b.c.d example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32709
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com. IN A
;; Query time: 0 msec
;; SERVER: a.b.c.d#53
;; WHEN: Tue Aug 25 01:22:07 UTC 2020
;; MSG SIZE rcvd: 36
But I don’t want this to work on the internet side, so raise the shields!
listen-address=10.10.0.1 <--- now I know that this actually works!
domain-needed
bogus-priv
server=8.8.8.8
expand-hosts
domain=localdomain
strict-order
dhcp-range=10.10.252.2,10.10.254.255,255.255.0.0,2m
dhcp-fqdn
dhcp-option=3,10.10.0.1
dhcp-option=119,localdomain
dhcp-option=15,localdomain
dhcp-hostsfile=/etc/dnsmasq/hosts.static
dhcp-optsfile=/etc/dnsmasq.d/options
Restart dnsmasq
sudo systemctl restart dnsmasq
OK, dnsmasq is secure again and in spite of what ss -antp
tells me
stu@tower2:update-motd.d$ dig @71.251.147.236 sumi-01
; <<>> DiG 9.11.3-1ubuntu1.12-Ubuntu <<>> @71.251.147.236 sumi-01
; (1 server found)
;; global options: +cmd
;; connection timed out; no servers could be reached
stu@tower2:update-motd.d$
Conclusion
If only I had read the man page I would have seen this, which confirms my observations:
-z, --bind-interfaces
… dnsmasq binds the wildcard address, even when it’s only listening on some interfaces.
- It then discards requests that it shouldn’t reply to.
- This has the advantage of working even when interfaces come and go and change address.
- This option forces dnsmasq to only bind the interfaces it’s listening on.
- This option is useful when running another nameserver (or another instance of dnsmasq) on the same machine.
- This is useful for multiple instances of dnsmasq which provide DHCP service to run in the same machine.