BIND
This page provides information on how to set up BIND for two scenarios:
- To provide the DNS service within a small intranet such as my home LAN.
- To provide a local DNS service on a hosted server that forwards most of the requests it gets to the hosting company's DNS servers, except for requests for a few specific DNSBL services. This is covered in this section.
Debian packages
The following Debian packages need to be installed:
bind9 dnsutils (not required but useful for debugging)
References
- http://www.bind9.net/manual/
- BIND9 Administrator Reference Manual
- http://www.howtoforge.com/traditional_dns_howto
- Traditional DNS HOWTO. Essentially shows how to configure an authorative DNS server for one domain. Also provides valuable information to the novice about the basics of DNS, and explains some DNS jargon.
- http://www.debian.org/doc/manuals/network-administrator/ch-bind.html
- Has much the same information as the above TODO, with an additional slant towards Debian.
- http://www.howtoforge.com/two_in_one_dns_bind9_views
- "Two-in-one DNS server with BIND9" HOWTO. Explains how to setup a DNS server that serves different content to internal (LAN) and external (Internet) clients, depending on the IP address of the querying client.
- http://en.wikipedia.org/wiki/Domain_Name_System
- The main Wikipedia page on DNS
- http://en.wikipedia.org/wiki/DNS_zone
- Wikipedia page with a good definition of what a DNS zone is. Especially interesting is the section with the example of zone authority in DNS queries
- http://en.wikipedia.org/wiki/Zone_file
- Wikipedia page with an example of a zone file. This is mainly interesting because it provides some discussion of TTL and the SOA record type.
- http://en.wikipedia.org/wiki/List_of_DNS_record_types
- Good overview over the different DNS record types.
- http://www.simpledns.com/help/
- The help reference to the Windows DNS server "Simple DNS" contains a lot of good and understandable information
- http://www.dnsstuff.com/reverse-dns-faq
- Responsibilities for setting up reverse DNS
Glossary
- DNS
- Domain Name System
- BIND
- Berkeley Internet Name Domain. The de-facto reference DNS implementation (includes both server and client).
- Resolver
- The client side of DNS software
- Root server
- One of the DNS servers that are at the root of the DNS tree hierarchy. A root server is represented by a period character ("."), e.g. in my own DNS configuration my IP address to name mapping ends with a period character.
- TLD
- Top Level Domain. Traditional examples are com, net, org, etc. Another set of TLDs are the country-specific ones, for instance ch or de. A third set of TLDs are "new generation" such as info or travel. See the Wikipedia article
- Infrastructure TLD
- There is exactly one infrastructure TLD, arpa
- ccTLD
- Country-code TLD. See the Wikipedia article
- gTLD
- Generic TLD. Any TLD that is not a ccTLD and not the arpa infrastructure TLD. Examples are com and info. Some gTLD such as com or org are unrestricted, i.e. they are available for registrations by any person or organization for any use. Other gTLD such as travel or jobs are restricted, i.e. registrations within them require proof of eligibility within the guidelines set for each.
- Authorative server
- One of the DNS servers that are authorative for a specific domain (e.g. herzbube.ch). When a domain is registered, at least two authorative DNS servers must be specified to the registrar. The registrar will then delegate responsibility for the domain to the authorative DNS servers. Often the authorative servers are provided by the ISP that hosts the domain, however up until now I have used dyndns.org for that purpose. Note that both primary and secondary DNS servers of a zone are authorative.
- Forward resolution
- Forward resolution is host name to IP address resolution.
- Reverse resolution
- Reverse resolution is IP address to host name resolution. Reverse resolution must be configured by whomever controls the IP address - this usually is an Internet provider. The reverse DNS entry is a PTR record that points to a concrete host (i.e. not the "abstract" domain). Wikipedia says the PTR record should point to a "canonical name" (i.e. a CNAME). Stackoverflow has the advice, in relation to MTA configuration, to let the PTR record point to the name that is provided with HELO/EHLO, or more generally that the PTR must point to a name that resolves to the same IP address for which the reverse lookup was made.
- named.conf
- The main configuration file for BIND. It references "zone" files.
- DNS zone
- A portion of the global DNS namespace for which administrative responsibility has been delegated. Examples are the root zone, the local zone, or (at the lowest level) any domain such as my personal domain herzbube.ch. See the Wikipedia article. Another explanation attempt: A zone is a domain less any sub-domains delegated to other DNS servers.
- Root zone
- The zone at the root of the DNS tree hierarchy. This zone is unnamed and represented by a period character ("."). The root zone contains all TLDs. Delegation is handed down to governments and various organizations that administer these TLDs.
- Zone file
- A text file that describes a portion of the domain name system (DNS) called a DNS zone. See the Wikipedia article
- Hints file
- One of the zone files. This file contains the names and addresses of the root servers on the Internet.
- Local host file
- One of the zone files. Name servers are the masters of their own loopback domain (127.0.0.1). The point of creating local zone files for each aspect of your of localhost is to reduce traffic and allow the same software to work on your system as it does on the network.
- Primary zone file
- One of the zone files. This file, also called the domain database, defines most of the information needed to resolve queries about the domain you administer. It maps names to IP addresses and provides information about the services offered by your Internet computer including your web and ftp server, email, telnet, name servers, etc. The zone file uses several record types, for instance SOA, MX or CNAME.
- Reverse zone file
- One of the zone files. This file maps IP addresses to host names. It's a mirror image of the primary zone file.
- Resource Record (RR)
- The basic data element in the DNS. Each record has a type (A, MX, etc.), an expiration time limit, a class, and some type-specific data. This Wikipedia article lists all the possible DNS record types.
- SOA
- Record type "start of authority"; a SOA record must not refer to a CNAME. The SOA record identifies the primary DNS server of a zone.
- NS
- Record type "name server"; an NS record must not refer to a CNAME, and it must not use an IP address. NS records identify the authorative DNS servers (primary and secondary) of a zone. It can be said that an NS record delegates a DNS zone to use the given authoritative name server.
- A
- Record type "address"; maps a host name to an IP address
- PTR
- Record type "pointer"; maps an IP address to a host name
- MX
- Record type "mail exchanger"; identifies the mail servers in the domain; an MX record must not refer to a CNAME, and it must not use an IP address.
- CNAME
- Record type "canonical name"; defines an alias for a host name; a CNAME must always refer to an A record, never to another CNAME (to prevent circular references).
- Host name
- Refers to a domain name that has one or more associated IP addresses. For instance, herzbube.ch is a host name, whereas ch is not.
- Primary DNS server
- The server where the master copies of a domain's zone files are located
- Secondary DNS server
- A server that has slave copies of a domain's zone files, obtained via a zone transfer
- Zone transfer
- The process of transferring zone files from one system to another, usually from a primary to a secondary DNS server. A DNS server may specify which servers are authorized to do zone transfers.
- Non-recursive query
- When a DNS server answers authoratively for one of its own domains, without consulting any other DNS server
- Recursive query
- When a DNS server answers a query by querying other DNS servers
- Stub resolver
- A simple-minded resolver that relies on a recursive DNS server to perform the work of finding information for them. In contrast, a normal resolver would itself perform each query, iterating through several DNS servers (starting with the root servers) to find the needed information
- dig
- Domain Information Groper. Command line utility for querying DNS servers.
- FQDN
- Fully qualified domain name. Sometimes referred to as an "absolute domain name". A domain name that specifies its exact location in the tree hierarchy of the DNS. It specifies all domain levels, including the top-level domain, relative to the root domain. A fully qualified domain name is distinguished by its unambiguity; it can only be interpreted one way. In the DNS, and most notably, in DNS zone files, a FQDN is specified with a trailing period character (".").
- TTL
- Time to live. A value associated with DNS records that tells clients how long they may cache the record before the authorative DNS server has to be queried again.
- Negative Cache TTL
- This special TTL, which is defined in the SOA record of a zone, is used for negative responses to queries, i.e. if a query is made for something that does not have a DNS record. The negative response may then be cached for the duration specified by the Negative Cache TTL.
- DDNS
- Dynamic DNS. If a DNS server allows external clients (e.g. a DHCP server) to dynamically modify its zones.
Questions & Answers
- How is DNS organized?
- DNS is a distributed database with multiple levels. Level 1 consists of the root servers, level 2 covers the TLDs, and level 3 is usually everything else (although there may be more levels if there are more DNS zones at level 3). A resolver that needs to find the IP address of google.com first queries one of the root servers, which refers the resolver to one of the servers for the TLD com, which finally refers the resolver to the authorative server 216.239.32.10 (ns1.google.com). The last server in the chain can then tell the resolver the actual IP address of google.com.
- How does caching work in the DNS environment?
- An authorative DNS server (may be primary or secondary) of a zone assigns a TTL to each of its DNS records. The TTL specifies the maximum amount of time other DNS servers and applications should cache the record. They are, of course, free to query the primary DNS server again before TTL has been reached. Setting a DNS record's TTL value to zero, means that applications and DNS servers should not cache the record. When a DNS record is stored in the cache of a DNS server, the record's TTL is continuously reduced as time goes by, and when the TTL finally reaches zero the record is removed from the cache. When a DNS server passes DNS records from the cache along to applications and other DNS servers, it supplies the current TTL value - not the original. This way the original TTL is guaranteed no matter how many DNS servers the record passes through. Most DNS servers will not cache a DNS record for more than one week, regardless of the TTL. Special note on Negative Cache TTL: The last field in a zone's SOA record is the commonly called "Negative Cache TTL". If a query is made for something that does not have a DNS record, the client will receive a no domain or NXDOMAIN response with a Negative Cache TTL. Clients may thus cache negative responses in the same way as they would cache the result of a successful query.
- How does recursive querying work?
- (Answer copied verbatim from this page) Client applications (such as Internet browsers) typically requests that the DNS server performs recursion for them by setting an RD (Recursion Desired) flag in the request packet. This is a recursive request. Client applications do this both because they do not posses the ability to resolve domain names themselves, and also to take advantage of centralized caching on the DNS server. However, when a DNS server sends requests to other DNS servers as part of the recursion process, these requests are typically non-recursive (the RD flag is not set). The DNS server indicates back to the client if it is willing to perform recursion by setting or not setting an RA (Recursion Available) flag in the DNS response packet. When a DNS server receives a recursive request from a client that it is willing to perform recursion for, it will go through the process of resolving the requested domain name by first asking the root servers, which respond with a referral to the top level DNS servers, then asking one of those servers, which respond with a referral to the next level DNS servers, etc. When a DNS server receives a non-recursive request or a request from a client that it is not willing to perform recursion for, it typically responds immediately with whatever local data it has available at the time without doing any additional processing. [...] A recursive DNS request requires much more processing by the server compared to a non-recursive request. So it is important to only offer recursion to trusted clients.
- How can I create a zone for a sub-domain?
- A DNS server that is authorative for all records under the "xyz.com" domain can delegate responsibility for the sub-domain "abc.xyz.com" by defining an NS record for that sub-domain. The DNS server referenced by the NS record thus becomes authorative for the sub-domain, which effectively results in a new zone.
Goals of my local DNS setup
Summary
The goals, in descending order of importance, are:
- Hosts in the local network should be known under <hostname>.herzbube.ch, or simply <hostname>. In both cases, the name should resolve to an address in one of the local network (wired LAN = 192.168.1.0, WiFi = 192.168.2.0).
- IP addresses allocated by the DHCP server should be automatically added to the DNS database
- Hosts and their IP addresses should be administered in the LDAP directory
- Be responsible for my own DNS hosting on the Internet (i.e. get rid of DynDNS.org).
Solution for goal 1
Goal #1, as it is stated, requires that the DNS zone for herzbube.ch contains both public IP addresses (212.101.18.224) and private IP addresses (192.168.1.x or 192.168.2.x). In the current situation, with the DNS zone being hosted by DynDNS.org, I believe this is not a good idea - private IP addresses should not appear in a public, Internet context. If I were able to host the DNS zone myself (and optionally make DynDNS.org my secondary DNS server), I might be able to do a trick with the "views" feature of BIND9 (see the "Two-in-one DNS server with BIND9" HOWTO). Unfortunately, this is not possible - the domain registrar for the TLD ch does not accept my puny DNS server (see "Goal #4" implementation section below).
The solution I have come up with is the definition of three new DNS zones:
- The local networks are placed under three new sub-domains:
dmz.herzbube.ch
,lan.herzbube.ch
andwifi.herzbube.ch
- Originally I had only a single sub-domain
localnet.herzbube.ch
, but after I added a WLAN to my intranet this solution became untenable - The problem was that some hosts were capable of connecting both via wired LAN and WiFi, which means that those hosts would appear under two different IP addresses
- Forward DNS resolution would have been possible by defining two A records with different hostnames, but reverse DNS resolution would always have resulted in one or the other IP address
- The only proper solution to this problem is to split the single sub-domain into three distinct sub-domains
- Originally I had only a single sub-domain
- The following DNS records are added to the zone for
herzbube.ch
(which is currently hosted by DynDNS.org):- One
NS
record per sub-domain. This effectively creates new DNS zones for the sub-domains, delegating control over the zones to the zones' primary DNS servers:
- One
dmz.herzbube.ch. NS ns1.dmz.herzbube.ch. lan.herzbube.ch. NS ns1.lan.herzbube.ch. wifi.herzbube.ch. NS ns1.wifi.herzbube.ch.
- One A record per sub-domain that defines where the new primary DNS server for that sub-domain's zone is located. These
A
records are so-called glue records.
- One A record per sub-domain that defines where the new primary DNS server for that sub-domain's zone is located. These
ns1.dmz.herzbube.ch. A 192.168.0.2 ns1.lan.herzbube.ch. A 192.168.1.11 ns1.wifi.herzbube.ch. A 192.168.2.6
- Because control over the new zones has been delegated to my own DNS servers (at 192.168.0.2, 192.168.1.11 and 192.168.2.6), I have now complete freedom in how to setup the new zones
- Hostnames (and anything else) will be located under the new sub-domains (e.g.
alcarondas.dmz.herzbube.ch
,tharbad.lan.herzbube.ch
,nargothrond.wifi.herzbube.ch
)
This solution has two drawbacks:
- It still leaks one private IP address per private zone (192.168.0.2, 192.168.1.11 and 192.168.2.6) into the public DNS space. This is certainly not ideal, however leaking only a single IP address per private zone is definitely superior to the primitive solution of simply defining all the private addresses directly within the
herzbube.ch
zone (i.e. definingA
records for the various hostnames). The "private zone" solution is also better in that it somewhat hides the structure of my private network from public eyes. - Sub-domains don't look pretty, and more typing is necessary for a FQDN. I guess at the moment I have to accept that this is the price to pay for having a relatively cheap Internet connection. If I were willing to pay more, I am sure I could get a better solution directly from my ISP, but apart from being more expensive it would also become even harder to switch to another ISP (if I ever wanted to).
Solution for goal 2
An overview over the steps required:
- The DNS server needs to be configured to accept updates for those DNS zones that need dynamic updates
- The DHCP server needs to be configured to send updates to the DNS server
- A shared secret needs to be established to secure the communication channel between the two servers. This is less important in my circumstances where both servers are located on the same machine, but it should still be implemented, both as a precaution and for learning purposes
An important note on the side: Once dynamic updates start to occur, the DNS server will periodically, or when it is shut down, flush its cached information to disk. The zone files are overwritten by this, so it doesn't make sense to put comments into them!
Solution for goal 3
Not yet solved.
Solution for goal 4
This goal seems to be impossible to achieve. The reason for this is that the domain name registrar for the TLD ch (Switch) does not accept arbitrary DNS servers for delegation. The DNS server must be specially registered with the registrar, and at the moment it appears that only ISPs can do such a registration. Since I cannot deploy my own primary DNS server for herzbube.ch, I am stuck with the public DNS server of DynDNS.org.
TODO: Investigate the exact requirements that Switch has for a primary DNS server. See the issue tracker for a status of this investigation.
Static implementation
The zone files
Overview
This section first discusses some general aspects of zone files and their content. It then lists the actual, current content of my zone files. Only the static records are listed, dynamically added content is treated in a separate chapter "Dynamic implementation" further down.
Default TTL
A zone file should start with the definition of a default TTL:
$TTL 1d
This TTL will be applied to all DNS records that do not specify their own explicit TTL.
SOA record
SOA means "start of authority". This record has authorative information about the DNS zone in general. An example with (probably/hopefully) useful values:
@ IN SOA ns1.herzbube.ch. zone-admin.herzbube.ch. ( 2009091601 ; Serial 1d ; Refresh 1h ; Retry 7d ; Expire 1h) ; Negative Cache TTL
Discussion:
- @
- A shorthand reference to the "current origin", which means the zone used in /etc/bind/named.conf.local to refer to this zone file. Thus, if the zone file was referenced inside the clause zone "herzbube.ch" { ... }, the current origin would be herzbube.ch.
- IN
- Specifies that the class of this record is "Internet". The other classes exist for non Internet protocols and functions, so they are not relevant for us and we will always use "IN".
- SOA
- Specifies that the type of this record is "Start of Authority".
- ns1.herzbube.ch.
- The FQDN of the primary DNS server of the zone, i.e. the DNS server who has authority for the zone. The zone should contain an NS record as well as an A record for this DNS server. Note the trailing period character (".").
- zone-admin.herzbube.ch.
- The email address of the domain administrator. In this example the address is zone-admin@herzbube.ch. Note the trailing period character (".").
- 2009091601
- Serial number. This is just a common name, the field basically contains a numeric value that designates the version of the zone file. A larger value means a newer version. When the zone is edited, the serial number must be updated so that secondary DNS servers will notice that something has changed and can update their records (= zone transfer). The convention is that the serial number format is YYYYMMDD with an incremented double digit number tagged to the end. Thus, there can be up to 100 changes during a single day.
- 1d
- This field tells a secondary DNS server how often it should check its primary DNS server whether an update (= zone transfer) is necessary. The unit is seconds.
- 1h
- This field tells a secondary DNS server how much time should elapse between retries to connect to its primary DNS server in the event of a connection failure. The unit is seconds.
- 7d
- Total amount of time a secondary DNS server should retry to contact its primary DNS server before expiring the data it contains. Or, in other words, the length of time that the slave server should continue to respond to queries even if it cannot update the zone file. Future references will be directed towards the root servers. Note that an expiration period exists under the theory that out of date data is worse than no data at all. The unit is seconds.
- 1h
- Negative Cache TTL for this zone. If a query is made for something that has no DNS record, the negative response to that query may be cached by clients for the duration specified by the Negative Cache TTL. The unit is seconds.
Note: Even though the internal unit for all time values in a SOA record is seconds, BIND9 allows to specify the values in more convenient notations such as "1h" (1 hour, 3600 seconds), "1d" (1 day, 86'400 seconds) or "1w" (1 week, 604'800 seconds).
Zone file location
To distinguish my zone files from the default zone files provided by the Debian package, I place them in a special directory:
/etc/bind/zones
Underneath that directory each zone has its own sub-directory. For instance, the files for zone wifi.herzbube.ch go into
/etc/bind/zones/wifi.herzbube.ch
Forward zone for dmz.herzbube.ch
The forward zone file for dmz.herzbube.ch is located in /etc/bind/zones/dmz.herzbube.ch/db.dmz.herzbube.ch. Its content:
; Default TTL $TTL 1d ; Start of authority (must not refer to a CNAME) @ IN SOA ns1.dmz.herzbube.ch. zone-admin.herzbube.ch. ( 2009111501 ; Serial 1d ; Refresh 1h ; Retry 7d ; Expire 1h) ; Negative Cache TTL ; Name servers (must not refer to a CNAME) @ IN NS ns1 ; The nameserver A record ns1 IN A 192.168.0.2 ; A records alcarondas IN A 192.168.0.1 pelargir IN A 192.168.0.2
Notes:
- Currently none
Reverse zone for dmz.herzbube.ch
The reverse zone file for dmz.herzbube.ch is located in /etc/bind/zones/dmz.herzbube.ch/db.0.168.192.in-addr.arpa. Its content:
; Default TTL $TTL 1d ; Start of authority (must not refer to a CNAME) @ IN SOA ns1.dmz.herzbube.ch. zone-admin.herzbube.ch. ( 2009111501 ; Serial 1d ; Refresh 1h ; Retry 7d ; Expire 1h) ; Negative Cache TTL ; Name servers (must not refer to a CNAME) @ NS ns1.dmz.herzbube.ch. ; Addresses 1 PTR alcarondas.dmz.herzbube.ch. 2 PTR pelargir.dmz.herzbube.ch.
Notes:
- The SOA record is exactly the same as the one in the forward zone file
- It is necessary to always specify the FQDN because the origin in this zone will be set to "0.168.192.in-addr.arpa". I didn't attempt to set $ORIGIN, as was suggested in one of the HOWTOs I have read, because I don't want to invite trouble.
- It is vital that the zone file contain an NS record, otherwise BIND will refuse to load the file (named-checkconf -z prints a "bad zone" message, but if the daemon is restarted without this check, it will silently ignore the error!)
Note that does not refer to the zone file above: If the addresses in a reverse zone require more than a single octet, remember to write the addresses in reverse notation. For instance, if the zone origin is "168.192.in-addr.arpa" and you want to refer to the address "192.168.0.1", the address must be written as "1.0".
Forward zone for lan.herzbube.ch
The forward zone file for lan.herzbube.ch is located in /etc/bind/zones/lan.herzbube.ch/db.lan.herzbube.ch. Its content:
; Default TTL $TTL 1d ; Start of authority (must not refer to a CNAME) @ IN SOA ns1.lan.herzbube.ch. zone-admin.herzbube.ch. ( 2009111501 ; Serial 1d ; Refresh 1h ; Retry 7d ; Expire 1h) ; Negative Cache TTL ; Name servers (must not refer to a CNAME) @ IN NS ns1 ; The nameserver for the internal network (reverse lookup of the IP ; address currently results in pelargir.lan.herzbube.ch instead ; of ns1.lan.herzbube.ch) ns1 IN A 192.168.1.11 ; A records pelargir IN A 192.168.1.11 laserjet1300n IN A 192.168.1.126 ; Aliases gw CNAME pelargir test CNAME pelargir davical CNAME pelargir
Notes:
- See the section about the forward zone for
dmz.herzbube.ch
Reverse zone for lan.herzbube.ch
The reverse zone file for lan.herzbube.ch is located in /etc/bind/zones/lan.herzbube.ch/db.1.168.192.in-addr.arpa. Its content:
; Default TTL $TTL 1d ; Start of authority (must not refer to a CNAME) @ IN SOA ns1.lan.herzbube.ch. zone-admin.herzbube.ch. ( 2009111501 ; Serial 1d ; Refresh 1h ; Retry 7d ; Expire 1h) ; Negative Cache TTL ; Name servers (must not refer to a CNAME) @ NS ns1.lan.herzbube.ch. ; Addresses 11 PTR pelargir.lan.herzbube.ch. 126 PTR laserjet1300n.lan.herzbube.ch.
Notes:
- See the section about the reverse zone for
dmz.herzbube.ch
Forward zone for wifi.herzbube.ch
The forward zone file for wifi.herzbube.ch is located in /etc/bind/zones/wifi.herzbube.ch/db.wifi.herzbube.ch. Its content:
; Default TTL $TTL 1d ; Start of authority (must not refer to a CNAME) @ IN SOA ns1.wifi.herzbube.ch. zone-admin.herzbube.ch. ( 2009111501 ; Serial 1d ; Refresh 1h ; Retry 7d ; Expire 1h) ; Negative Cache TTL ; Name servers (must not refer to a CNAME) @ IN NS ns1 ; The nameserver A record ns1 IN A 192.168.2.6 ; A records pelargir IN A 192.168.2.6 landroval IN A 192.168.2.2 ; Aliases gw CNAME pelargir
Notes:
- See the section about the forward zone for
dmz.herzbube.ch
Reverse zone for wifi.herzbube.ch
The reverse zone file for wifi.herzbube.ch is located in /etc/bind/zones/wifi.herzbube.ch/db.2.168.192.in-addr.arpa. Its content:
; Default TTL $TTL 1d ; Start of authority (must not refer to a CNAME) @ IN SOA ns1.wifi.herzbube.ch. zone-admin.herzbube.ch. ( 2009111501 ; Serial 1d ; Refresh 1h ; Retry 7d ; Expire 1h) ; Negative Cache TTL ; Name servers (must not refer to a CNAME) @ NS ns1.wifi.herzbube.ch. ; Addresses 6 PTR pelargir.wifi.herzbube.ch. 2 PTR landroval.wifi.herzbube.ch.
Notes:
- See the section about the reverse zone for
dmz.herzbube.ch
named.conf
Overview
Configuration of the BIND DNS server is located in
/etc/bind
If the BIND configuration or one of the zones is changed, the BIND daemon needs to be restarted to make these changes effective. Before you do this, don't forget to check whether the changes make sense. See "checking the configuration" further down.
/etc/init.d/bind9 restart
Debian specifics
/usr/share/doc/bind9/README.Debian.gz provides basic information about the structure of BIND configuration files in Debian. Essentially the idea is this:
- All conf files for the primary server are located in /etc/bind, possibly in subdirectories if the configuration is very complex
- Primary server conf files are referenced in named.conf using full path names
- Secondary server configuration in named.conf should refer to its zone files with simple filenames, so that the data files will be stored relative to BIND's working directory (defaults to /var/cache/bind)
- Zones subject to automatic updates via DHCP should be stored in /var/lib/bind, and specified with full pathnames
/etc/bind/named.conf uses an include syntax to refer to various sub-configuration files:
- /etc/bind/named.conf.options
- The "options" part of the BIND configuration
- /etc/bind/named.conf.default-zones
- References various concrete zone files that define default zones (e.g. the root zone)
- /etc/bind/named.conf.local
- Local configuration, empty by default.
Various pre-configured default zone files referenced in /etc/bind/named.conf.default-zones are:
- /etc/bind/db.root
- Root zone, i.e. lists root servers (hints file)
- /etc/bind/db.local
- Local zone file, i.e. configuration for the local loopback interface
- /etc/bind/db.127
- Reverse zone file for the local zone (db.local)
- /etc/bind/db.0
- Reverse zone file for the broadcast zone of the local loopback interface
- /etc/bind/db.255
- ditto
Conventions:
- Zone files are prefixed with db.
Checking the configuration
Before activating a configuration, it should be syntax-checked using
named-checkconf -z
Notes:
- The utility by default checks /etc/bind/named.conf
- The -z option is required so that the utility actually tries to load the zone files. If this is not specified, zone files that do not exist (e.g. because a wrong file name was specified accidentally) are not detected
To check a zone (the lan.herzbube.ch zone in this example), use this utility:
named-checkzone lan.herzbube.ch /etc/bind/zones/lan.herzbube.ch/db.lan.herzbube.ch
The actual configuration
To activate a zone (lan.herzbube.ch
in this example), the following lines need to be added to /etc/bind/named.conf.local:
zone "lan.herzbube.ch" { type master; file "/etc/bind/zones/lan.herzbube.ch/db.lan.herzbube.ch"; }; zone "1.168.192.in-addr.arpa" { type master; file "/etc/bind/zones/lan.herzbube.ch/db.1.168.192.in-addr.arpa"; };
Notes:
- I don't restrict zone transfers because there is no one that could attempt it (the ADSL router blocks the DNS port). For the record: Restricting zone transfers would require the option allow-transfer to specify the IP addresses that are allowed to do a zone transfer.
- I don't run my DNS server chroot'ed because it's too much trouble, and it's not really a security risk (again, the ADSL router blocks the DNS port)
In addition, to make sure that the DNS server is well behaved, I activate the default configuration for RFC 1918 zones, which is conveniently provided by the Debian package:
- To activate the RFC 1918 zones, the comment characters ("//") need to be removed from the following line in /etc/bind/named.conf.local:
include "/etc/bind/zones.rfc1918";
- However, in order to prevent a conflict with local zones that actually use addresses in the 192.168.0.0 range, the following line needs to be commented out in /etc/bind/zones.rfc1918:
// PN 17.09.2009 // Disabled because I use addresses from this zone in my local sub-domains // // zone "168.192.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
Additional configuration
Situation before deploying DNS
The ADSL router acts as the DHCP server for pelargir:
- The router hands out the domain moser-naef.ch (configured in menu 1)
- The router hands out the primary and secondary DNS servers of the ISP (configured in menu 3.2)
- pelargir sets its /etc/resolv.conf to this information
pelargir acts as the DHCP server for hosts in the local network:
- pelargir hands out the domain herzbube.ch (configured in /etc/dhcp3/dhcpd.conf)
- pelargir hands out the primary and secondary DNS servers of the ISP (configured in /etc/dhcp3/dhcpd.conf)
- Hosts in the local network set their /etc/resolv.conf to this information
Result:
- Everybody queries the DNS servers of the ISP
Modifications
Changes to the ADSL router configuration:
- The router now hands out domain dmz.herzbube.ch
- The router now hands out 192.168.0.2 as the primary DNS server, and the ISP's primary DNS server as the secondary DNS server
- To activate the change on pelargir, renew the DHCP lease (e.g.
ifdown
followed byifup
)
Changes to the DHCP server on pelargir (in /etc/dhcp3/dhcpd.conf):
- Change the domain name handed out so that it depends on the subnet where the client requests its IP address (option domain-name)
- Change the DNS servers handed out so that the front most entry refers to the DNS server
pelargir
. The IP address depends on the subnet where the client requests its IP address (option domain-name-servers) - To activate the change on clients, renew their DHCP leases and (if necessary) clear their DNS caches.
Result:
- Everybody (including pelargir) first queries the DNS server on
pelargir
before they query the ISP's DNS server - Hostnames are recognized with or without FQDN (e.g. tharbad is recognized as well as tharbad.lan.herzbube.ch)
The content of /etc/resolv.conf on a client in the lan.herzbube.ch
sub-domain should look like this:
domain lan.herzbube.ch search lan.herzbube.ch nameserver 192.168.1.11 nameserver 212.101.0.10 nameserver 212.101.4.253
Dynamic implementation
Authentication secret file
A client that wants to dynamically update DNS records must authenticate itself to the DNS server. The authentication mechanism requires a shared secred between DDNS client and DNS server. The file with the shared authentication secret looks like this:
key dhcp-updater { algorithm hmac-md5; secret "pRP5FapFoJ95JEL06sv4PQ=="; };
From the "BIND 9 Administrator Reference Manual" (http://www.bind9.net/manuals):
The shared secret is simply a random sequence of bits, encoded in base-64. Most ASCII strings are valid base-64 strings (assuming the length is a multiple of 4 and only valid characters are used), so the shared secret can be manually generated.
The secret is generated like this and can then be added to the above file via copy&paste. Note that currently only the HMAC-MD5 algorithm is supported.
# Generate the secret. This writes two files: # - one with the extension .key: Contains the public key # - one with the extension .private: Contains the private key # Public/private keys make sense only for asymmetric algorithms, but dnssec-keygen # creates two files even if a symmetric algorithm such as HMAC-MD5 is used. In this # case, both files simply contain the same secret. dnssec-keygen -a HMAC-MD5 -b 128 -n USER dhcp-updater # Get the secret. It is the last part of a line that looks something like this: # dhcp-updater. IN KEY 0 3 157 xhjomY+2e33haceeT5yKAw== cat Kdhcp-updater*.key # Cleanup, remove the generated files rm Kdhcp-updater*.key Kdhcp-updater*.private
Because the file contains a secret key, it must be protected accordingly against unauthorized reads:
cd /etc/bind touch dhcp-updater.key chown root:bind dhcp-updater.key chmod 640 dhcp-updater.key
Define which zones are updateable
Example for the zone that represents the lan.herzbube.ch
sub-domain:
zone "lan.herzbube.ch" { [...] allow-update { key "dhcp-updater"; }; }; zone "1.168.192.in-addr.arpa" { [...] allow-update { key "dhcp-updater"; }; };
Discussion:
allow-update
grants given clients the permission to update any record of any name in the zoneupdate-policy
, not used here, allows more fine-grained control over what updates are allowed- Only clients presenting the given key are allowed to update the zone
Permissions for zone files and container directories
When the BIND9 server receives an update, it writes the request to a journal file in the directory where the zone file is located. This requires that the directory is setup with appropriate permissions. The following example is for a zone that represents the lan.herzbube.ch
sub-domain:
cd /etc/bind/zones chmod g+w lan.herzbube.ch ls -ld lan.herzbube.ch drwxrwsr-x 2 root bind 4096 2009-11-15 01:39 lan.herzbube.ch
Periodically, or when it is shut down, the BIND9 server flushes its cached information to disk. The zone files are overwritten, so it doesn't make sense to put comments into them!
Note: This chapter is relevant only because my setup violates the Debian policy of writing dynamically updateable DNS zones to /var/lib/bind
.
Logging
It makes sense to write information about dynamic updates to specific log files. The following directives, added to /etc/bind/named.conf.local
, achieve this:
logging { channel update_debug { file "/var/log/named/update-debug.log"; severity debug 3; print-category yes; print-severity yes; print-time yes; }; channel security_info { file "/var/log/named/named-auth.info"; severity info; print-category yes; print-severity yes; print-time yes; }; category update { update_debug; }; category security { security_info; }; # If a category is not defined, the logging options from the "default" category # are used (which basically logs to syslog). If a message could not be matched # to any category, it is logged with the options of the "unmatched" category # (which sends everything to /dev/null). };
The directory needs to be created before the BIND server is restarted:
cd /var/log mkdir named chown bind named
Finally, the log files need to be added to /etc/logrotate.d/pelargir
:
/var/log/named/*.log { size 1000k missingok rotate 10 compress nocreate }
Resolver
For a discussion on how the resolver works, see network configuration page on this wiki.
In addition, the NSS page (Name Service Switch) may also be interesting/important.
Remote administration
Defining the control channel
The control channel definition determines which clients are allowed to remotely control the DNS server.
controls { inet 127.0.0.1 allow { localhost; } keys { "rndc-key"; }; };
Discussion:
- 127.0.0.1 defines the interface where to listen on
- The default port to listen on is 953
- Since the DHCP server lives on the same machine, the only source for updates can be the localhost; this is defined by the
allow
clause - The
keys
statement defines which secret key(s) must be presented by the connecting client. If this (or the entirecontrols
section) is missing, BIND tries to load the key from/etc/bind/rndc.key
- To disable the command channel, use an empty controls statement:
controls { };
rndc
The command line utility to remotely administrate the DNS server is
rndc
More information: TODO...
Local DNS service forwarding all requests except DNSBL service requests
The goal for this setup is to have a local DNS server that forwards all requests to the DNS servers of green.ch (the hosting company), except for requests to a few DNSBL services. These services need to be contacted directly because they block requests coming via the green.ch DNS servers, because too many other machines send requests via green.ch.
Add this to named.conf.options
to set up a forwarding DNS server:
// ------------------------------------------------------------ // Local configuration // ------------------------------------------------------------ // Set up the hosts to which the server forwards queries. // These are the green.ch nameservers that were originally listed in resolv.conf. // https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-forward forwarders { 146.228.101.20; 146.228.101.28; }; // only = The server only queries the forwarders and does not attempt to perform lookups on its own. // Important: A list with exceptions is defined in named.conf.local. // https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-forward forward only; // Specifies which hosts (an IP address list) are allowed to send queries to this resolver. // https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-allow-query // TODO: Do we need to add pelargir as well? allow-query { localhost; }; // Allow recursion and caching. This is already the default. // https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-recursion recursion yes; // Hosts that are allowed to perform recursive queries. // https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-allow-recursion allow-recursion { localhost; }; // Hosts that are allowed to access the server's cache. // This usually needs not be set, it is defined implicitly by the values of recursion and allow-recursion. // https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-allow-query-cache allow-query-cache { localhost; }; // Hosts that are allowed to transfer zones from this server. // We don't have zone files, so no zone transfer is needed. // https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-allow-transfer allow-transfer { none; }; // Hosts that are allowed to send NOTIFY messages. // I took over this statement from an example without understanding the documentation. // https://bind9.readthedocs.io/en/latest/reference.html#namedconf-statement-allow-notify allow-notify { none; };
Add this to named.conf.local
to define the DNSBL service exceptions:
// ------------------------------------------------------------ // Local configuration // ------------------------------------------------------------ // Disable forwarding for DNSBL queries (used for SpamAssassin) // https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=119541646 zone "multi.uribl.com" { type forward; forward first; forwarders {}; }; //zone "dnsbl.sorbs.net" { type forward; forward first; forwarders {}; }; zone "combined.njabl.org" { type forward; forward first; forwarders {}; }; zone "activationcode.r.mail-abuse.com" { type forward; forward first; forwarders {}; }; zone "nonconfirm.mail-abuse.com" { type forward; forward first; forwarders {}; }; zone "iadb.isipp.com" { type forward; forward first; forwarders {}; }; zone "bl.spamcop.net" { type forward; forward first; forwarders {}; }; zone "fulldom.rfc-ignorant.org" { type forward; forward first; forwarders {}; }; zone "list.dnswl.org" { type forward; forward first; forwarders {}; }; zone "blackholes.mail-abuse.org" { type forward; forward first; forwarders {}; }; zone "bl.score.senderscore.com" { type forward; forward first; forwarders {}; }; zone "zen.spamhaus.org" { type forward; forward first; forwarders {}; }; zone "sa-trusted.bondedsender.org" { type forward; forward first; forwarders {}; }; zone "sa-accredit.habeas.com" { type forward; forward first; forwarders {}; }; include "/etc/bind/zones.rfc1918";
In theory this configuration should be able to satisfy all DNS queries on the hosted machine. This would mean that
- In
/etc/default/bind
this can be set:RESOLVCONF=yes
- In
/etc/resolv.conf
the green.ch nameservers can be replaced with this:nameserver 127.0.0.1
In practice it can't be done like this, because the hosted machine is embedded into the hosting company's network via DHCP. This means that /etc/resolv.conf
must be left untouched because it would eventually be overwritten by the DHCP client. As a consequence, any services like SpamAssassin that want to make use of the local DNS service must be specifically configured. See the SpamAssassin wiki page for details.
dig
The Domain Information Groper (dig) command line utility is useful for troubleshooting and "debugging" a DNS server setup. This section contains a few brief examples on usage. Note that unless specified otherwise dig will use UDP (not TCP) for queries.
To get all the information about the domain name herzbube.ch from one of the DNS servers listed in /etc/resolv.conf:
dig herzbube.ch any
Note: At the end of the output, dig displays the IP address of the DNS server that was actually queried.
Same, but get information from a specific DNS server:
dig @ns1.mydyndns.org herzbube.ch any
Note: In this example, dig needs to lookup ns1.mydyndns.org first. It will do so behind the scene, by querying one of the DNS servers listed in /etc/resolv.conf
Get "MX" record information:
dig herzbube.ch mx
Get "A" record information:
dig herzbube.ch dig herzbube.ch a
Get information about two domain names:
dig pelargir.herzbube.ch any www.moser-naef.ch any
Do not display TTL information in the query result:
dig herzbube.ch any +nottlid
Perform iterative queries, starting at the root DNS servers, and display the result of each query. This is useful to see the delegation path from the root DNS servers to the name being looked up. Note that in this use case the queries issued by dig are not recursive.
dig herzbube.ch any +trace
Reverse lookup an IP address:
dig -x 212.101.18.224
Perform a non-recursive query:
dig herzbube.ch any +norecurse
To check whom forward or reverse DNS is delegated to:
dig herzbube.ch ns # Forward DNS delegation for domain herzbube.ch dig 224.18.101.212.in-addr.arpa ns # Reverse DNS delegation for static public IP 212.101.18.224 dig 1.168.192.in-addr.arpa ns # Reverse DNS delegation for private network 192.168.1.0
Troubleshooting
dig returns with SERVFAIL
If dig returns with SERVFAIL error, this means that the DNS server it queried was unable to answer the request due to some internal error. In my case I had the problem when I tried to perform a reverse lookup.
The problem was two-fold:
- I tried to lookup the address 192.168.0.1, but my DNS server was mis-configured in a way so that it didn't know about either of the zones 168.192.in-addr.arpa or 0.168.192.in-addr.arpa
- My DNS server was also not configured to forward the request to some other DNS server
- The end result was that my DNS server could not answer the request, so the response was SERVFAIL
Interestingly enough, when I tried the utility host instead of dig I always received some sort of valid response. The reason for this is that host goes to the next DNS server if it receives a SERVFAIL, so after my own DNS server was unable to answer the request, host happily went on to query my ISP's DNS server (which of course was setup correctly). To prevent this, one can use the -s option:
host -s 192.168.0.1