- Why serve DNS locally?
- Building a caching nameserver
- Running a local domain
- Putting it all together
- Adding a secondary nameserver
- And so much more
Note: This article was written at the request of Carla Schroder, and portions of it appear by permission in edited form in her very fine volume, The Linux Cookbook (O’Reilly, 2004).
There are two good reasons for putting a DNS server on your local network, even if your local server isn’t answering queries about your network coming from other hosts on the Internet:
-
It can speed up network operations like web browsing that involve frequent hostname lookups.
-
It can provide your network with a central repository of local machine information without having to copy files all around the network.
There’s a third reason: it can be educational and fun. Running a local server will teach you at least a little bit about DNS operations—learning that could possibly come in handy during job interviews—and it provides some satisfaction to those who like to build things themselves.
The easiest project is setting up BIND to do nothing but cache DNS information locally. A caching server doesn’t provide any authoritative information; it just remembers the answers to previous lookups in case the same lookup is performed again.
Consider the typical small office. It’s a good hunch that, during a typical workday, nearly every workstation will want to know the address of popular hosts like www.google.com. Rather than having every workstation ask Google’s name server for that information, they can ask the local caching nameserver, which only needs to ask for that information once every so often.
A caching nameserver handles three duties:
-
It looks up host information on the Internet and passes it back to the local network.
-
It tells your network clients the address of localhost.
-
It tells your network clients the hostname associated with the address 127.0.0.1.
On a Linux host, the information for the last two items are typically managed by /etc/hosts
, but it’s prudent to provide information about the loopback interface via DNS as well.
Using BIND, a caching nameserver will require four configuration files: the main configuration file for named, a list of the root name servers, a definition of localhost, and a definition of the loopback address, 127.0.0.1.
The main BIND configuration file is typically called named.conf
; it usually lives in /etc
or thereabouts. Red Hat packages install it as /etc/named.conf
. Gentoo, on the other hand, installs it as /etc/bind/named
.conf.
BIND configuration is a subject unto itself, and this example configuration file will not employ all of BIND’s bells and whistles, but it will get you going.
The sample below defines where named should find its configuration files, the networks for which it can provide authoritative answers, and how to find information for other networks.
//
// sample BIND configuration file
//
options {
// tell named where to find files mentioned below
directory "/var/named";
// on a multi-homed host, you might want to tell named
// to listen for queries only on certain interfaces
listen-on { 127.0.0.1; 10.11.12.0/24; };
};
// The single dot (.) is the root of all DNS namespace, so
// this zone tells named where to start looking for any
// name on the Internet
zone "." IN {
// a hint type means that we've got to look elsewhere
// for authoritative information
type hint;
file "named.root";
};
// Where the localhost hostname is defined
zone "localhost" IN {
// a master type means that this server needn't look
// anywhere else for information; the localhost buck
// stops here.
type master;
file "zone.localhost";
// don't allow dynamic DNS clients to update info
// about the localhost zone
allow-update { none; };
};
// Where the 127.0.0.0 network is defined
zone "0.0.127.in-addr.arpa" IN {
type master;
file "revp.127.0.0";
allow-update { none; };
};
The first zone definition listed in the example named.conf tells named how to find information about foreign networks. In the example, the file is called named.root, though you can give it any name you like. It lists the names and addresses of all the root name servers.
Unlike the other configuration files in this example, this file is maintained by someone other than you. The folks at InterNIC make it available via ftp: ftp://ftp.internic.net/domain/named.root. This file doesn’t change all that often, but you’ll want to check ftp.internic.net every so often just to make sure.
; This file holds the information on root name servers needed to
; initialize cache of Internet domain name servers
;
; This file is made available by InterNIC
; under anonymous FTP as
; file /domain/named.root
; on server FTP.INTERNIC.NET
; -OR- RS.INTERNIC.NET
;
; last update: Jan 29, 2004
; related version of root zone: 2004012900
;
;
; formerly NS.INTERNIC.NET
;
. 3600000 IN NS A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4
;
; formerly NS1.ISI.EDU
;
. 3600000 NS B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201
;
; formerly C.PSI.NET
;
. 3600000 NS C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12
;
; formerly TERP.UMD.EDU
;
. 3600000 NS D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET. 3600000 A 128.8.10.90
;
; formerly NS.NASA.GOV
;
. 3600000 NS E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10
;
; formerly NS.ISC.ORG
;
. 3600000 NS F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241
;
; formerly NS.NIC.DDN.MIL
;
. 3600000 NS G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4
;
; formerly AOS.ARL.ARMY.MIL
;
. 3600000 NS H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET. 3600000 A 128.63.2.53
;
; formerly NIC.NORDU.NET
;
. 3600000 NS I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17
;
; operated by VeriSign, Inc.
;
. 3600000 NS J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30
;
; operated by RIPE NCC
;
. 3600000 NS K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129
;
; operated by ICANN
;
. 3600000 NS L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET. 3600000 A 198.32.64.12
;
; operated by WIDE
;
. 3600000 NS M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33
; End of File
The third configuration file is much more cryptic than the first two. In this example, it’s called zone.localhost
, but that name is arbitrary. You could call it linux.rocks
if you were so inclined. It tells named that the address of localhost is 127.0.0.1.
;
; loopback/localhost zone file
;
$TTL 1D
$ORIGIN localhost.
@ IN SOA @ root (
1 ; Serial
8H ; Refresh
15M ; Retry
1W ; Expire
1D) ; Minimum TTL
IN NS @
IN A 127.0.0.1
The last config file tells named that the hostname associated with the IP address 127.0.0.1 is localhost.
;
; reverse pointers for localhost
;
$TTL 1D
$ORIGIN 0.0.127.in-addr.arpa.
@ IN SOA localhost. root.localhost. (
1 ; serial
8H ; refresh
15M ; retry
1W ; expire
1D ) ; minimum
IN NS localhost.
1 IN PTR localhost.
That’s about it. Put those files in place, start up named and you’ve got yourself a caching nameserver.
If your local network consists only of a few stationary Unix hosts, then the easiest way to distribute information about local hostnames is by pushing a customized /etc/hosts
to each machine.
There are a few common situations in which that simple solution might not meet your needs:
You have transitory machines like laptops or LAN-party hosts that occasionally pop up on your network, and you want to manage their network presence with DHCP.
Your local network also contains a sprinking of machines running Microsoft Windows, and the local users don’t want to be bothered by copying some obscure text file deep into the bowels of their filesystem.
Your network is getting too big to push files around manually.
People off your network need your DNS information.
Once you’ve got a caching nameserver up and running, adding information about your domain is fairly straightforward. You need to modify named.conf
to tell it about your local domain, and you’ll need two files to define the names and addresses of your hosts.
The following samples are based on a ficticious domain named schroder.net
that lives on the 10.11.12.0
subnet. There are five hosts on our network:
torvalds
(10.11.12.1) for DNS, Mail
stallman
aka depot
(10.11.12.2) for NFS/Samba file services
cert
aka www
(10.11.12.3), our web server
wall
(10.11.12.4), a workstation
walsh
(10.11.12.5, a workstation
The example named.conf
listed above needs only two additional zone blocks in order to know that it’s the authoritative source of information about the schroder.net
domain and the 10.11.12.0
subnet.
zone "schroder.net" IN {
// this is the authoritative server for
// schroder.net info
type master;
file "zone.net.schroder";
};
zone "12.11.10.in-addr.arpa" {
// this is the authoritative server for
// the 10.11.12.0 network
type master;
file "revp.10.11.12";
};
We’ve told named that it’s the authoritative data source for the schroder.net
domain, so now it’s time to define it.
This zone file will be a bit more complex than the one we created for the localhost
zone. It will have to have an entry for each host, plus it will have to define the name server and mail exchanges for the network.
;
; dns zone for for schroder.net
;
$ORIGIN schroder.net.
$TTL 1D
; any time you make a change to the domain, bump the
; "serial" setting below. the format is easy:
; YYYYMMDDI, with the I being an iterator in case you
; make more than one change during any one day
@ IN SOA torvalds hostmaster (
200405191 ; serial
8H ; refresh
4H ; retry
4W ; expire
1D ) ; minimum
; torvalds.schroder.net serves this domain as both the
; name server (NS) and mail exchange (MX)
NS torvalds
MX 10 torvalds
; define domain functions with CNAMEs
depot CNAME stallman
www CNAME cerf
; just in case someone asks for localhost.schroder.net
localhost A 127.0.0.1
; our hostnames, in alphabetical order
cerf A 10.11.12.3
stallman A 10.11.12.2
torvalds A 10.11.12.1
wall A 10.11.12.4
walsh A 10.11.12.5
The reverse pointer file ensures that each host’s IP address points back to the correct hostname. The in-addr.arpa domain was established to provide address-to-host mapping. A host’s IP address is reversed to form its hostname in this domain, so, e.g., 10.11.12.1
would become 1.12.11.10.in-addr.arpa
.
For our example domain, we’ll set up reverse pointers for the 10.11.12.0 subnet.
;
; reverse pointers for 10.11.12.0 subnet
;
$ORIGIN 12.11.10.in-addr.arpa.
$TTL 1D
@ IN SOA torvalds.schroder.net. hostmaster.schroder.net. (
200405190 ; serial
28800 ; refresh (8 hours)
14400 ; retry (4 hours)
2419200 ; expire (4 weeks)
86400 ; minimum (1 day)
)
; define the authoritative name server
NS torvalds.schroder.net.
; our hosts, in numeric order
1 PTR torvalds.schroder.net.
2 PTR stallman.schroder.net.
3 PTR cerf.schroder.net.
4 PTR wall.schroder.net.
5 PTR walsh.schroder.net.
You’ve now got the six configuration files necessary to run your nameserver:
named.conf
, the main configuration file for named,
named.root
, containing the names and addresses of the Internet’s root nameservers,
zone.localhost
, containing the address for localhost,
revp.127.0.0
, containing reverse pointers for the 127.0.0.0 network,
zone.net.schroder
, containing the addresses and hostnames for our sample domain, and
revp.10.11.12
, containing reverse pointers for our domain’s IP address space.
The named.conf
gets installed into /etc
or thereabouts, while the others all go into the the directory specified in named.conf
, which in our example is /var/named
.
Once they’re all in place, start up named and give it a whirl!
At some point, your network may grow large enough, or receive enough DNS traffic, that you’ll have to have a backup nameserver to relieve traffic on the main server and to have an alternative source for information when your primary nameserver is unavailable.
Once your primary nameserver is properly configured, adding a secondary isn’t terribly difficult. There are basically three steps:
Tweak the primary’s named.conf
so that it’ll transfer information to the secondary and notify it when changes are made to the local domain.
Tweak the zone and reverse-pointer configs for the local domain so that the secondary is listed as one of the authoritative nameservers for the domain.
Get a caching nameserver running on the host that will serve as secondary and then tweak the configs so that it’s aware of its role as secondary.
Telling named about a secondary is very easy: just add an also-notify block to zones for the local domain. The only information you really need is the IP address of the secondary. For this example, we’ll make cerf
, the web server, our secondary.
Whenever you made a change to the local domain, just bump the serial number and restart named
or tell it to reload its config files. A notice will be sent, and the secondary, upon seeing a new, larger serial number, will ask for a zone transfer to bring itself up to date.
zone "schroder.net" IN {
// this is the authoritative server for
// schroder.net info
type master;
file "zone.net.schroder";
// tell cerf when changes get made
also-notify { 10.11.12.3; }
};
zone "12.11.10.in-addr.arpa" {
// this is the authoritative server for
// the 10.11.12.0 network
type master;
file "revp.10.11.12";
also-notify { 10.11.12.3; }
};
The second task in bringing a secondary online is to add a second NS record, letting everyone know that both the primary and the secondary nameservers are available to answer questions about your domain.
A simple one-line addition to both the zone and reverse-pointer configuration files is all that’s needed to define a second nameserver.
;
; dns zone for for schroder.net
;
$ORIGIN schroder.net.
$TTL 1D
; any time you make a change to the domain, bump the
; "serial" setting below. the format is easy:
; YYYYMMDDI, with the I being an iterator in case you
; make more than one change during any one day
@ IN SOA torvalds hostmaster (
200405191 ; serial
8H ; refresh
4H ; retry
4W ; expire
1D ) ; minimum
; torvalds and cerf are our name servers, while torvalds also
; serves as the mail exchange (MX)
NS torvalds
NS cerf
MX 10 torvalds
; define domain functions with CNAMEs
depot CNAME stallman
www CNAME cerf
; just in case someone asks for localhost.schroder.net
localhost A 127.0.0.1
; our hostnames, in alphabetical order
cerf A 10.11.12.3
stallman A 10.11.12.2
torvalds A 10.11.12.1
wall A 10.11.12.4
walsh A 10.11.12.5
;
; reverse pointers for 10.11.12.0 subnet
;
$ORIGIN 12.11.10.in-addr.arpa.
$TTL 1D
@ IN SOA torvalds.schroder.net. hostmaster.schroder.net. (
200405190 ; serial
28800 ; refresh (8 hours)
14400 ; retry (4 hours)
2419200 ; expire (4 weeks)
86400 ; minimum (1 day)
)
; define the authoritative name servers
NS torvalds.schroder.net.
NS cerf.schroder.net.
; our hosts, in numeric order
1 PTR torvalds.schroder.net.
2 PTR stallman.schroder.net.
3 PTR cerf.schroder.net.
4 PTR wall.schroder.net.
5 PTR walsh.schroder.net.
Finally, we need to configure the secondary nameserver. You’ll want to follow the instructions for getting a caching nameserver up and running. Once that’s done, you’ll add zone records for the domain and reverse-pointer information.
The major difference between this configuration and the primary’s is that the type is set to “slave” and we have to tell named
where to find the primary. Otherwise, this named.conf
looks similar to the one we wrote for the primary.
//
// sample BIND configuration file
//
options {
// tell named where to find files mentioned below
directory "/var/named";
// on a multi-homed host, you might want to tell named
// to listen for queries only on certain interfaces
listen-on { 127.0.0.1; 10.11.12.0/24; }
}
// The single dot (.) is the root of all DNS namespace, so
// this zone tells named where to start looking for any
// name on the Internet
zone "." IN {
// a hint type means that we've got to look elsewhere
// for authoritative information
type hint;
file "named.root";
};
// Where the localhost hostname is defined
zone "localhost" IN {
type master;
file "zone.localhost";
// don't allow dynamic DNS clients to update info
// about the localhost zone
allow-update { none; };
};
// Where the 127.0.0.0 network is defined
zone "0.0.127.in-addr.arpa" IN {
type master;
file "revp.127.0.0";
allow-update { none; };
};
// serve as secondary for schroder.net domain
zone "schroder.net" IN {
type slave;
file "zone.net.schroder";
// where the primary nameserver lives
masters { 10.11.12.1; }
};
// serve as secondary for 10.11.12.0 net info
zone "12.11.10.in-addr.arpa" {
type slave;
file "revp.10.11.12";
masters { 10.11.12.1; }
};
BIND has features out of the reach of this short introduction. The man pages and documentation that come packaged with your distribution probably provide a good starting point.
As you might guess, the Internet is also a fine source of information. Two works stand out:
BIND 9 Administrator Reference Manual
[DNS HOWTO](DNS HOWTO)
O’Reilly & Associates has published the very fine DNS and BIND and the somewhat newer DNS & BIND Cookbook. Both of these titles are definitely worth a look-see.
Thanks for the guide. It might be beneficial to include something about setting up forwarding to speed up cache misses. I found using the caching configuration by itself was prohibitively slow, but with forwarding I'm able to host an internal domain & cache external queries almost as fast as it'd be to get them directly from 8.8.8.8 or 1.1.1.1.