If there is a tool we love, it is called iptables. The default firewall tool chain on Linux has a lot of options to filter pretty much any traffic you wish.
In this Tips and Tricks, we will show you how to block DNS requests (domain names) via iptables. Enjoy!
DNS is binary protocol, where the domain name and the record type (A, AAAA, MX) are all encoded into the DNS query and response packets. If you were trying to filter www.example.com, you would not see the whole domain name in the packets.
What you would see is:
Which is pretty much the domain name broke down into each sub section (www, example and com) with the sub section length before it. Simple no? That’s how the specs specify how the qname should be used in the protocol. To give another example, that’s how test.mysite.cloudflare.com would show up:
Test has 4 bytes in length, followed by mysite with 6 bytes in length, etc. That applies to all domains going through DNS.
Blocking DNS requests via IPtables
With this basic knowledge in mind, we can now block DNS requests via iptables by leveraging the hex-string module. DNS requests use port 53/UDP by default, so if we want to block www.example.com, we would do:
/sbin/iptables -I INPUT -p udp --dport 53 -m string --hex-string "|03|www|07|example|03|com|" --algo bm -j DROP
See what we did? We passed the string to the hex-string module, broke down into multiple sections: length, sub domain, length, sub domain, etc. A powerful feature of hex-string is that it automatically converts normal strings into hex internally, making our life a lot easier when writing rules (we didn’t have to convert www into hex, for example). However, if you look at your iptables rule lists, you would see them all encoded into hex:
# iptables -nvL 0 0 DROP udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 STRING match "|03777777076578616d706c6503636f6d|" ALGO name bm TO 65535
In addition to the domain name, ff you want to restrict by a specific DNS record, you can add them after the domain name (000001 for A records, 000006 for SOA records, etc). So to block A records for www.example.com you would do:
/sbin/iptables -I INPUT -p udp --dport 53 -m string --hex-string "|03|www|07|example|03|com|000001|" --algo bm -j DROP
I recommend commenting those rules so you can easily find the later when running iptables -nvL (remember that it will convert to hex).
And that’s it. Hope you found it useful.