Hacking Linux Exposed

About
Authors
Contents
Reviews
Foreword
Purchase

Articles
Books
Sourcecode
Tools
Errata

Home

 


previous article
index
next article
Making the Conversion: From BIND to tinydns
By Bri Hatch.

Summary: Once your dns caching service is setup, it's time to start converting your BIND datafiles to tinydns data format.


Last week, we set up the dns caching server, appropriately named dnscache. This week, we'll set up tinydns, the process that allows you to serve your DNS data.

First, let's use the tinydns-conf program to set it up:

  # tinydns-conf tinydns dnslog /etc/tinydns 127.0.0.6

Like last week, we'll set this up on an unused IP address for testing, in this case 127.0.0.6. If you have an actual IP address that is not currently running BIND or dnscache, then you can use that instead of 127.0.0.6.

tinydns-conf uses the same arguments, namely the user to run the server (tinydns), the user to run the multilog program (dnslog), and the directory tinydns will call home (/etc/tinydns). The /etc/tinydns directory is set up almost exactly the same as /etc/dnscache from last week, such as the env, log, and supervise directories. /etc/tinydns/root will contain different data this time, of course.

Next, let's tell svscan that it should start up tinydns:

  # ln -s /etc/tinydns /service

In five seconds or so, tinydns should be spawned; however, it doesn't contain any data yet so let's learn how to put some in. Tinydns doesn't have zone files like BIND. Instead, all the data resides in one big file -- /etc/tinydns/root/data -- which is fairly readable by us humans. Tinydns actually works on a compiled version of this file, /etc/tinydns/root/data.cdb, which is in cdb (constant database) format -- a very fast-access database format created by DJB. This file format is so fast that tinydns never loads any of it's data into memory, unlike BIND which must load everything to function at all. tinydns assumes the kernel will keep frequently-accessed buffers in kernel memory (a good assumption) so you don't hit the disk that often anyway. Tinydns can keep answering queries even when the new data.cdb file is being updated.

So, lets see what's in the root directory:

  # cd /etc/tinydns/root
  # cat data
  # make
  /usr/local/bin/tinydns-data
  # ls
  Makefile         add-host    data
  add-alias        add-mk      data.cdb
  add-childns      add-ns

Our data file currently doesn't have anything in it (no biggie), but we recreated the data.cdb file with the 'make' command anyway. These add-* files are simple shell scripts you can use to add new DNS records. Let's create a new domain -- 'example.dom'[1] -- using these scripts and see what the actual records look like in the data file:

  # ./add-ns example.dom 127.0.0.6

  # make
  /usr/local/bin/tinydns-data

  # cat data
  .example.dom:127.0.0.6:a:259200

  # host -t soa example.dom 127.0.0.6
  example.dom SOA a.ns.example.dom. hostmaster.example.dom.
  1027968095 16384 2048 1048576 2560
  
  # host -t ns example.dom 127.0.0.6
  example.dom name server a.ns.example.dom.
  
  # host a.ns.example.dom 127.0.0.6
  a.ns.example.dom has address 127.0.0.6

(Note that all of our 'host' commands must specify the tinydns server's IP address, 127.0.0.6, since we're just testing this out.) The add-ns script simply adds a line of the form to the data file:

  .domain:ip_address:name:ttl

However, this one line is all that's needed to configure a domain's SOA (start of authority) record, and set up an NS record and the associated A record. Note that the default contact is hostmaster@example.dom. Make sure this email address is valid.

The TTL for the SOA is set to three days by default (259200 seconds). Instead of manually listing the NS host name, you simply provide the IP address, and it dynamically creates the hostname 'a.ns.example.dom'. If you want to add nameservers, simply call add-ns again:

  # ./add-ns example.dom 127.1.1.1
  
  # cat data
  .example.dom:127.0.0.6:a:259200
  .example.dom:127.1.1.1:b:259200

This command automatically creates a 'b.ns.example.dom' entry with the new IP address. Since we're just testing here, you should delete that last line for now using your favorite text editor.

  # vi data

Ok, now it's time to add an 'actual' IP addresses. Let's assume we have our fictitious servers on 192.168.1.0 network:

  # ./add-host www.example.dom 192.168.1.1

  # ./add-ns 1.168.192.in-addr.arpa 127.0.0.6

  # cat data
  .example.dom:127.0.0.6:a:259200
  .1.168.192.in-addr.arpa:127.0.0.6:a:259200
  =www.example.dom:192.168.1.1:86400
  
  # make
  /usr/local/bin/tinydns-data
  
  # host www.example.dom 127.0.0.6
  www.example.dom has address 192.168.1.1
  
  # host 192.168.1.1 127.0.0.6
  1.1.168.192.in-addr.arpa domain name pointer www.example.dom.

First we used add-ns to set up a zone for reverse DNS lookups (the 1.168.192.in-addr.arpa zone). The data line for our new IP address is of the form:

  =hostname:ip_address:ttl

This sets up both a forward (A) and reverse (PTR) record for this host, as seen in the output of the two host commands. If we wanted only a forward record, we could have instead used an entry of the form:

  +hostname:ip_address:ttl

This entry is created with the 'add-alias' command instead of 'add-host.

We've seen how to create SOA, NS, A, and PTR records thus far, and all using three different kinds of lines in the data file, which are pretty easy to read. Other useful lines in data include:

  • @domain:IP.AD.DR.ES:name:dist
    
    This creates an MX record for example.dom pointing to ip_address named 'name.mx.example.dom' of priority 'dist', and the appropriate A record, for example:

      # grep ^@ data
      @example.dom:127.127.127.127:mail:10
    
      # host -t mx example.dom 127.0.0.6
      example.dom mail is handled by 10 mail.mx.example.dom.
      
      # host mail.mx.example.dom 127.0.0.6
      mail.mx.example.dom has address 127.127.127.127
      
    
  • Chostname1:hostname2
    
    This creates a CNAME for hostname1 pointing to hostname2, for example

      # grep ^C data
      Cftp.example.dom:www.example.dom
    
      # host ftp.example.dom 127.0.0.6
      ftp.example.dom is an alias for www.example.dom.
    

You can use other entries as well. These options can be found within the documentation at http://cr.yp.to/djbdns/tinydns-data.html, or locally with the command

  # lynx /doc/commands.html

The nice thing about the data lines is that you can usually drop most of the fields at the end. tinydns automatically will pick appropriate TTLs. For example, you could use:

  =www.example.dom:192.168.1.1

instead of

  =www.example.dom:192.168.1.1:86400

At this point, you have all the info you need to create a new tinydns data file to handle all the DNS data you currently use. You'll also find that it is easier to read in general, and certainly easier for programs to manipulate. Here's a quick summary of the line types, including some I didn't discuss above:

Initial Char Mnemonic Purpose
. zone delimiter Create SOA and NS records
@ email delimiter Create MX records
= define/equal Create A and PTR records
+   Create A record only
C (C)name Create CNAME records
^ carat is pointy Create PTR record only
' text starts with quotes Create TXT record
Z (Z)one Create SOA record only

You can use a lot of different options for performing functions such as creating different responses depending on the client IP address, similar to BIND's views, or making records that are only good before or after a certain time -- helpful for smoothly changing DNS data without administrator interaction. Just for easy reference, here's a commented example file:

  # The example.dom domain:
  .example.dom:127.0.0.6:a

  # The reverse DNS entry
  .1.168.192.in-addr.arpa:127.0.0.6:a
  
  # A few host entries.  (The '=' means PTR records are created too)
  =www.example.dom:192.168.1.1
  =ftp.example.dom:192.168.1.2
  =shell.example.dom:192.168.1.3
  =backupmail.example.dom:192.168.1.4
  
  # Mail goes to primary first, backup if that fails
  @example.dom:192.168.1.3:primary:10
  @example.dom:192.168.1.4:backup:20
  
  # Some CNAMES
  Clogin.example.dom:shell.example.dom
  Cmailserver.example.dom:shell.example.dom

So, your task this week is to convert some or all of your BIND datafile to tinydns data format. Test things out on the temporary IP address, 127.0.0.6, and when you get all the bugs worked out, simply turn off BIND (Forever! Huzzah!) and have tinydns listen on your actual IP address.

If, for example, you were using 192.168.1.1 with BIND, then do the following to have tinydns take over:

# echo '192.168.1.1' > /etc/tinydns/env/IP
# svc -d /etc/tinydns
# svc -u /etc/tinydns

Now you are 100% BIND free! Congratulations and welcome to the club of the secure. Enjoy watching your friends run around like headless chickens the next time BIND bugs are found as they frantically try to upgrade machine after machine.

Though the native tinydns data file format is pretty painless and takes up a lot less room than BIND zone files, you may have a lot of data to convert. If that's the case, all is not lost. Next week, I'll show you how you can quickly 'import' your old BIND zones into tinydns data format.

NOTES

[1] Yes, '.dom' is not a valid DNS suffix. I'm intentionally choosing something that will not clash with anything out in the real world.


Bri Hatch is Chief Hacker at Onsight, Inc, and author of Hacking Linux Exposed and Building Linux VPNs. He has a hard time believing all these folks who say you don't need air conditioning in Seattle, when his apartment was still 91 degrees at 2am. Bri can be reached at bri@hackinglinuxexposed.com.


Copyright Bri Hatch, 2002.

This article was first published here in ITworld.com Inc., 118 Turnpike Rd., Southborough, MA 01772  on 06-Aug-2002.

previous article
index
next article