Security Basics mailing list archives

Re: Securing DNS Server


From: Bennett Todd <bet () rahul net>
Date: Tue, 5 Nov 2002 13:22:50 -0500

2002-11-01-19:31:14 Naman Latif:
I am trying to restrict Access to our DNS Server from Outside using a
Cisco IOS Firewall.

This can be done, more or less of completely effectively. The very
best approach is to simply make sure no insecure services are
running on your DNS server, so that the protection you enforce on
your "IOS Firewall" (that's a vague term, could mean various
different things) doesn't have to be 100% perfect. Failing that, you
can at least approach a pretty tight protection, at least with some
things that could be called "IOS Firewalls".

Initially we only had Port 53 Access to this Server from outside.
But it turned out that when our DNS Server has to query a root
name server, it sends out a UDP query with a random higher (>1023)
source port number, which means that I will have to open >1023
Ports access to this server from outside.  In this situtation How
do I protect my DNS server from outside attacks on higher port
numbers ? Is there a range of Source Port numbers that a BIND DNS
server would use, when querying outside servers ?

Whew. There are so many questions implicit in that.

Let's start off by making a really important distinction in DNS
servers --- one that is sadly not made by BIND, and so therefore
isn't made clear by the DNS RFCs (since they're deeply and
unfortunately wedded to BIND).

There are two fundamentally different kinds of DNS server.

There are authoritative content servers. They offer content from
zone data files, in response to iterative requests, and are
referenced by NS records in other nameservers that "delegate"
certain zones to them. Besides serving their own authoritative final
data, they can also serve additional NS records that delegate
subdomains to other servers. These are the servers that provide
parts of the DNS namespace. They are only queried by recursive
resolvers, AKA cacheing nameservers.

The second variety of "DNS server" is a cacehing nameserver, or
recursive resolver (two names for the same architectural component).
A cacheing nameserver is referenced by an IP addr listed in
/etc/resolv.conf; it receives recursive queries, and makes iterative
queries to work out the answers, which it then returns.

So in a typical DNS lookup, you say go "ping foo.bar.example". Your
ping program is linked with resolver libraries; it calls a routine
from that library "gethostbyname" or something like that. That
routine checks /etc/resolv.conf to get the IP address for your
recursive resolver.  The library routine then sends a recursive
DNS query, asking for the "A" record (maps hostname to IP address)
for "foo.bar.example", to the DNS server whose IP addr it found
in /etc/resolv.conf. That is the cacheing nameserver. It's got a
list of the root nameservers as part of its configuration; they're
authoritative for the root of the DNS namespace. All they serve is
delegations. So the cacheing nameserver picks on of those, perhaps
a.root-servers.net. It sends it an iterative query for the A record
for foo.bar.example. It receives a reply; the reply either says
"NXDOMAIN", if there is no such top-level-domain (TLD) as .example,
or else it lists one or more NS records for authoritative servers
for the .example TLD. Assuming it got some delegations, it then
picks one of those at random, and asks _it_ for the A record for
"foo.bar.example". The gtld-servers don't have much final
authoritative data either, so it'll either get an NXDOMAIN, or else
a delegation to authoritative nameservers for "bar.example". Try
again, it'll ask one of them, and either get the real answer, or
else NXDOMAIN. Besides picking a first server to try at random in
each step, there's also retries, and a local cache (that's why
recursive resolvers are called cacheing nameservers) to speed things
up.

Now BIND complicates the picture unnecessarily since one daemon,
named, is both the cacheing nameserver and the authoritative
nameserver. Other DNS server packages separate these cleanly; I
really recommend using djbdns.

On to our muttons. Since your DNS server is trying to query root
nameservers, it's definitely functioning as a recursive resolver.
That means it's sending queries to other nameservers, and must be
able to receive their replies. All DNS queries can be carried either
on UDP or TCP; initial queries (except for zone transfer) are issued
on UDP; if the reply exceeds 512 bytes in length, the query is
re-issued over TCP. So to make sure DNS works robustly, you must
allow both.

Now for the role of cacheing nameserver, the DNS server is making
queries out to the internet, and must be able to receive the
replies. The TCP part is easy, just allow outbound TCP queries to
port 53. If you've a stateful firewall that's easy, and if you
don't, that's still easy --- just allow all outbound tcp dstport=53
traffic, and inbound tcp srcport=53 where the flags contain SYN and
ACK or where the flags do not contain SYN (flags=SYN is TCP
connection request, you want to block that, but flags=SYN+ACK is the
response to a SYN request, you need to allow that to have TCP work;
there are other "don't care" flags that you need to ignore). UDP is
trickier; if you've got a stateful packet filter it can allow
incoming UDP packets that appear to be replies to an outbound query
within the last 30 seconds or whatever, so just allow outbound UDP
dstport=53 with replies. For a stateless packet filter, you have to
allow incoming srcport=53, so if you've only got stateless packet
filtering, you must make sure your DNS server doesn't have any
vulnerable UDP services --- or if it does, you must protect it
locally, perhaps with on-host packet filtering.

If your DNS server is also an authoritative nameserver, then you in
addition need to allow the incoming queries, UDP dstport=53 and, if
your zone data has any huge record sets that might make a query
exceed 512 bytes, incoming TCP dstport=53 as well.

Don't run BIND, though, it'll bite ya. Besides confusing you and
everyone else who has to deal with it, BIND also has a terrible
security track record. Use djbdns.

-Bennett

Attachment: _bin
Description:


Current thread: