Blocking DNS Amplification attacks using IPtables

If you are managing a Linux server, you’ve probably heard about DNS amplification attacks which make use of misconfigured DNS servers. DNS amplification is a DDoS technique which uses a large reply by DNS resolving the target. This is accomplished by spoofing the query with the source IP of the target victim to ask for a large DNS record, such as an ANY reply of the ROOT record or, which is most commonly found. The request itself is usually around 60-70 bytes, while the reply is as much as 2-3K. That’s why it’s called amplification. It will not only make your network participate in the attack, but it will also consume your bandwidth. More details can be found here.

Blocking these kinds of attacks can be tricky. However, there are some basic iptables rules that block most of it, using them in combination with fail2ban. As usual, your mileage might vary.
The commands below were tested and executed on Ubuntu Server 16.04 LTS 64-bit using fail2ban 0.10.

First, add this IPtables rule to your /etc/network/interfaces.tail so it’s automatically loaded each time your network interface(s) restart and/or your server (re)boots.

post-up iptables -A INPUT -p udp -m udp --dport 53 -m limit --limit 5/sec -j LOG --log-prefix "fw-dns " --log-level 7
post-up iptables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --set --name dnsanyquery --mask
post-up iptables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --name dnsanyquery --rcheck --seconds 1 --hitcount 1 -j DROP --mask

Note: –mask depends on your network configuration. Type ifconfig to find your mask.

The first iptables rule is for use with fail2ban. The second and third rule are used in conjunction with each other:
The second iptables rule looks for the incoming udp packets on port 53 and searches the first 50 of packet for hex string “0000FF0001” (which is equivalent to an ANY query) and saves it under dnsanyquery (under /proc/net/ipt_recent/dnsanyquery) with a timestamp.
The third iptables rule drops the packet if the source ip and query type (in this case “ANY”) matches and occurred more than one time in the past second.

Next, create the file /etc/fail2ban/filter.d/iptables-dns.conf with the following contents:


failregex = fw-dns.*SRC=<HOST> DST
            ^.* security: info: client #.*: query \(cache\) './(NS|A|AAAA|MX|CNAME)/IN' denied

ignoreregex =

And add the following to /etc/fail2ban/jail.local to ban the IP for 1 day (No jail.local file? Shame on you! Don’t edit the jail.conf file directly, It will be overwritten during updates. Instead, make & edit a copy like so: cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local)

# see for more info
enabled = true
ignoreip =
filter = iptables-dns
action = iptables-multiport[name=iptables-dns, port="53", protocol=udp]
logpath = /var/log/kern.log
bantime = 86400
findtime = 120
maxretry = 1 

Finally, restart fail2ban and your network interface(s) or server to enable the rules. After doing so, check using fail2ban-client status if you see the ‘iptables-dns’ jail listed. If fail2ban refuses to start, check your regex for typos using fail2ban-regex /var/log/kern.log /etc/fail2ban/filter.d/iptables-dns.conf

That’s all folks! Comments or suggestions? Let me know in the comments!

Source: A Realistic Approach and Mitigation Techniques for Amplifying DDOS Attack on DNS in Proceedings of 10th Global Engineering, Science and Technology Conference 2-3 January, 2015, BIAM Foundation, Dhaka, Bangladesh, ISBN: 978-1-922069-69-6 by Muhammad Yeasir Arafat, Muhammad Morshed Alam and Feroz Ahmed.

12 thoughts on “Blocking DNS Amplification attacks using IPtables

  1. A copy/paste of your regex results in:

    No ‘host’ group in ‘^.* security: info: client #.*: query \(cache\) ‘./(NS|A|AAAA|MX|CNAME)/IN’ denied’

    What’s the fix?

    1. Hi. The syntax should be correct as I’m currently using it on three different servers. Please double check the quotes, those might get messed up while copy-pasting. Thank you

  2. Using Ubuntu 16.04 TLS and Fail2Ban v0.10.1 i get the following message when i do the fail2ban-regex command as described in the post:

    Use failregex filter file : iptables-dns, basedir: /etc/fail2ban
    ERROR: No failure-id group in ‘^.* security: info: client #.*: query \(cache\) ‘./(NS|A|AAAA|MX|CNAME)/IN’ denied’

    Fail2ban does however start and show the jail as active, is this suppose to happen or do i need to change something?

      1. Hi Freek.

        I’m facing the same problem as Xeltor and darpachief comments.
        I’ve checked that iptables-extensions are in fact installed, loaded and working, as iptables doesn’t have any problem.

        The problem is fail2ban regex itself, something is wrong here:
        ^.* security: info: client #.*: query \(cache\) ‘./(NS|A|AAAA|MX|CNAME)/IN’ denied

        Can you please check if having problems too with this command on your servers?
        fail2ban-regex /var/log/kern.log /etc/fail2ban/filter.d/iptables-dns.conf

        Thank you!

  3. This statement is incorrect: searches the first 50 of packet for hex string “0000FF0001”

    It does not search the first 50. It searches beginning at offset 50.
    Furthermore it is not the offset of the packet but the offset beginning at the IP header (IP tables does not process the Ethernet header portion of the packet).

  4. Hello Freek,

    what about securing ipv6 ? do you have a guide on rate limiting etc for ipv6 as well? I am hosting a pi-hole VPS with ipv6 enabled and concerned that the above guide will only stop attacks on ipv4.

  5. I’m having the same issue as Arien and Xelter. Have checked carefully to ensure that nothing got messed up with the copy and paste. Would like to use your instructions to prevent my public pihole from being used for DNS amplification attacks. Running Ubuntu 18.04.1 and Fail2Ban 0.10.2

    Thanks for your great work!

  6. Here’s a transcript:

    > root@perky:/home/scott# fail2ban-regex /var/log/kern.log /etc/fail2ban/filter.d/iptables-dns.conf
    > Running tests
    > =============
    > Use failregex filter file : iptables-dns, basedir: /etc/fail2ban
    > ERROR: No failure-id group in ‘^.* security: info: client #.*: query \(cache\) ‘./(NS|A|AAAA|MX|CNAME)/IN’ denied’

Leave a Reply

Your email address will not be published. Required fields are marked *