Exploring the new Bind 10 name server

Test Drive

Author(s):

Admins have waited all of five years for the 10th major release of the Bind name server, which appeared at the end of March this year. The latest release is a complete rewrite of the DNS server, with a modular design and new configuration tools, but is it ready for business?

The Bind name server has a mixed reputation. Although the lion's share of DNS servers on the web run it, veteran administrators will recall – with a mixture of melancholy and horror – the difficult transition from Bind 4 to Bind 8: Although the zone files were almost identical, the configuration moved from named.boot to named.conf. The format suddenly contained brackets and semicolons that were once unnecessary. Additionally, Bind 8 and its successor allowed more configuration options, for which the old format proved insufficient.

After five years of development (Figure 1), Bind 10 brings even greater upheaval. Not only the configuration, but also the architecture has changed fundamentally. JSON database files replace named.conf; zones are still configured with familiar zone files, but in operation they are also stored in SQLite. (The administrator has the option to disable the default database storage option and go back to storage in normal zone files.)

Figure 1: Started in 2008, completed in 2013 – is everything on schedule for Bind 10?

Configuration is managed through a Rest API using HTTPS. To allow this to happen, Bind 10 comes with a command-line utility that lets administrators make configuration changes in a proprietary language.

Finally, instead of a named, Bind 10 operates through 12 processes (DHCP not included), most of which are Python processes. The built-in DHCP components, according to the project website, are still "experimental," but you can already configure and test. The modularization of Bind 10 into individual daemons is the biggest change for administrators, and it prevents you from upgrading many existing enterprise scenarios. Figure 2 shows the setup that most enterprises use for name resolution. A single name server instance handles both the authoritative and the recursive service. All clients use the name of an existing server that provides all the answers.

Figure 2: In the setup commonly used in business today, a single DNS server does all the work.

But the standard scenario depicted in Figure 2 is not ideal. A cleaner approach would be to separate the two functions, as shown in Figure 3. The recursive name server in this configuration has entries for the local zones that tell it to query the authoritative name server explicitly – through either the secondary mechanism or the forward zone entries.

Figure 3: The recommended configuration using a separate DNS resolver and an authoritative server is currently not possible with Bind 10.

As an inquiry on the Bind 10 mailing list confirmed, the configuration shown in Figure 3 is currently not possible with Bind 10. Requests for the local network would go through the Internet, with no prospect for successful responses because they only exist locally.

However, the developers say they plan to implement the setup shown in Figure 3 in a later version by letting the server evaluate the RD (Recursion Desired) bit in the query. The server will then either forward the request to the authoritative component or to the resolver. As of now, if your network reflects the scenario shown in Figure 3, you can't use Bind 10.

Installation

Bind 10 is still quite new, with no official packages, let alone repositories, when this issue went to press. The Linux Magazine test team had to build the complete application from source [1]. Shortly before the editorial deadline, packages for Bind 10 appeared on the openSUSE Build Service, which allowed for easy installation with just one click [2].

On the Gentoo installation used for the test, we needed to install the boost, botan, log4cplus, and sqlite3 packages before building Bind; Python version 3.1 or later is also required. The DHCP component requires MySQL, but you can do without it for simple tests. After installing the packages, quickly compile using:

w ./configure && make && make install

If you want to run the DHCP server with a MySQL back end, you need the --with-dhcp-mysql option.

After installing Bind 10, you first need an administrative account for the configuration interface. To set it up, run b10-cmdctl-usermgr; this utility prompts you for a username and password, which it then adds to the cmdctl-accounts.csv file in $INSTALLDIR/etc/bind10. The program is still very rudimentary and only allows you to add users; it has no other functions. Incidentally, the utility names all start with b10.

Before you set out to configure the name server, you need to decide on the mode in which you will be running it: recursive or authoritative (i.e., as the master for your own zones). Unlike the previous versions, modularization in Bind 10 leads to only one component accepting connections on one IP address. Things are different for a host with multiple IPs.

Commissioning

To start the name server, run the INSTALLDIR/sbin/bind10 wrapper script, which, in turn, starts b10-init, which is located in the libexec directory of the installation. b10-init launches the configured components. When you first start Bind 10, all the log messages are routed to the console. In a second shell on the same machine, you then launch bindctl from the INSTALLDIR/bin directory. This command-line front end for the Restful API is used to configure Bind 10.

By default, the server accepts requests on localhost port 8080 and accepts only secure SSL connections. A self-signed certificate is installed with Bind 10, but you can replace it if necessary. When a connection is opened for the first time, bindctl queries the username and password; they are sent to ~/.bind10/default_user.csv for reuse – but in plaintext.

After logging on to the server with the user you created, you need to create the desired component. In the first example (Listing 1), this is an authoritative name server. The first line creates an instance of an authoritative name server. Line 2 is used to tag Bind services that require special attention at start and stop time, including the resolver and the web server for the configuration.

Listing 1

Creating an Auth Server

 

The third line indicates whether the auth service is necessary for this configuration. config commit enables the changes, and you can then immediately test the name server. To query the version.bind entry, for example, use the following command:

dig @127.0.0.1 -c CH -t TXT version.bind

Now it is time to teach the name server about the zones it needs to provide. Bind 10 can use a SQLite database or legacy zone files to manage them. Despite SQLite, you still need to use zone files.

Apart from dynamic DNS updates, changes end up in the zone file; the old zone definition is automatically overwritten when you import the new version. Although it is possible to modify the database directly using requests, this will most likely cause inconsistencies; the bind authors advised against doing this when I asked. The import program goes by the name b10-loadzone. Listing 2 shows a sample call.

Listing 2

Importing a Zone into Bind 10

 

Zone Import

Bind 10 not only imports zones but also implicitly runs the bindctl commands, which are necessary for creating the zone. The zone is then immediately enabled. Although it is possible to point to your own SQLite database using the -c option, it is probably only necessary to split the file if you are a large provider supporting many zones. If you do not want to copy the zone to the database, but prefer to go on working with traditional zone files, you need to stick with bindctl (see Listing 3).

Listing 3

Creating a Zone with Zone Files

 

In the first step, Listing 3 creates a new instance of the class IN, to which it then adds parameters. The type is MasterFiles, in contrast to sqlite3 in the standard configuration. The parameters comprise the zone and the corresponding file in JSON format. The last line finally enables the cache, which serves up the zone from main memory instead of from the disk. This step is absolutely essential for zones made up of text files.

An entry in the data_sources/classes/IN hierarchy is not created for every new IN zone, only for the MasterFiles and sqlite3 types. The SQLite database can contain multiple zones, in which the Master Files type requires a JSON entry for each pair from a zone together with the associated file, all neatly separated by commas. As with legacy versions of Bind, admins need to communicate changes in the zone file; in Bind 10, the auth loadzone example.org command reloads the example.org zone.

Primary or Secondary?

Normally primary name servers have at least one secondary name server that copies the zones in what is known as a zone transfer process. To prevent any unauthorized person from obtaining a list of all hosts in a zone, Bind secures the zone transfer either at the IP level or  – and this is much safer – using a key or a combination of key and IP.

Bind 10 uses a key ring, which could contain multiple keys. Each entry consists of a group of three, with the name of the key, the key itself, and the actual algorithm. The administrator can omit the default algorithm, HMAC-MD5, from the name, but it is generally recommended to use other algorithms and then name them explicitly as well.

bindctl lets you create a new key:

config add tsig_keys/key "example.org.:Nvf5WLM1LA0E2VuhnkbE4Q=="

You can now reference the key in ACLs below example.org. For the secondary name server to be able to perform zone transfers, the admin must enable another component. Again, bindctl is needed for this (Listing 4)

Listing 4

Enabling the Zone Transfer Component

 

In the default configuration, the name server allows zone transfers from anywhere, without restrictions. This is also shown in the implicitly generated ACL: config show Xfrout/transfer_acl. You can manage this behavior either per zone with separate ACLs, or globally.

ACLs can be written in JSON format and have the following form:

{"action":"ACCEPT|REJECT|DROP", "from":"<IP_range>","key":"<name_of_key>"}

The IP_range lets you define a single address or a range in the form of 192.168.1.0/24, as in older versions of Bind. This feature naturally applies to both IPv4 and IPv6 addresses and networks. from and key are optional and need not be present, but if they do exist in a rule, this is considered an AND operation. A ruleset consists of several rules in which commas separate the {...} blocks; square brackets group the whole enchilada. Because this is an array, you can add ACLs with a set command instead of the usual add commands:

config set Xfrout/transfer_acl [{<first block>}, {<second block>}, ...]

It is also possible to create more complicated mappings in the ACLs. Chapter 9 of the "Bind 10 Admin Guide" provides some examples [3]. In the test, however, we only managed to release zones that Bind stored in its SQLite database. The reason for this was probably that the database has more tables for incremental zone transfers, but this option is not intended for flat files.

If you want a Bind 10 name server to act as a secondary, you need to add and configure two components: Xfrin handles the actual zone transfers; Zonemgr checks the SOA records for changes and triggers Xfrin as needed. The Bindctl statements in Listing 5 show how to configure Bind 10 as a secondary and how to integrate a zone.

Listing 5

Bind 10 as a Secondary Name Server

 

The logfile then contains entries that prove Bind does not run the zone transfer until after the final config commit at the end. You can also manually trigger a zone transfer with the following command:

Xfrin retransfer zone_name="example.test" master=10.1.1.1

Unfortunately it is not possible in the current release to set ACLs for notifies, so notifies can definitely be spoofed. The "Bind 10 Admin Guide" [3] only offers the following laconic entry: "Access control (such as allowing notifies) is not yet provided. The primary/secondary service is not yet complete."

Dynamic DNS

Bind 10 supports dynamic DNS updates that reach the computer from, say, another DHCP server. The built-in Bind 10 DHCP server is not capable of generating them.

That said: a separate component exists on the DNS server to integrate updates; you need to enable it using bindctl. Additionally, for each zone you want to receive updates, you need to enter an ACL that explicitly permits this. Listing 6 shows the configuration statements and an ACL for a zone.

Listing 6

Setting up Dynamic DNS Updates

 

Both recursive and primary and secondary name servers are separated into two components in Bind 10. If you follow the developer's advice, the two components should not run on the same host, if only because each of the components wants to accept connections to DNS on port 53; inevitably, they will get in each other's way. If you want to use them on a single host, you at least need to bind the resolver and primary to different IP addresses.

Listing 7 shows how bindctl initializes the recursive name server. Because the recursive server in the default configuration only accepts connections on localhost, and an ACL is set up by default to accept only recursive queries from localhost, you need to add 10.1.1.1 to the list of addresses on which Bind accepts requests and add an ACL that also allows recursive queries for the local 10.1.0.0/16 network.

Listing 7

Recursive Name Server

 

Logging

In the default configuration, Bind 10 writes all log information to the console where it was started. For productive operation, however, you will want to pass the messages to either syslog or a separate file. The Logging keyword helps you manage the configuration hierarchy. You can set up individual instances of the loggers type below it. A logger can record the actions of one or more components. This setting is configurable via the name parameter, where * references all components.

Listing 8 shows how to send log entries to a file. In this case, Bind also takes care of log rotation and lets you limit the size of the logfiles. Using syslog as the destination lets you pass on the messages to the syslog server. The output parameter contains the syslog facility. The severity in the logger definition (line 3) is set automatically if you use syslog. The output_options are defined as an array; however, in our lab, they resulted in two entries below a logger, neither of which worked.

Listing 8

Logging to a File

 

Performance

The response time of a DNS server can prove critical for the behavior of many other services, from the perceived responsiveness of a website through setting up calls in VoIP. With the Bind 10 installation for this article running on a virtual machine, the Linux Magazine test team conducted several comparative tests between Bind versions 9.9.2 and 10.

Figure 4 shows the results. Our choice of benchmarking tool was Dnsperf 2.0 by Nominum, a manufacturer of DNS appliances [4]. The tool uses a text file with records and types to query the A-record for host.local. The benchmark can then run the text file several times; for the auth server in this article, four records were inspected 10,000 times.

Figure 4: Average values from a benchmark conducted with Dnsperf: Bind 9 is faster.

We also tested the various storage options that Bind 10 offers (text file, SQLite DB, with and without memory cache). We had to use the default configuration for version 9.

In comparison, Bind 9 (at 3,400 queries per second) running on the same VM was just ahead of the quite obviously immature Bind 10. Dnsperf includes a second tool named Resperf for testing recursive resolvers; it first goes through a preheat phase, in which it fills the cache, before measuring the resolver throughput. Here, the test went even more obviously in favor of Bind 9, which managed about 3,000 queries per second compared with 1,600 for Bind 10.

Many Pitfalls

During the tests, yet more problems occurred. For example, after activating the cache for the zones that Bind 10 stored up in SQLite, we were only able to query the zones that were entered in the list of cache zones. We even had to enter the secondary zone that existed in the same SQLite database before we could query it. The fact that the auth server allows zone transfers by default is a 180-degree U-turn compared with the behavior of previous versions. Careless administrators are certainly at risk.

Gentoo users need to ensure that they build Python 3.2 with the sqlite useflag; otherwise, the components that use Python do not work because they cannot access their configurations without this flag.

What is also currently missing is a way of listing the configured zones. An inquiry on the mailing list resulted in constructive suggestions on how to resolve this in certain configurations. A representative of the ISC confirmed both the absence of the feature, as well as the ongoing efforts to add it.

If you use ACLs for primary or secondary zones in your existing installation of Bind, or if you use views in Bind 9, you need to be aware that these features are not possible with the standard Bind 10 tools. Again, the authors of the Linux Magazine test received a negative response on the Bind mailing list. This may change once Bind 10 becomes more widespread outside of provider environments. Right now, these missing features might already be criteria that prevent migration.

Radical Cure Without Benefits

Bind 10 means radical change, without the administrator being rewarded with benefits that justify the effort. Although its newly acquired modularity makes Bind more easily customizable and more versatile, which might also be useful for an Internet provider who offers many primary zones, the functional limitations, such as the lack of views, and especially the lack of an option for running the authoritative and recursive name servers on one machine, might limit the use of Bind 10, at least for many administrators of corporate networks.

The DHCP component is, at most, recommended for experiments only and lives up to the warnings on the website. It would also have made more sense to use the command-line utility for managing zone content; however, this option is completely ruled out, and as long as Bind 9 still outperforms Bind 10, as the benchmark in this short article suggests, corporate admins really have little incentive to upgrade to the new version.

Problem Case: Open Recursive Name Servers

In recent months, misconfigured name servers have caused numerous distributed denial-of-service (DDoS) attacks. For example, the anti-spam organization "Spamhaus" experienced a DDoS attack around Easter that achieved an incredible bandwidth of 300Gbps.

A DNS DDoS attack typically involves the attacker using UDP to send many DNS requests with the spoofed source IP of the victim to tens of thousands of servers on the Internet. Open recursive name servers allow and respond to these requests for any IP address – and, as a consequence, send their responses to the victim, where data packets arrive simultaneously from all over the world. The attacker only needs to send very small queries, querying specific DNS records, to generate large responses of several kilobytes. This attack is often called the "DNS Amplification Attack."

Recursive name servers, then, always need an ACL to specify the IP network areas for which they are responsible. Only in the rarest cases will this actually be a global 0.0.0.0/0; instead, the range should be restricted to a DMZ, intranet, or dialup areas. External laptops that need to access a corporate DNS should also originate from a clearly defined address range – a precaution that is possible thanks to VPN tunnels.

For Bind 10, Listing 7 shows the necessary query_acl using the 10.1.0.0/16 network as an example. The entry

options {
  [...]
  allow-recursion { 10.1.0.0/16; 127.0.0.0/8; ::1; };  [...]
}

produces an allow-recursion ACL in the options block for the still-widespread Bind 9. (Peer Heinlein)

The Author

Konstantin Agouros works for N.runs AG as a consultant for network security. His focus is on telecommunications providers and free software. His book DNS/DHCP is published by Open Source Press.