Distroname and release: Debian Squeeze
Chrooted DNS Server with BIND9
Introduction
In this setup we will go through the setup of a DNS server using BIND9, which we will chroot for security enhancements.We will in this setup create a lookup zone file for the domain test.local.
Debiantest1 has an IP of 192.168.56.102
Debiantest2 has an IP of 192.168.56.103 (Needed only for the master / slave setup described at the bottom of the guide)
DNS lookups/queries runs on port 53 UDP, and zone transfers runs on port 53 TCP. Normally port 53 UDP should be enough to forward for external access, but if you have replicating DNS servers and zone transfers you should open for 53 TCP between the replication DNS partners as well.
Chroot BIND9 Guide reference:
http://www.tldp.org/HOWTO/Chroot-BIND-HOWTO-2.html
According to the /etc/init.d/bind9 file a chrooted environment should be running in /var/lib/named and not /chroot/named as this howto is showing.
Please feel free to change it, if you find the need to do so. This setup works as well without any issues I have occoured.
Installation
The installation is very simple, like almost all debian applications.#aptitude install bind9Doing install, the installation process will create a user called bind, which should be used to run bind with. Some directories, will therefor need to have permissions for the bind as user or group after the chroot change.
Next, stop the bind9 service, since we will "move" it to chroot jail.
#/etc/init.d/bind9 stopThat was it, so far so good, now lets configure the chroot environment.
Creating the chroot environment
As mentioned ealier, make sure that the bind9 service is stopped before proceeding!Let us create the directories that the chroot BIND9 should run in.
#mkdir -p /chroot/named/etc/namedb/slave #mkdir -p /chroot/named/var/cache/bind #mkdir /chroot/named/var/run #mkdir /chroot/named/devCreate character special file, since BIND will be unable to access /dev/*, or any other files or directories outside the chroot jail actually.
This check should not be needed, but you can check the major, and minor device numbers of /dev/random and /dev/null by using the ls command.
# ls -l /dev/random crw-rw-rw- 1 root root 1, 8 Feb 16 2009 /dev/random ls -l /dev/null crw-rw-rw- 1 root root 1, 3 Feb 16 2009 /dev/nullNow create the two character special file devices, with the numbers from the output above, and set permissions on the files.
#mknod /chroot/named/dev/random c 1 8 #mknod /chroot/named/dev/null c 1 3 #chmod 666 /chroot/named/dev/*Now we will need to move the existing files in /etc/bind to the new chroot directory, since it will be unable to leave the chroot and access the files in /etc/bind
We will also create a symlink, so other applications still will have access through the original location
#mv /etc/bind /chroot/named/etc #ln -s /chroot/named/etc/bind/ /etc/bindAllow bind to access the directories and files in the chroot environment.
#chown bind:bind /chroot/named -RNow change bind, so it will run in our new created chroot environment.
This is done by changing the /etc/default/bind9 file.
You can also see that it will run with the bind user in this file.
/etc/default/bind9
# run resolvconf?
RESOLVCONF=yes
#startup options for the server
OPTIONS="-u bind -t /chroot/named"
Configuration of bind and its chroot
We are also required to change the logging options, because we are still in chroot jail. If we do not do this, our logging will fail! Create a new file called /etc/rsyslog.d/bind-chroot.conf, and add the following line to the file. Check the syslog for errors if it does not create the /chroot/named/dev/log file
/etc/rsyslog.d/bind-chroot.conf
$AddUnixListenSocket /chroot/named/dev/log
Restart bind, and rsyslog to see if it is working.
#/etc/init.d/bind9 start #/etc/init.d/rsyslog restartExecuting the rsyslog after a restart should create the /chroot/named/dev/log file.
#ls /chroot/named/dev log null randomOK, that should be it, and the configuration of bind in chroot should be done. Next we will continue with the configuration of bind itself.
Configuration of bind
Get your DNS servers from your ISP (or use OpenDNS or something similar), and add them to the named.conf.options file. Most likely it is needed to uncomment the lines.
/etc/bind/named.conf.options
forwarders {
123.456.789.123;
};
Make sure that we use our own newly installed named servers locally on the system.
#echo "search test.local" > /etc/resolv.conf #echo "nameserver 127.0.0.1" >> /etc/resolv.confThe named.conf.local is the file where we are going to add our zone files that we wants to act as a an DNS resolver for.
Note the link we are using is NOT /chroot/named/etc/bind/zonefiles/, but /etc/bind/zonefiles , since bind does not have access to the /chroot/ folder and can therefor not access the file.
Remember we created a symlink earlier that points /etc/bind to /chroot/named/etc/bind!
/etc/bind/named.conf.local
zone "test.local" {
type master;
file "/etc/bind/zonefiles/test.local"
};
Since we specified that the zonefile to use is an directory called zonefiles we need to create it,and set rights on the directory and zonefile. Remeber to set the rights for the zonefiles when new ones are created!
Create directory for the zonefiles.
#mkdir /etc/bind/zonefilesHINT: When creating new zone files, it is possible use the db.local as a template, and then edit it to your needs (Much editing needed though!).
The zonefiles can be named anything you want, but remember it must match the defined filename in the name.conf.local file.
#cp /etc/bind/db.local /etc/bind/zonefiles/test.localAfter creating the directory and the zonefile, set bind as userowner and groupowner of the zonefile directory and its file. If you create a new zonefile, remember to set its rights, and else bind cannot read it!
#chown bind:bind /etc/bind/zonefiles/ -R
Bind Zone File Explanation
- Serial
A unique serial number that must be on each zone file. A good idea is to set this to a date and revision number (YYYYMMDDNN).
Note that if the serial number is not changed after a change in the zone file, BIND will not update the slave server(s) since the serial stays the same, so remember to change it.
An exampel could be 2010062505, which is year 2010, month 6, date 25th, and revision number 05 (5th change that day). If you change the file another day, start from 01.
- Refresh
The time for the slave server(s) to poll the master(s) zone file differences.
If the serial is different it will update on the master / slave server(s).
- Retry
The time between retry attemps a slave server tries to contact the master server. If the master server cannot be contacted for a longer time that the retry value is set, the name server will stop working as resolver for that name.
- Expire
If a master server crashes, the slave server will take over, and continue to work as an resolver, but only in the time the expire is set. So it should be enough to get the master server up and running.
- Minimum Cache TTL
The time that other name servers caches the information for the current zone.
Therefor it is possible to use minutes, hours, days, weeks instead.
minutes = M
hours = h
days = d
weeks = w
Example:
30M; Refresh timeout of 30 minutes specified in minutes instead of seconds
Example of the edited zone file for our test.local domain. Note, must have a dot (.) in the end of both domain and e-mail!
/etc/bind/zonefiles/test.local
$ORIGIN test.local.
$TTL 3600
@ IN SOA ns1.test.local. hostmaster.test.local. (
2010070701; Serial
30M; Refresh
1h; Retry
2w; Expire
3h; Minimum Cache TTL
)
@ IN NS ns1; same as ns1.test.local.
@ IN NS ns2.test.local. ;same as ns2
@ IN A 192.168.56.102; test.local.
ns1 IN A 192.168.56.102
ns2 IN A 192.168.56.103
test 600 IN A 192.168.56.104; sets a TTL of 600 seconds, instead of the default 3600
Ok that should be it, now restart bind and test. Please check the syslog for errors when doing so, since it will write here if it cannot load the zonefile for whatever reason. (A typo, security issues or similar)!
Restart
#/etc/init.d/bind restartIf you just make changes to the zone file already created you can update the current zone file, or all zone files without reloading or restarting the whole bind daemon. Remember to append the serial, or else the zonefile will not be updated on the slave servers.
To reload all zonefiles.
#rndc reloadTo reload only a specific zonefile
#rndc reload test.localMultiple zone files can be specified by just using a whitespace.
#rndc reload test.local test2.localLets make a ping test to see if the lookup is working, and the server is running (hopefully it will, since it is it own server!
#ping ns1.test.local PING ns1.test.local (192.168.56.102) 56(84) bytes of data. 64 bytes from 192.168.56.102: icmp_seq=1 ttl=64 time=0.081 ms 64 bytes from 192.168.56.102: icmp_seq=2 ttl=64 time=0.165 ms
Advanced configurations
In the below section, we will continue with the setup of the bind server. The below steps are not needed at all, but could be useful. If you do not need it, there is no need to continue reading.NTP
In case that you will need to replicate zone files between servers, install the ntp package on all servers, to be completely sure that the time is the same on the servers or it could cause problems for loading zone files or replicate them to the master/slave server.If ntp is not installed and configured on both servers, it is very likely you will start to get errors like these when bind tries to transfer the zonefiles, or update them.
example error from the master:
named[1873]: client 192.168.56.103#4654: request has invalid signature: TSIG transfer: tsig verify failure (BADTIME)example error from the slave:
named[1873]: zone test.local/IN:refresh: failure trying master 192.168.56.2#53 (source 0.0.0.0#0): clocks are unsynchronizedIf you need info about the ntp, please take a look here! http://www.linuxlasse.net/linux/howtos/22
As soon as the NTP is setup and running, continue with the Master / slave configuration below.
Master / slave configuration
It is possible to create slaves to replicate the zone files to. Unfortunately it is not possible through bind to replicate the named.conf.local file, so when a new domain is added the same change is needed to be done on the slave server as well. But ALL changes to zone files will be replicated!To secure the transfer between the two servers we will use TSIG (Transaction Signatures). This can de done by using dnssec.
Enable dnssec on both master AND slave by adding "dnssec-enable=yes" in the { } section.
/etc/bind/named.conf.options
options {
dnssec-enable=yes
};
Next we will create the TSIG encryption file on the master server (ONLY).
#dnssec-keygen -a hmac-md5 -b 128 -n host Debiantest1When the key is created we will need to use the hash value in the Key: Section of the .private file. The file is in this example named: Kdebiantest1.+157+60049.private
#cat Kdebiantest1.+157+60049.private Private-key-frmat: v1.2 Algorithm: 157 (HMAC_MD5) Key: tASE3yatYigo7Phs+vAG8Q== Bits: AAA=On both master AND slave add the hash value to named.conf.
/etc/bind/named.conf
key "TRANSFER" {
algorithm hmac-md5;
secret "tASE3yatYigo7Phs+vAG8Q==";
};
On the master server only we will tell the IP of the slave server to replicate data between.
/etc/bind/named.conf
server 192.168.56.103 {
keys {
TRANSFER;
};
};
And on the slave server only the IP of the master.
/etc/bind/named.conf
server 192.168.56.102 {
keys {
TRANSFER;
};
};
Restart bind on all both master and slave server(s) after the changes.
#/etc/init.d/bind restartYou bind server, should now be up and running, and your zone files should be updated automatically after changes/updates to the zone files when running:
#rndc reloadIf not, check the logs! :)
Useful informations
That are some useful reading here on the following links:http://www.redhat.com/docs/manuals/linux/RHL-9-Manual/ref-guide/s1-bind-zone.html
http://en.wikipedia.org/wiki/Zone_file
http://www.zytrax.com/books/dns/ch7/statements.html