DNS server with djbdns (VegaDNS GUI + bonus replication)

djbdnsThis is my personal guide to setup djbdns tinydns DNS server to publish domain name information to the Internets. If djbdns, tinydns, name server, dns are strange words just move along, move along…

If you followed my guide to install and setup a tinydns resolver (dns cache), there is already in the system the main tools to proceed. If not check the previous guide and install djbdns and daemontools. Get daemontools up and running and reading from the /service directory (we don’t annoy our good friend Daniel J Bernstein PhD).

First step create the needed users (dnslog is already present at your system if you followed the dns cache guide)

pw useradd -n tinydns -s /usr/sbin/nologin
pw useradd -n dnslog -s /usr/sbin/nologin

Now the magical command that does (almost) everything for you. Replace a.b.c.d with the ip address with the ip that you want to run the DNS server.

tinydns-conf tinydns dnslog /etc/tinydns a.b.c.d

And now start it

ln -s /etc/tinydns /service/tinydns

We can query it with dig or some other dns querying tool (even that with no domain data loaded we will get no response). We are going to use a djbdns command, dnsq (sends a non-recursive DNS query to DNS server). As usual replace a.b.c.d to the real ip address of the server you just set up.

dnsq a domain.com a.b.c.d

It will hang and timeout. DON’T PANIC, it’s normal behavior from tinydns, domain.com isn’t on data there is no answer back, but you can (should) check the log to confirm that it has received the dns query.

tail /etc/tinydns/log/main/current | tai64nlocal

For this server publish any information to the world and do some useful work it should be made a name server. Go to your registrar and register the ip address of the tinydns instance as a Domain Name Server (the interface and nomenclature used is different from registrar to registrar). What you are actually doing is to add a Glue Record (technical details are out of the scope of this post, but feel free to google it).

Now the final piece of the puzzle, to load in tinydns the domain name information that you want to publish. You can go to /etc/tinydns/root directory and use the commands there (add-alias, add-host, etc) to add domain data and run make to compile the data.cdb file (the fast key/value database that tinydns uses), also you can manually edit the data file with the domain information in the correct format and then run make. There is nothing wrong with these methods (manual editing is quite powerful and flexible) but if you have to maintain several domains data this is quite daunting. So, VegaDNS to our rescue!

vegadnsVegaDNS is a web-interface to the tinydns system. You will need Apache (or other web server), MySQL, PHP and Wget. It’s pretty easy to install. You will need to customize two files, webroot/src/config.php and webroot/update-data.sh. In config.php the usual stuff, paths, database settings, etc. Take care to $trusted_hosts, this is the list of ip addresses that can get the data in Vegadns database dumped in tinydns format. Then you must customize update-data.sh with your VegaDNS url and tinydns paths. This shell script (update-data.sh) fetches via WGet the VegaDNS dump in tinydns format and updates data and data.cdb.

It has very cool feature, it’s the possibility to get data from several VegaDNS instances and load up in your tinydns server (i use it all the time in customers FreeBSD jails to provide secondary DNS server). Also, is not a bad security practice to move this script out of webroot (or at least block it with some deny rule at web server level). After setting up some domains in VegaDNS you should run in command line update-data.sh, if no errors are printed and you get an updated data and data.cdb file you are set to put it to run automatically with CRON. You can change the frequency of updates checks (i go for 6 minutes interval), so run crontab -e and:

*/6 * * * * /path/to/your/update-data.sh

Server Replication

Normally to publish a domain you will need two domain name servers (a primary and a secundary). If you followed the guide tinydns is patched with the Jumbo patch. Among several things it allows you to configure tinydns to listen to multiple ips, just put them comma separated in /etc/tinydns/env/IP and restart tinydns. But this is not real replication, if you have 2+ servers you will want to have replication between 2 different machines, so if there is a problem in server number one, server number two will carry on DNS service.

There are two typical solutions for this, AXFR a replication dns protocol across server. This route will imply running yet another daemon (the AXFR service), and the protocol is not very efficient and can bring security concerns, DJB himself says:

Note that there are much better DNS replication protocols

Another route is to setup replication trough rsync, server one rsyncs data and data.cdb to server two, and it’s a pretty decent solution, you must setup ssh domain keys between the servers and the typical setup process is detailed here by DJB (subsection Replicating your DNS service).

If you have VegaDNS managing primary, there is a much simpler way to replicate the data between two (or more) servers. Setup secundary normally, and then just copy to secondary update-data.sh from the VegaDNS package and run it with CRON as you do in primary. Also don’t forget to add the secondary IP to $trusted_hosts in config.php in the primary. It’s pretty damn easy and your domain data will be exactly replicated in both of the servers. If primary fails, secondary will trow an error on update-data.sh run, but will keep the last good non-error data!

Like always (the disclaimer), this works very good for me but can work very bad for you, so use this information at your own liability.

Leave a Reply