I'm having trouble figuring out how to block ANY dns request on BIND to lower the changes of a DNS Amplification attacks. I've seen guides online but most of them appear to perform rate limit via iptables or bind.

Any tips or advice?


Solution 1:

This method is inefficient, but it does what you requested

The only effective and universal way that I know if is to enable an iptables string filter to block the request. Be sure to back up your iptables configuration before doing this.

-A PREROUTING -p udp -m udp --dport 53 -m string --hex-string "|0000ff0001|" --algo bm --from 40 -j DROP 

placed in the iptables raw table section of your iptables configuration.

... or from the command line:

iptables -t raw -I PREROUTING -p udp -m udp --dport 53 -m string --hex-string "|0000ff0001|" --algo bm --from 40 -j DROP

The reason to use the raw table is to avoid the state table hits in the event you are getting a high rate of requests.

Optional step that may be useful: Use with caution and test on a test server. Avoid doing this on a business critical server without extensive testing.

This may stop some DNS enumeration and amplification attacks, but it breaks a couple RFC's. It is trivial to prevent anything other than NOERROR from leaving your server.

#
# drop anything leaving with the source port of 53 (DNS)
iptables -t raw -I OUTPUT -p udp -m udp --sport 53 -j DROP
#
# but then let through NOERROR for recursive
iptables -t raw -I OUTPUT -p udp -m udp --sport 53 -m string --hex-string "|8500|" --algo kmp --from 30 --to 31 -j ACCEPT
#
# and let through NOERROR for non-recursive
iptables -t raw -I OUTPUT -p udp -m udp --sport 53 -m string --hex-string "|8400|" --algo kmp --from 30 --to 31 -j ACCEPT

None of the DNS daemons support selecting with request types to block without modifying the source code, AFAIK. For example, I modified rbldnsd to respond to "ANY" with the "A" answer. This is of course unorthodox and may upset purists.

Solution 2:

If you have BIND 9.9 or later and your installation has Response Rate Limiting enabled during build, then you could set a rate limited like below:

  options {
           ...
           rate-limit {
              responses-per-second 10;
              log-only yes;
          };
  };

If you're satisfied with the result when reviewing your query.log, then remove log-only line and watch it take affect. The default is 5 if I'm not mistaken and it is not advised to go below that number. Also please monitor your drop ratio as you may want to tune it on nameservers that host more zones.

And yes you could do iptables, but that is ill advised as in most cases the IP filter gets in trouble before your nameserver does. Also it can't make distinctions based on the request, only on the number of packets and it's source IP. This means you will drop a lot of legal traffic.