For those of you who know the BIND name server but don't know about CouchDB, it is a distributed, fault-tolerant and schema-free document- oriented database accessible via REST. And for those who know CouchDB but don't know BIND, BIND is a DNS name server, probably the DNS name server: it powers a large majority of the world's Domain Name System.

While I was experimenting with CouchDB it occurred to me that it would make a rather sexy DNS data store, and so I started looking into using it for doing precisely that. I revised the proof of concept because I had the schema all wrong, and implemented a follow-up with a full zone in a single document -- much better. Quite a bit of feedback then got me to implement a PowerDNS pipe back-end, but I wasn't terribly pleased with it. So I implemented a BIND SDB driver, and here it is.

The Simplified Database Interface for BIND 9 is an application programmer interface (API) with which a programmer can add a back-end (called a driver in BIND SDB) to the BIND name server. BIND uses that driver to provide answers to DNS queries. BIND 9.1 introduced this simplified database interface, or SDB, to make it easy to create specialized applications.

When a zone uses SDB, BIND answers queries for the zone, not by reading information from zone master files, but instead by using the driver specified in the zone's configuration. Standard drivers distributed with BIND SDB let you use a variety of databases and files from which to retrieve data. The current BIND 9.7.2 distribution contains drivers for bdb, dir, ldap, pgsql, sqlite, tcl, and time. For example, the demonstration timedb driver returns the date and time when you query for a txt record in a zone configured to use timedb.

A single instance of BIND can have both normal zones and zones served by SDB drivers. An SDB zone has an SDB-specific database statement in a zone clause. If this is present when BIND receives a query for such a zone, BIND calls the SDB driver to resolve the query instead of using master files as for normal zones.

Adding an SDB driver to your named isn't for the faint of heart. The couch- sdb README contains some pointers, but you'll have to dig in to the BIND distribution to find the nitty gritty on how to do that. (What I really recommend is my book, where I devote a whole chapter to SDB and show you in great detail how to implement a driver.)

Upon receiving queries for zones configured to use couch-sdb, BIND invokes the couch-sdb driver which goes off and requests the zone's document from CouchDB and uses values in that document to create answers which are stuffed back into SDB and thus sent back to the DNS client.

A zone is configured in a single document which contains objects that define replies to queries on a particular zone, and you can view an example JSON document here. Let's look at some bits, though:

"_id": "",
       "_rev": "5-5629159584efcd2e63ab651aff9d19df",
       "type": "zone",
       "zone": "",
       "default_ttl": 1800,
       "soa": {
           "mname": "",
           "rname": "",
           "xserial": 69
  • The document's _id is the zone name.
    • If a serial value exists in the soa object, it must be an integer, which is used as the SOA serial. If it doesn't exist, the first integer value of the document's _rev is used; now that is way cool! -- auto-incrementing serial! (The value called xserial above will be ignored.)
    • mname and rname are used, else hard-coded values.
    • default_ttl is just that; it is used for the NS RR and for records that don't have their own TTL.
"ns": [
  • ns is an array of name servers. Names, of course; not addresses!
    • Apropos names; unqualified names are in the zone
"rr": [
               "name": "www",
               "type": "A",
               "data": [
               "ttl": 62
               "name": "@",
               "type": "mx",
               "data": "10",
               "ttl": 600
  • rr is an array of RR objects. Each of these have:

    • A domain name, which must be unqualified. (I.e. use www only.) Use @ for the zone apex.
    • A type. Upper or lower case.
    • data is the rdata for the domain. It is either a single value or an array of similar values, in which case an RRset is built.
    • An optional ttl for this RRset.
    • And do remember: Don't put a CNAME and other data together!

Configuring named to use the couch-sdb driver isn't difficult. A zone stanza defines a zone as master, and you give it a database statement. The first word in the statement, here it is couch, defines the SDB driver named will utilize. The next two parameters are specific to the couch- sdb driver: they are the URL of the CouchDB instance and the name of the CouchDB database respectively.

zone "" {
       type master;
       database "couch dnszones";
    zone "temp.aa" in {
        type master;

Some advantages of using a CouchDB back-end to BIND are:

  • CouchDB databases replicate over normal HTTP, allowing firewall administrators to accomodate said replication without having to open additional ports (53) for zone transfers (AXFR).
  • The way I've implemented the couch-sdb driver allows you to have auto-incrementing serial numbers. The way this works is that if the zone's document doesn't explicitly contain a serial field, the document's revision (_rev), which is incremented automatically whenever a document changes, is used as the SOA serial.

There are of course also disadvantages. First of all, BIND SDB is rather slow to start; this isn't a limitation of couch-sdb, but rather a design "feature" of BIND: when BIND starts up, it queries each and every zone (including those configured to use an SDB database) for the SOA and NS of the zone. This means that upon startup, CouchDB will be hit with a query for every couch-sdb configured zone. Then there is obviously the additional dependency to CouchDB: both BIND and the database back-end must be running for the name server to work. But here again, this isn't a limitation of BIND -- the same applies to whichever database-driven DNS server you want to use. The couch-sdb is currently experimental; there may be the odd memory leak in the (also experimental) CDBC library I created for this, but all in all, it appears to function rather nicely. I'm interested in reading your comments.

Flattr this
DNS, Database, dnsbook, CouchDB, NoSQL, BIND, and SDB :: 06 Oct 2010 :: e-mail


blog comments powered by Disqus