http://www.free-x.ch/pub/djbdns.html Installing djbdns on a FreeBSD server

Installing djbdns on a FreeBSD server

Georg Wagner

1  Introduction

I run a small network of FreeBSD machines at home. One of these machines acts as a gateway to the internet via a leased line. On this gateway machine I use ipfilter as the firewall and snort as the intrusion detection system. Since the network is small and has only 4 machines, including my wife's Windows client, I kept the lookup table of machines and their IP addresses in /etc/hosts on each of them. But in future I want to run my homepage, "The FreeBSD Pages" http://www.free-x.ch/ on my own server. This was reason enough for preparing to install a DNS server of my own. Since my knowledge of running a DNS server was limited, I bought Paul Albitz and Cricket Liu's DNS and Bind book and read it. My impression was that it would be a daunting job to get a secure DNS server running, meaning one DNS server on the firewall hiding all internal information from the outside world and another one in the internal network.

While searching for information on DNS I stumbled across the website of Felix von Leitner http://www.fefe.de where djbdns was mentioned. One feature of djbdns, called split horizon, seemed to solve the problem of running a secure DNS server on a firewall. So I decided to give it a try.

2  Installation

After collecting and digesting the following information:

Dan Bernstein's djbdns homepage http://cr.yp.to/djbdns.html

Life With djbdns http://www.lifewithdjbdns.org

Installing djbdns (DNScache) for Name Service http://www.securityfocus.com/frames/?focus=linux&content=/focus/sun/articles/dnscache.html

Unofficial djbdns home page http://www.djbdns.org

Unofficial FAQ by Felix von Leitner http://www.fefe.de/djbdns/

man pages for djbdns ftp://ftp.innominate.org/gpa/djb

I searched the ports collection for djbdns and it was, as expected, already there so I entered the following commands:

# su toor

# cd /usr/ports/net/djbdns

# make install

and left for a coffee while the installation ran.

The dependencies djbdns needs to run, ie. daemontools, were resolved automatically by the ports collection.

3  Configuring

The configuration takes two steps: first the daemontools have to be configured, and then the djbdns configuration can take place.

Configuring the daemontools

The first decision was where to put the service directory. D. Bernstein suggests to put it into /. I did not like this idea and decided to have it in the /var hierarchy (see man hier).

# cd /var

# mkdir service

svscan is the process which supervises the contents of this directory. Every file (or link) in this directory will be considered to be a daemon which should be started and kept alive by svscan. Later on you will have to create a link for dnscache and tinydns in this directory. In the directory /usr/local/etc/rc.d I created a file named svscan.sh which starts svscan during the boot process.

#! /bin/sh 

SERVICE_DIR=/var/service 

PATH=/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin

exec svscan $SERVICE_DIR &

Don't start svscan yet, wait until you are ready with your installation. If you already have svscan running, wait to create the above mentioned links until you have done all the configuration steps.

Configuring djbdns

Creating the users dnscache and dnslog

djbdns needs three users each with their own group. I created the neccessary groups in /etc/group first:

dnscache:*:100: 

dnslog:*:101: 

tinydns:*:111:

and then called vipw and entered:

dnscache:*:100:100:djbdns:/var/dns:/sbin/nologin 

dnslog:*:101:101:djbdns:/var/dns:/sbin/nologin

tinydns:*:111:111:djbdns:/var/dns:/sbin/nologin 

Setting up dnscache

# dnscache-conf dnscache dnslog /var/dns/dnscache 192.168.0.1

# ln -s /var/dns/dnscache /var/service

# touch /var/dns/dnscache/root/ip/192.168.0

Setting up tinydns

# tinydns-conf tinydns dnslog /var/dns/tinydns 127.0.0.1

# ln -s /var/dns/tinydns /var/service

Generating the dns-data

You must tell tinydns the hosts it should resolve. I opened /etc/tinydns/root/data using my favorite editor and typed:

.hoengg.ch:127.0.0.1:a:259200 

.0.168.192.in-addr.arpa:127.0.0.1:a:259200 

@hoengg.ch::mail.hoengg.ch::86400 

=machine1.hoengg.ch:192.168.0.1:86400 

=machine2.hoengg.ch:192.168.0.2:86400 

=machine3.hoengg.ch:192.168.0.3:86400 

+mail.hoengg.ch:192.168.0.1:86400

These entries are only valid for my internal network. They do not exist in the outside world. When you are done editing you must type:

# make
to generate the database data.cdb (assuming that you are still in the directory /var/dns/tinydns/root/data).

4  Testing of your installation

Now I startied up the daemons by running svcan. Thereafter to test the installation I ran the following commands:

Commandresult
local addresses 
dnsip localhost127.0.0.1
dnsip machine1.hoengg.ch192.168.0.1
dnsname 192.168.0.1machine1.hoengg.ch
dnsmx0 mail.hoengg.ch
external addresses 
dnsip www.ora.com204.148.40.9
dnsname 204.148.40.9helio.ora.com
dnsmx ora.com10 smtp.oreilly.com 10 smtp2.oreilly.com

Pitfalls

Having done the configuration I called:

# /usr/local/etc/rc.local/svscan.sh
This should have started dnscache and tinydns but calling dnsip or nslookup as described above just timed out. Searching around I realized that only tinydns was running but I could not find a process for dnscache. Verifying all my configuration files did not reveal any obvious errors. Finally I consulted the logfile of dnscache and found an entry stating something like "could not exec sh" (unfortunately I do not have this logfile anymore, so I can't give you the exact error message). The only file where I had done something with /bin/sh was svscan.sh. And there it was: the PATH variable was lacking an entry for /bin. Interestingly it only influenced the startup of dnscache - tinydns was not affected.

The second strange behaviour which I found out later was that dnsip was rather slow. It found the internal and external addresses I tried but it took some time. Later on I noticed that nslookup only answered queries for internal addresses, external domains were not resolved. Looking around I found the cause for this strange behaviour in the log of my firewall ipfilter. I had only opened port 53 for exactly the 2 external nameservers I contacted before using djbdns.

pass out quick proto tcp/udp from any to 212.40.0.10 port = 53 keep state group 150 

pass out quick proto tcp/udp from any to 212.40.5.50 port = 53 keep state group 150

But since djbdns behaves differently -if you want to understand the background please read the documents - I had to replace these 2 entries by:

pass out quick proto tcp/udp from any to any port = 53 keep state group 150

5  Split horizon DNS

With split horizon DNS you have one machine answering internal and external DNS queries separately, i.e. internal hosts can look up hosts in the internet and external hosts can look up your DNS zone.

The catch is that

When using split horizon DNS, you should have two network interfaces in your host. On my gateway machine these are fxp0 and fxp1. fxp1 is the external interface and has the ip 195.141.97.43, fxp0 is the internal interface with the ip 192.168.0.1. My internal domain is called hoengg.ch, while my externally visible domain will be free-x.ch.

To solve this problem you have to run two copies of tinydns. One will serve the public version of my zone to the world, so obviously I use the external ip 195.141.97.43 for it.

# tinydns-conf tinydns dnslog /var/dns/tinydns-public 195.141.97.43

To offer a caching DNS resolver to my internal network, I install dnscache to use the internal ip 192.168.0.1.

# dnscache-conf tinydns dnslog /var/dns/dnscache 192.168.0.1

dnscache will only answer queries from 127.0.0.1 by default, so I have to allow it to answer queries for the network 192.168.0:

# touch /var/dns/dnscache/root/ip/192.168.0
Since this network interface is in my internal network, the outside world should not be able to send queries to it (since I have set up a firewall).

The second copy of tinydns will serve my internal network, and since both IPs are already taken, I configure it to use the loopback IP 127.0.0.1.

# tinydns-conf tinydns dnslog /var/dns/tinydns 127.0.0.1

Now, all I have to do is to tell my dnscache that it should consult the local tinydns when it is asked to resolve my internal hoengg.ch addresses. That's quite easy:

# echo 127.0.0.1 > /var/dns/dnscache/root/servers/hoengg.ch 

# echo 127.0.0.1 > /var/dns/dnscache/root/servers/0.168.192.in-addr.arpa

The second line makes sure that reverse lookups will also be forwarded to the internal tinydns.

6  Final Considerations

A more secure installation would be to split up the dns horizon across two machines. The tinydns serving the outside world would remain on my gateway machine and the tinydns/dnscache combo on another host in my internal network.


File translated from TEX by TTH, version 2.87.
On 27 Jan 2001, 17:47.