HOWTO Setup a DNS Server with BIND
From Gentoo Linux Wiki
- This page is a candidate for deletion
- Reason given: No longer accurate. Needs to be rewritten. Was created back in 2005.
- If you disagree with its deletion, please explain why on its discussion page.
- If you intend to fix it, please remove this notice, but do not remove this notice from articles that you have created yourself.
- Make sure no other pages link here and check the page's history before deleting.
| Installation • Kernel & Hardware • Networks • Portage • Software • System • X Server • Gaming • Non-x86 • Emulators • Misc |
Contents |
[edit] Introduction
BIND (Berkeley Internet Name Daemon) is an open reference implementation of the Domain Name System (DNS) protocol and provides a redistributable implementation of the major components of the Domain Name System.
- a name server (named)
- a resolver library
- troubleshooting tools like nslookup and dig
The BIND DNS Server is used on the vast majority of name serving machines on the Internet, providing a robust and stable architecture on top of which an organization's naming architecture can be built. The resolver library included in the BIND distribution provides the standard APIs for translation between domain names and Internet addresses and is intended to be linked with applications requiring name service.
[edit] My Bind Installation
My personal Bind installation has over 15000 zones and peaks at roughly 500 queries/sec across two servers. This How-To includes many organizational tips for running a large system without administration of it becoming unwieldly. I'll point those out along the way so home users with three or four domains can skip the extra steps. However most of the large system configs are geared towards easier troubleshooting and administration and I encourage all users to use the ISP tweaks I've included. After all most large systems started out as small systems.
[edit] Firewall Config
Bind listens on port 53 UDP and TCP. TCP is normally only used during zone transfers so it would appear that you could filter it if you have no slaves. However If the response to a query is greater than 1024 bytes, the server sends a partial response, and client and server will try to redo the transaction with TCP.
Responses that big do not happen often, but they happen. And people do quite often block 53/tcp without their world coming to an end. But this is where one usually inserts the story about the Great DNS Meltdown when more root servers were added. This made queries for the root list greater than 1024 and the whole DNS system started to break down from people violating the DNS spec (RFC1035) and blocking TCP.
[edit] Installing Bind
This document is based on a fresh install of 2005.0 built on July 13 on a Dell 4700. 3.0Ghz P4 w/HT, gentoo-sources 2.6.12-r4 SMP kernel, glibc built with the NPTL flag, and Bind 9.2.5-r4. Older or newer installs should not differ too greatly from this install.
Bind is in Portage and has a number of USE variables to add functionality. We're going to eliminate most of them for the purpose of this doc to keep things simple. Once I'm happy that this doc can actually lead someone through a simple setup, I may go back and add in other functionality.
[edit] Choosing your USE flags
For most users I'd recommend removing IPv6 support and any database support. This doc probably won't delve into using a database backend. Linux 2.6 users with NPTL that anticipate a high number of queries will defintely want to enable threads as Bind is highly threaded.
| File: /etc/portage/package.use |
net-dns/bind -ipv6 -ldap -mysql -bind-mysql -postgres -odbc threads |
[edit] Dependencies
On my fresh install there were no extra dependencies required over the default install using the above USE variables.
azul ~ # emerge -upv bind These are the packages that I would merge, in order: Calculating dependencies ...done! [ebuild N ] net-dns/bind-9.2.5-r4 +berkdb -bind-mysql -dlz -doc -idn -ipv6 -ldap -mysql -odbc -postgres (-selinux) +ssl +threads 4,398 kB
Bind as configured above builds in under five minutes on my test system. Your mileage may vary.
[edit] Configuring kernel
It's possible that you may need to change your kernel configuration. "Different security models" is optional, but if you have enabled it, you must also enable the default Linux capabilities:
| Linux Kernel Configuration: Kernel Configuration |
Security options --->
[X] Enable different security models
<*> Default Linux Capabilities
|
[edit] Configuring Bind
Gentoo alternates between naming files and directories "named" or "bind" which makes everything confusing. Also, most other OSs use "named" for everything rather than "bind". I've forgotten exactly what I did to straighten things out, but the commands below should allow you to assume everything is in a named/something or called named.whatever. I'll need to do a fresh install to verify sometime soon.
I prefer to break customer domains into include files by company. We have a small number of customers with 500+ domains per customer. It's a bit easier to find domains in the config this way and to track changes. I also include the logging config and any acls this way as well. You can put them all into one file if you like.
[edit] Creating Dirs and Symlinks
We're going to create some structure for the rest of config files. We're also going to symlink bind dirs to named dirs so that admins unfamilar with Gentoo can still find evertything. It's like that whole /etc/apache vs /etc/httpd problem people new to Gentoo have. This will also keep /var/bind/ from getting littered with files and make an etc-update mishaps less likely to lose all your configs.
ln -sf /etc/bind /etc/named ln -sf /var/bind /var/named mkdir /var/bind/conf mkdir /var/named/reverse mkdir /var/named/personal mkdir /var/named/customer1 mkdir /var/named/customer2 chown -R named: /var/bind mkdir /var/log/bind ln -sf /var/log/bind /var/log/named chown -R named: /var/log/bind
[edit] Fixing the Pid Files and RC Scripts
Ebuilds prior to net-dns/bind-9.2.5-r4 had an issue with the named.pid file. Following steps are recommended to fix it.
mkdir -p /var/run/named chown named: /var/run/named
Then edit /etc/init.d/named and change all instances of /var/run/named.pid to /var/run/named/named.pid. I find this layout a bit cleaner than dropping named in /var/run/ and my named.conf below assumes you've done this.
[edit] named.conf
I really suggest using this config. Yes you can set Bind up without all the logging, splitting domains into their own file, but troubleshooting is vastly easier when you have done all the groundwork. You will need to change the IP's that are allowed to do recursion to your own IP's. The same will allow transfer and notify as well.
| File: /etc/named/named.conf |
options {
directory "/var/named"; // sets root dir, use full path to escape
statistics-file "/var/named/named.stats"; // stats are your friend
dump-file "/var/named/named.dump";
zone-statistics yes;
allow-recursion { 127.0.0.1; 10.0.0.0/8; }; // allow recursive lookups
allow-transfer { 10.11.12.1; 10.11.12.2; }; // allow transfers to these IP's
notify yes; // notify the abover IP's when a zone is updated
also-notify { 10.110.0.11; 10.120.0.11; }; // notify these other servers when a zone is updated
pid-file "/var/run/named/named.pid";
transfer-format many-answers; // Generates more efficient zone transfers
listen-on { any; };
};
// Include logging config file
include "/var/named/conf/logging.conf";
// Include to ACLs
include "/var/named/conf/acls.conf";
// Include customer zones
include "/var/named/conf/customer1.conf";
include "/var/named/conf/customer2.conf";
|
NOTE: The 'listen-on' option can have as many IP addresses as you want separated by ';' or the word 'any' which will make it listen on all IP's on port 53 by default (you can specify other ports as well). The default for this option is '127.0.0.1' which will not allow a DNS lookup to your server from any computer other than the one you are running BIND on.
[edit] Logging conf
Bind can be chatty in the log files and the sheer amount of data can sometimes make it hard to find interesting logs. Fortunately Bind allows you to separate your logs and rotate them automatically in its config. The following config splits each logging category into separate files, rotates them every 5MB, and keeps three rotations of each log. You can change the length of the log file rotations by changing the versions and size options in each channel. While this config seems quite large and ugly it'll never need to be touched and having log files separated like this can make many common troubleshooting procedures easier.
| File: /var/named/conf/logging.conf |
logging {
channel default_file { file "/var/log/named/default.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel general_file { file "/var/log/named/general.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel database_file { file "/var/log/named/database.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel security_file { file "/var/log/named/security.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel config_file { file "/var/log/named/config.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel resolver_file { file "/var/log/named/resolver.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel xfer-in_file { file "/var/log/named/xfer-in.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel xfer-out_file { file "/var/log/named/xfer-out.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel notify_file { file "/var/log/named/notify.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel client_file { file "/var/log/named/client.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel unmatched_file { file "/var/log/named/unmatched.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel queries_file { file "/var/log/named/queries.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel network_file { file "/var/log/named/network.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel update_file { file "/var/log/named/update.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel dispatch_file { file "/var/log/named/dispatch.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel dnssec_file { file "/var/log/named/dnssec.log" versions 3 size 5m; severity dynamic; print-time yes; };
channel lame-servers_file { file "/var/log/named/lame-servers.log" versions 3 size 5m; severity dynamic; print-time yes; };
category default { default_file; };
category general { general_file; };
category database { database_file; };
category security { security_file; };
category config { config_file; };
category resolver { resolver_file; };
category xfer-in { xfer-in_file; };
category xfer-out { xfer-out_file; };
category notify { notify_file; };
category client { client_file; };
category unmatched { unmatched_file; };
category queries { queries_file; };
category network { network_file; };
category update { update_file; };
category dispatch { dispatch_file; };
category dnssec { dnssec_file; };
category lame-servers { lame-servers_file; };
};
|
[edit] ACL conf
The ACL section defines Access Control Lists that Bind uses to group a set of networks by name. In this example, the networks 10.*.*.*, 192.168.1.*, and 127.0.0.1 have been grouped together under the name 'our-networks'. This name can then be used to refer to the entire group when assigning permissions. (See: HOWTO_Setup_a_DNS_Server_with_BIND#Adding an ACL to a Zone)
| File: /var/named/conf/acls.conf |
acl "our-networks" {
10.0.0.0/8;
192.168.1.0/24;
127.0.0.1;
};
|
[edit] Zone File conf
There are many examples of how to add a zone file to the config. Zone statements can be placed directly in named.conf, or they can be included from an external file using the include statement. In this example we will include one of the two zone statements listed below. Zone configurations can be made in two different formats. Let's call them single-line and multi-line.
This is how a configuration in multi-line format appears:
| File: multi-line.conf |
zone "badapple.net" IN {
type master;
file "personal/badapple.net";
};
zone "chilug.org" IN {
type master;
file "personal/chilug.org";
};
|
And this is the same config with a single zone on each line:
| File: single-line.conf |
zone "badapple.net" IN { type master; file "personal/badapple.net"; };
zone "chilug.org" IN { type master; file "personal/chilug.org"; };
|
You may prefer the single line format for administrative tasks. It's easier to run sort, grep, sed, and other tools against the config file to make mass changes. Any script you write to generate a new slave or master config will be easier and simpler to write. However, it appears that the multi-line config is easier to read in documentation, so we're going to use it through out this How-To for clarity.
Each refers to zone file using the file line to include a map of domain names and their matching IP addresses. Zone files are covered in more detail below.
[edit] Adding a Slave Zone
| File: multi-line.conf |
zone "badapple.net" IN {
type slave;
file "personal/badapple.net";
masters { 10.11.12.1; };
};
zone "chilug.org" IN {
type slave;
file "personal/chilug.org";
masters { 10.11.12.1; };
};
|
[edit] Adding an ACL to a Zone
We can use the Access Control Lists to specify permissions for each zone.
allow-query { our-networks; };
Adding this line to the zone defined below tells Bind that any of the networks specified in the 'our-networks' group has permission to request the name of any IP address in the 10.113.1.* network.
| File: /var/named/conf/zone-with-acl.conf |
zone "1.113.10.in-addr.arpa" IN {
type master;
file "reverse/10.113.1.0";
allow-query { our-networks; };
};
|
[edit] Zone Files
[edit] Picking Your Zone File
There are a number of example of zone files on the Internet, each with their own little quirks. I would recommend using a layout that appeals to you. However it is in your best interest to use the same format for all your domains. This will make changes easier and you can script out wholesale changes using sed or other tools if your IP's need to change quickly or other problems. There is nothing worse than trying to edit 1000 domains by hand each with a different format.
[edit] Example of a Zone File for a Domain
| File: Sample of Zone File |
$TTL 600
; domain1.com
@ IN SOA laxlxns01.dnsserver.com. hostmaster.dnsserver.com. (
2005062601 ; serial
12h ; refresh
1h ; retry
2w ; expire
1h ; minimum
)
IN NS laxlxns01.dnsserver.com.
IN NS laxlxns02.dnsserver.com.
IN MX 10 mail.domain1.com.
@ IN A 10.10.10.34
; host records
localhost IN A 127.0.0.1
mail IN A 10.20.20.45
* IN A 10.10.10.34
|
[edit] Domain Zone File Explained
[edit] About serial numbers
Don't forget to update the serial number each time you change a zone file. The new serial number must be anything larger than the previous one. Most systems simply use the date of the change plus two digits as a serial number. For example, a zone file that has been changed for the second time on the third of January 2004 would have2004010302as a serial number. But the serial number can be any number with the maximum value of 9999999999 as long as the new serial number is larger than the previous serial number. If you don't increment your serial number, your DNS slave servers will not accept the changes and keep the old version of the zone file.
Sometimes you'll need to reset your serial number. This is easy to do if you control all your name servers. Change the master server, stop the slave servers, delete the old zone, start the slave servers. However if you do not have access to your slave servers you can set the serial number to 0 on the master server. Once the slave picks up the change you'll be able to use any number as the next serial number. This is usually done when an admin sets the serial to 3005103001 and wants to reset the serial back to 2005103001 or something similar.
[edit] About IP Addresses
When specifying a given IP range using the format 8.113.10.in-addr.arpa., the bytes are given in reverse order. In effect the IP range is 10.113.8.0/24. For a 16-bit netmask, it would be 113.10.in-addr.arpa., equivalent to 10.113.0.0/16.
[edit] Example of a Zone for Reverse DNS
| File: reverse |
$TTL 600
8.113.10.in-addr.arpa. IN SOA laxlxns01.dnsserver.com. hostmaster.dnsserver.com. (
2005062601 ; serial
12h ; refresh
1h ; retry
2w ; expire
1h ; default_ttl
)
8.113.10.in-addr.arpa. IN NS laxlxns01.dnsserver.com.
IN NS laxlxns02.dnsserver.com.
;
; DB VLAN
21 IN PTR laxlxdb01.domain1.com.
22 IN PTR laxlxdb02.domain1.com.
31 IN PTR laxlxdb01.domain2.com.
32 IN PTR laxlxdb02.domain2.com.
|
[edit] Helper Scripts
| File: dns-generateslave.sh |
#!/bin/bash
# Quick little bash script to create a slave conf based on the current master conf.
echo ""
echo "Current directories are:"
echo "customer1, customer2, customer3"
echo ""
read -p "Enter the directory you wish to create a slave config for: "
for i in `awk '{print $2}' /var/named/conf/$REPLY.conf | sed 's/\"//g'`
do echo "zone \""$i"\" IN { type slave; file \""$REPLY/$i"\"; masters { 38.118.147.251; }; };" >> $REPLY-slave.conf
done
|
| File: dns-newdomains.sh |
#!/bin/bash
# Quick little bash script to create a new master conf by listing the domains in a dir
echo "Current directories are:"
echo "customer1, customer2, customer3"
echo ""
read -p "Enter the directory you wish to create a config for: "
for i in `ls /var/named/$REPLY`
do echo "zone \""$i"\" IN { type master; file \""$REPLY/$i"\"; };" >> $REPLY.conf
done
|
[edit] Default zone
If you are a hosting provider and want to have default zone (if some domain has your NS server as primary, but you haven't added zone for this domain yet) for newly-added domains AND your server is not designed to execute recursive queries, you can use this section:
| File: Sample of Default Zone File |
zone "." IN {
type master;
file "path_to_default_zone_file";
};
|
After this, any domain, that cannot be found in your configuration will be passed over "path_to_default_zone_file" ruleset.
| File: Bind 8 Zone file example |
$ORIGIN com. //note that Bind 8, you need to specify all the domain externsion * 14440 IN SOA ns.domain.com. hostmaster.domain.com. ( 2008010101 1200 7200 1209600 3600 ) 86400 IN NS ns.domain.com. * 14400 IN A 123.123.123.123 |
| File: Bind 9 Zone file example |
$TTL 10M //note that you must have TTL for bind 9<br> @ IN SOA ns.domain.com. hostmaster.domain.com. ( 2008012701 10M 10M 10M 10M) @ 86400 IN NS ns1.domain.com. * IN A 123.123.123.123 |
