Using a Local Root Zone with djbdns

Posted: Sun, 7 August 2011 | permalink | No comments

In my continuing war on the effects of craptastic mobile Internet connectivity, I came across a suggestion to host a local copy of the root zone alongside your local DNS resolver. It’s an interesting idea, so I’ve decided to give it a go, despite the potential problems (I’m confident I can manage the risks).

I was surprised to find that nobody had a guide on setting this up using djbdns1 so… I’ve written one.

If you’re thinking of doing this yourself, heed some words of caution: It is imperative that you keep your local cache up to date. If you set this up, and don’t maintain it, you will have a slow, gradual degradation of Internet service as the live root zone diverges from your local, out-of-date cache.

If you set this up locally, just for yourself, that’s one thing; all you’re doing is breaking your own machine. If you want to do this for the ISP you run, though, you’re doing your customers a grave disservice if you don’t automate the cache update, and setup some means of monitoring that your cache is kept up to date (a SOA check against the live roots, or at least a check to make sure that your data.cdb file is no more than a couple of days old).

The Design

For simplicity, I decided to run a dedicated tinydns instance that only serves the root zone. This makes it easy to periodically refresh the root zone that I serve with a script, which I run daily, without needing to integrate with the database of any other tinydns instances I’ve got running (I have a couple on my laptop for testing). I’ve set this up on an arbitrary loopback address (127.53.53.53), so it’s inaccessable from anywhere other than localhost, and so my local dnscache instance just forwards root zone requests to it.

Setup the infrastructure

You’ve now got a minimal tinydns suitable for serving a local cache of the root zone to anyone on your local machine who asks. But where’s the data?

Script the root zone processing

The following script should do the job nicely. Drop it somewhere useful and chmod a+x it. If you put your tinydns somewhere else, change the TINYDNS_DATA variable at the top.

Run it once by hand to “seed” your root cache, then add it to cron for a nightly update.

#!/bin/sh

set -e

TINYDNS_DATA="/etc/service/tinydns-root/root/data.cdb"

###########################################################################

WORKDIR="$(mktemp -d)"
trap "rm -rf ${WORKDIR}" EXIT

cd "$WORKDIR"

wget -q http://www.internic.net/domain/root.zone.gz
wget -q http://www.internic.net/domain/root.zone.gz.sig

if ! gpgv root.zone.gz.sig root.zone.gz >/dev/null 2>&1; then
        echo "Root zone signature validation failed -- this is probably
really bad" >&2
        exit 1
fi

gzip -d root.zone.gz

egrep -v '[[:space:]]IN[[:space:]]+(RRSIG|DNSKEY|DS|NSEC)[[:space:]]' root.zone \
     | /usr/local/bin/bind-to-tinydns . data btttmp

tinydns-data

cp data.cdb "${TINYDNS_DATA}"

Test

The simplest test, to make sure you’ve got everything running, is just to request something from the root zone:

dig @127.53.53.53 com IN NS

If you get something useful (compare against dig com IN NS for a sanity check) then everything’s probably working well.

Point dnscache to your local root server

echo 127.53.53.53 >/etc/service/dnscache/root/servers/@
svc -k /etc/service/dnscache

And you’re away.

  1. For all it’s oddities, it’s a very tidy piece of software, and takes up so little resources on a modern system that it’s presence is practically invisible – it uses less memory than init


Post a comment

All comments are held for moderation; markdown formatting accepted.

This is a honeypot form. Do not use this form unless you want to get your IP address blacklisted. Use the second form below for comments.
Name: (required)
E-mail: (required, not published)
Website: (optional)
Name: (required)
E-mail: (required, not published)
Website: (optional)