3

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?

4 Answers 4

4

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.

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.

2

There is no configuration option for dropping all queries of type ANY. minimal-responses can be used to drop the additional section of your replies except where required by RFC, making it a safe option with no real downsides. (aside from administrator troubleshooting)

Honestly, it's rather late in the game to be considering this approach. Sure, . ANY may still show up in your top queries now and then but pseudo random subdomain attacks are the current flavor of the day and emphasize packets per second over bytes per second. After that there will be something else, and so on.

The focus on rate limiting is mostly due to it being one of the most effective strategies for limiting the damage that your infrastructure can do overall. This is where your focus should be. If you're running a recursive infrastructure, make sure that BCP-38 is implemented somewhere between the customer and your outbound path. Don't run an open resolver. So and and so forth. Only once you've limited your general attack surface does it make sense to focus on attack specific strategies, because as you are discovering here those quickly lose value.

1

I'm using Unbound DNS or Knot-resolver to as DNS cache to drop ANY, PTR request. Then forward to your upstream resolver

policy.add(function (req, query)
    if query.stype == kres.type.ANY then
            return policy.DROP
elseif query.stype == kres.type.PTR then
            return policy.DROP
    end
end)
1
  • Interesting solution.
    – Tommiie
    Jan 6, 2019 at 15:20

You must log in to answer this question.