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:
What you see is the domain name broken down into each sub section (www, example and com) with the sub section length before it.
That’s how the specs specify how the qname should be used in the protocol. To give another example, this is how test.mysite.defragged.com would appear:
Test has 4 bytes in length, followed by mysite with 6 bytes in length, etc. That applies to all domains going through DNS.
Numberic Value is a Hexadecimal
Make note that the numeric values are hexadecimal values, not decimals. For example, if a text string had 10 characters it would be presented as 0a and 100 characters would be represented as 64.
An easy way to verify the hexadecimal value is to use a decimal to hexadecimal converter.
Blocking DNS requests via IPtables
With this basic knowledge we can 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, if 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 them later when running iptables -nvL (remember that it will convert to hex).
And that’s it. Hope you found it useful.
Sharing is caring!