We have dnsmasq running on a PC connected directly to the internet. It is also used for DHCP and PXE booting for the nodes of our cluster as well as for the other PCs on our public subnet ($PUB_SUBNET). Without careful configuration this can lead to an open DNS relay server.

The Problem

This server in the current configuration answers all requests, also those from the internet which leads to an open DNS resolver, which could then be used1 for a DDOS. Specifically, it can be used for a DNS amplification attack. Note that if we want to serve DHCP requests on the $PUB_SUNNET subnet this is the default behavior. One can switch off DHCP on specific network interfaces, but not DNS.

This setup was working for over a year without problems, but for about one day it took an unreasonable long time to resolve local cluster node names which in turn lead to a lot of spurious messages from our Icingia monitoring server (timeouts, etc.). Upon further investigation it was found that outbound UDP traffic was constantly high (30 MBytes/s) and dnsmasq was using around 10% CPU cycles when started with dnsmasq --no-daemon --log-queries. Strangely, I can not find the massive UDP traffic in our Ganglia statistics, but one can see the CPU load. If the load is indeed from dnsmasq we were used for this attack more than one week.

CPU load during DNS abuse. On Friday night the firewall rules were activated, the drop of the load is clearly seen

Securing dnsmasq

One way to mitigate this attack is to block requests from outside our subnet and only allow local subnets to query our server:

iptables

iptables -A INPUT -p tcp --dport 53 -s 192.168.0.0/16 -j ACCEPT

iptables -A INPUT -p udp --dport 53 -s 192.168.0.0/16 -j ACCEPT

iptables -A INPUT -p tcp --dport 53 -s $PUB_SUBNET -j ACCEPT

iptables -A INPUT -p udp --dport 53 -s $PUB_SUBNET -j ACCEPT

iptables -A INPUT -p tcp --dport 53 -j DROP

iptables -A INPUT -p udp --dport 53 -j DROP

Newer versions of dnsmaq can be configure to answer only requests from specified subnets. On Debian Wheezy the dnsmasq version is at version 2.62, but the option “–local-service” was added in dnsmasq only at version 2.69 precisely for this reason, so for now we have to stick with above firewall rules.

From the dnsmaq ChangeLog:

Add --local-service. Accept DNS queries only from hosts whose address is on a local subnet, ie a subnet for which an interface exists on the server. This option only has effect if there are no --interface --except-interface, --listen-address or --auth-server options. It is intended to be set as a default on installation, to allow unconfigured installations to be useful but also safe from being used for DNS amplification attacks.