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.
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:
# cd /usr/ports/net/djbdns
# make install
The dependencies djbdns needs to run, ie. daemontools, were resolved automatically by the ports collection.
The configuration takes two steps: first the daemontools have to be configured, and then the djbdns configuration can take place.
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).
# mkdir service
SERVICE_DIR=/var/service
PATH=/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin
exec svscan $SERVICE_DIR &
djbdns needs three users each with their own group. I created the neccessary groups in /etc/group first:
dnslog:*:101:
tinydns:*:111:
dnslog:*:101:101:djbdns:/var/dns:/sbin/nologin
tinydns:*:111:111:djbdns:/var/dns:/sbin/nologin
# ln -s /var/dns/dnscache /var/service
# touch /var/dns/dnscache/root/ip/192.168.0
# ln -s /var/dns/tinydns /var/service
You must tell tinydns the hosts it should resolve. I opened /etc/tinydns/root/data using my favorite editor and typed:
.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
Now I startied up the daemons by running svcan. Thereafter to test the installation I ran the following commands:
| Command | result |
| local addresses | |
| dnsip localhost | 127.0.0.1 |
| dnsip machine1.hoengg.ch | 192.168.0.1 |
| dnsname 192.168.0.1 | machine1.hoengg.ch |
| dnsmx | 0 mail.hoengg.ch |
| external addresses | |
| dnsip www.ora.com | 204.148.40.9 |
| dnsname 204.148.40.9 | helio.ora.com |
| dnsmx ora.com | 10 smtp.oreilly.com 10 smtp2.oreilly.com |
Having done the configuration I called:
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.5.50 port = 53 keep state group 150
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
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.
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.
# echo 127.0.0.1 > /var/dns/dnscache/root/servers/0.168.192.in-addr.arpa
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.