Linux – Iptables rules for Caching Nameserver

binddomain-name-systemfirewalliptableslinux

We're running Bind as a Caching-Nameserver and these are the 3 rules on our setup to handle the DNS functionality:

iptables -A INPUT -s $OUR_NETWORK -p udp --destination-port 53 -j ACCEPT
iptables -A INPUT -s $OUR_NETWORK -p tcp --destination-port 53 -j ACCEPT
iptables -A INPUT -p udp --source-port 53 -m state --state ESTABLISHED,RELATED -j ACCEPT

The first two rules are for our clients. Notice that I included TCP even though we don't allow zone-transfers since we're not hosting any zones (but I noticed some legitimate clients doing queries via TCP) and that's the reason I included it.

My question is regarding the third line. This line is for the response from upstream DNS servers (responses to our recursive queries). I thought this line was sufficient but then I noticed on the log (packets I drop that don't match any ALLOW line) that there were dozens of UDP packets coming from source-port UDP/53.

My initial thoughts were:

1) these are legitimate responses from other DNS servers that the connection-tracking of my system didn't recognized as "related"

2) these are legitimate responses but they're "late responses" and thus my system didn't recognize them.

What rule do you use for the responses on you caching nameservers? Should I allow ANY by matching just the incoming source-port udp/53 regardless of state? Do you use the connection-tracking mechanism (ESTABLISHED, RELATED) for udp?

All the best,
JFA

Best Answer

IMHO, you should specifically permit egress DNS queries on your OUTPUT chain (on both UDP and TCP, of course), and then drop the port- and protocol- specific flags from the RELATED ingress rule, e.g.:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Or, in other words, use egress policy to control outbound traffic on a per-protocol basis, and stateful matching to control the inbound responses.

The default RHEL/CentOS iptables rules work like this, albeit they default to permit any OUTPUT packet.

And yes, you will quite often see rejected packets because they were too late to match the stateful matching.