[LWN Logo]

Dynamic content in the DNS system using Dents

Todd Lewis ( tlewis@mindspring.net)

1. Introduction

2. The Dents driver module system

3. mod_msg_tgl

4. Advanced Features

5. The Good, The Bad, The Ugly

6. Conclusion

7. Resources

1. Introduction

I am the head of the Dents project, a group of programmers working on building a GPL'd server for the Internet's DNS protocol. Dents is still very much a work in progress, and so I'm not going to talk about all of its features and how everyone should be using it. We hope to do a general release Real Soon Now, and at that time I hope return and tout all of great reasons to start using Dents.

Today, I'm going to talk about one teensy part of Dents, our driver module system, and about one driver module in particular, one I've recently written, which I thought certain readers may have an interest in.

2. The Dents driver module system

First, a little background. named, the DNS server which is part of the BIND distribution, is the dominant name server today. Most DNS servers, with the notable exception of Dents, are derived, in whole or in part, from named. named forces you to store your DNS data in a zone file, a flat text format for representing DNS data. There are external modifications to named which allow alternative approaches, but they are not integrated into the main named source code base.

Lots of people would like to store their DNS data in a relational database, e.g., or perhaps serve dynamic data via DNS. This is very hard to do with named, because it stores all DNS data in a single, monolithic tree (or hash table, I forget.) The notion of a single tree storing all data is so ingrained in the named source code that it is very hard to modify it to support using alternative methods.

By contrast, Dents treats DNS zones in a similar way to that in which Linux or any other modern unix supports file systems; they are "mounted" using a driver. These drivers take the form of shared object files which Dents loads at run-time. The mechanism is similar to the way in which the GTK+ widget set does themes. (I looked a lot at the GTK+ module code when writing the first version of the Dents driver module system.) Like GTK+, we have the capability of loading new drivers while we are running, not just at start time. Indeed, we hope that our CORBA-based control facility which is presently under development will allow us to load zones into a running server without having to restart that server. That's a discussion for another day, however.

The upside of all of this is, that if you can write code that will take in a DNS question and spit out a DNS answer, then you use that code to generate DNS data. This is a really big change in how DNS works. Remember when CGI was born and the web went from a gopher-knock-off to a wonderful expanse of dynamic content? We hope to unleash a similar storm of creativity in the DNS space.

The Dents driver module system is several months old at this point, and it works really well. All DNS functionality in Dents is done using these driver modules; even our recursion functionality is separated from the main server into a separate driver module. We have drivers that support zone files (mod_stddb), drivers which serve data out of a relational database (mod_mysql_eza), and drivers which don't store any DNS data at all and instead generate answers algorithmically based on the query (mod_frl).

This is really great, and we're all very excited about it. The main problem with this approach is that you have to be able to program in C (or some binary-compatible language) in order to write a Dents driver. This really bugged me, because I much prefer programming in perl or shell to programming in C. I know lots of people who are fine perl or shell or python programmers who might not be able to program in C. I really wanted for these people to be able to create dynamic DNS data, the same way that CGI allows people to create dynamic web content. So, I wrote a driver to make it possible, and it's this driver that this article is all about.

3. mod_msg_tgl

mod_msg_tgl is a Dents driver which spawns off external programs (called driver processes, or dprocs) and answers DNS queries by passing messages back and forth with those driver processes. This communication is done with pipes; the driver processes find their stdin originating from Dents and their stdout terminating to Dents. The message format that they use to communicate back and forth is a very simple, line-oriented text protocol.

Here is an example of what a conversation between mod_msg_tgl and a driver process. Say that a Dents server is configured to serve the domain "test.dents.org" using mod_msg_tgl, which in turn would use the script /usr/local/bin/dns_server.sh to serve the data. You would configure the server by putting the following line into your named.boot file:


mod-primary test.dents.org mod_msg_tgl /usr/local/bin/dns_server.sh

Then say you query the server for www.test.dents.org, like this:


host -t a www.test.dents.org.

Well, in this case, the server, via mod_msg_tgl, would send a message to the driver process that looks like this:


>>> 2 Q www.test.dents.org. A

Let's look at what all of that means:

So, the driver process sees this, does whatever he wants to do, and then returns a message consisting of two lines:


<<< 2 A www.test.dents.org. A 59.138.101.147


<<< 2 F

Just to reinforce the simplicity of what's going on here, let's replay all of that. First, what the client sees:


$ host -t a www.test.dents.org.
www.test.dents.org has address 59.138.101.147

And the exchange on the server side that made this happen:


>>> 2 Q www.test.dents.org. A
<<< 2 A www.test.dents.org. A 59.138.101.147
<<< 2 F

If this seems simple, that's because it is supposed to be! Let's take a look at an actual application of this technology, clock.sh. This script responds to DNS queries with the present time. First, the script:


#!/bin/sh

# clock.sh : an sh script for use with mod_msg_tgl to serve the time
# c 1999, Todd Lewis <tlewis@mindspring.net>
# licensed under the terms of v2 of the GPL

while read a b c d
do
        if [ $b = "ZL" ]
        then
                echo "$A SOA $c `uname -n` root.localhost 100 3600 900 3600 3600"
        elif [ $b = "Q" ]
        then
                echo "$a A $foo[3] TXT The_time_is_`date +%H:%M:%S`"
                echo "$a F"
        else
                echo "$a E 4"
        fi
done

We tell Dents to use this script with mod_msg_tgl by including the following line in our named.boot:


mod-primary time.dents.org. mod_msg_tgl /usr/local/bin/clock.sh

We start Dents:


dents -c named.boot

And then we query away:


reflections% dig @localhost www.time.dents.org. -p 1053

; <<>> DiG 8.1 <<>> @localhost www.time.dents.org. -p 
; (1 server found)
;; res options: init recurs defnam dnsrch
;; got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUERY SECTION:
;;      www.time.dents.org, type = A, class = IN

;; ANSWER SECTION:
www.time.dents.org.     1H IN TXT       "The_time_is_23:21:36"

;; Total query time: 39 msec
;; FROM: reflections.mindspring.com to SERVER: localhost  127.0.0.1
;; WHEN: Tue Oct  5 23:21:36 1999
;; MSG SIZE  sent: 36  rcvd: 69

"But Todd", I can hear you ask, "I want to serve glue records and poison DNS caches and serve out all of my Hesiod data. Can I do that with mod_msg_tgl?" The answer is that yes, you can do all of this and more. Just because, out of the box, mod_msg_tgl is designed to be easy to use, that doesn't mean that it isn't also a powerful DNS engine!

4. Advanced Features

4.1 Optional Answer Arguments

The Answer message format is simple. Perhaps too simple, you DNS studs out there may be saying. "Say that I want to specify a different ttl for my answer, or place it in a DNS section other than the Answer section? Can I do that?" The answer is, of course you can!

Your standard "A" message can be followed by a sequence of "key=value"-style optional settings. If you want to have your clock program issue resource records with a ttl of 0 instead of the default ttl, then instead of saying this:


<<< 2 A www.time.dents.org. A 59.138.101.147

you can say this:


<<< 2 A www.time.dents.org. A 59.138.101.147 ttl=0

Options which are presently supported are:

The mod_msg_tgl documentation explains all of this in detail.

4.2 SOA Support

As you may have noticed, our example script detected if the operation code was "ZL" and, if so, responded with an "SOA" message. "ZL" stands for "Zone Load", and driver processes can respond either with an error message (op code of "E"), or with an SOA message. The server caches this setting for the SOA and uses it in all future queries. A driver process may update that SOA any time he feels like it, assuming that it's his turn to talk. The server will use the default ttl and all other settings from the SOA in the serving of that zone.

4.3 Extended Query Support

My above description of how the "ZL" exchange works left out a little detail; before answering with "SOA", the driver process can specify a series of settings which he would like for that zone. (You could also specify settings before returning an error, but that wouldn't accomplish anything.)

Here's what such an exchange would look like:


>>> 1 ZL time.dents.org.
<<< 1 O time.dents.org. EXTENDEDQ
<<< 1 SOA time.dents.org. reflections.mindspring.com root.localhost 100 3600 900 3600 3600

These are presently the only two supported options:

The extended query format results the driver process receiving a message like the following:


>>> 3 EQ www.time.dents.org. TXT IN 10 127.0.0.1 2000 0 1

I'll be brief on what all of this means; here's the summary from the documentation:


FORMAT: <seq#> EQ <name> <qtype> <qclass> <id> <client-ip> <client-port> <opcode> <recursion-desired>

As you can see, you get all sorts of neat stuff to play with. Want to give the client his own IP back as an answer to all queries? Now you can. (Remember about caching servers, though, before you go playing jokes based on this on your friends.)

5. The Good, The Bad, The Ugly

5.1 What mod_msg_tgl is good for

Why would anyone want such a thing? Well, I personally am using mod_msg_tgl right now in order to prototype a Dents driver in perl before implementing it in C. This new driver uses the awesome Berkeley DB v2 to store DNS data in a key-value database. You should be able safely to update the database externally, using BDB's transaction support, and have your changes take effect immediately in DNS. This, in turn, should make all sorts of cool DNS tricks with dynamic data possible.

Sure, I could write this from day one in C, but if I change my mind about how I want the data laid out, as I've already done once and may do again, then it's really a pain to rewrite all of that code. Since I'm doing the prototype in perl, however, I just tie the database to a hash, and all is right with the world; changing how I have the database laid out is a snap. When I am happy with how it all looks, then I'll take the perl code, convert it to C and make a full Dents driver out of it.

5.2 What mod_msg_tgl is bad for

5.3 Future Directions

mod_msg_tgl is still a work in progress; there are several improvements which I would like to make:

6. Conclusion

While Dents is not yet a suitable general-purpose DNS server, we are making rapid progress; at this point we are mostly fixing bugs before unleashing our creation on the world; named will serve just fine in the interim. However, mod_msg_tgl is technology which is working fairly well and which has no analogue available today. For people who have need to do innovative things with DNS, I encourage you to take a look at it and see if it meets your needs. You can find out more about mod_msg_tgl and Dents in general below in our ( Resources) section.

7. Resources