This page describes how to deploy a DNS response-code filter using iptables. The DNS response-code filter drops packets with a given DNS response (such as NXDOMAIN). This filter is useful when an attack uses many random names, causing many negative responses. Since normal traffic also has negative responses, this filter has a high false-positive rate, but it allows positive queries to proceed.
DNS replies can be larger than the query size that exhaust egress network bandwidth. Some attacks make random queries, all having the same reply (usually “non-existent domain”). We can drop the replies with that response, and pass other replies. Response blacklisting is an imprecise filter with a high false-postive rate, since normal traffic often has the same replies (negative replies from Google Chrome’s random queries to probe for captive portals , or because users mistype URLs). However, we see Response Blacklisting as a defense of “last resort” that can help preserve some responses, even under significant attack.
Each DNS response has a 4 bits field to represent the response code. Different response code indicates different characteristics of the DNS replies. For example, response code 0 indicates “no error”, response code 3 indicates “non-existing domain” (NXDomain). To block the NXDomains we need to block the replies which have 3 in their response codes.
We check four bytes of the outgoing replies starting from the 28th byte for UDP, and the 54th byte for TCP to get the response code. We use the u32 option of IPtables to check the four bytes. If the response matches 3, we drop those replies. We use the following two rules for both UDP and TCP to block the replies with response 3 (“NXDomain”):
sudo iptables -A OUTPUT -p udp -s $IP --sport $PORT -m u32 --u32 "28 & 0x000F = 0x3" -j DROP
sudo iptables -A OUTPUT -p tcp -s $IP --sport $PORT -m u32 --u32 "54 & 0x000F = 0x3" -j DROP
Here, $IP means the source IP from where the replies are generated (the server address).
$PORT means the source port from where the replies are generated (for DNS this is 53).
These rules are for outgoing packets.
0x000F mask can be different based on the endianness of the machine.
Also, we use u32 option that compares four bytes but we haven’t checked for options that compare less number of bytes.
For related publications, please see the ANT publications web page.