Linux: Block DNS queries for specific zone with IPTables
I have been seeing a lot of weird/bogus DNS traffic (thousands of queries a second) hitting our servers lately and I decided to try and block it. Specifically I saw tons of requests coming in for proxypipe.net
with a bunch of random hosts prepended. Things like: 6Gdb1QlP.f.proxypipe.net., mhl00ULG.e.proxypipe.net., clacqxlG.f.proxypipe.net., etc. I decided I would block all DNS requests that contained the "proxypipe.net" anywhere in the packet.
The easiest way is to use iptables to block packets that contain a specific string. The problem with this approach is that DNS packets do not contain the actual string. Instead they are encoded in this manner: X domain Y TLD
Where X is the number of bytes in the domain portion, and Y is the number bytes of characters in the TLD portion. This makes your iptables rules look like this:
iptables -A INPUT -i eth0 -p udp --dport 53 -m string --hex-string "|09|proxypipe|03|net" --algo bm -j DROP
iptables -A INPUT -i eth0 -p udp --dport 53 -m string --hex-string "|06|kitten|02|ru" --algo bm -j DROP
iptables -A INPUT -i eth0 -p udp --dport 53 -m string --hex-string "|03|www|07|puppies|04|woof" --algo bm -j DROP
Advanced:
Technically the query looks like X domain Y TLD 0
where the zero indicates that there are no more parts of the domain. This is immediately followed by two bytes indicating the type of query.
This allows you to get fancy and only block specific types of queries for a domain while allowing others:
|Type | Code| |------------| |Any | 00ff| |A | 0011| |CNAME | 0005| |MX | 000f| |AAAA | 001c| |NS | 0002| |SOA | 0006|
If you wanted to block all MX requests for domain.com
you would do a rule like this:
iptables -A INPUT -i eth0 -p udp --dport 53 -m string --hex-string "|06|domain|03|com|00000f|" --algo bm -j DROP
IPTables converts your string rules to hex, so it is helpful to add a comment so you can read them later using iptables -vnL
. You can use the iptables comment module to document your rules.
iptables -A INPUT -i eth0 -p udp --dport 53 -m string --hex-string "|06|domain|03|net|00000f|" \
--algo bm -j DROP -m comment --comment 'Block domain.net MX'