Note: This article was written alongside BIND 10 1.0.0-beta. See this article which covers the major differences to be aware of between 1.0.0-beta, and 1.0.0-rc.
In the previous article in the BIND 10 series, we saw how to build and install BIND 10, start it up (in the background), get it running as a designated user, connect to the command channel, and issue a command to shut BIND 10 down. In this article, we will see how BIND 10 needs to be configured to act as an authoritative DNS server. Further articles will deal with recursion, the DHCP components, and more as I investigate BIND 10 in more detail. I’m learning as I write too, so bear with me - BIND 10 is very new software, and is still in Beta stages of development - thus a lot of BIND 10 is still incomplete, or even where complete - incoherent - especially to a BIND 9 veteran like myself!
If you haven’t read the BIND 10: First Steps article, I suggest you go and do that now.
We will use bindctl to interact with the BIND 10 command channel. I’ve had a bit more time to dig into bindctl and what it actually does (and where it stores its configuration) so we will digress a little at first, and take a look at that.
bindctl: Where are my Configuration Commands Going?
Before we start issuing configuration commands via bindctl, it’s worthwhile knowing exactly where the configuration is stored, how bindctl interacts with b10-cmdctl, and in what format the configuration is stored.
Reviewing the BIND 10 Guide (points for counting how many times I refer to this document over all my BIND 10 articles), we can see that we communicate with the configuration manager over some administrative interface (in our case the only option at present is bindctl). The configuration manager provides a RESTful API, and writes the configuration out in JSON (JavaScript Object Notation). Or … as the Guide points out “a format loosely based on JSON”. I will sigh (/sigh) and continue.
As we’ve not provided any configuration commands as yet, the configuration DB does not yet exist. However, once we have, it will be available for review at <BIND_10_BASE>/var/bind10/b10-. This file is of cursory interest, but should not be modified directly.
Enabling Authoritative DNS
It’s time to get BIND 10 to do some work for us - configuring it to serve DNS data for a simple zone. There will be many things to note along the way, so pay attention! When we left the last article, BIND 10 was shutdown, so make sure it’s up and running before continuing with this article. It’s running? Good - let’s carry on.
Looking at the BIND 10 Guide (hereafter referred to as the Guide - too much typing otherwise), we have two choices. We can either execute the predefined command set init_authoritative_server, provided with BIND 10, or issue the commands required manually.
In order to cement your understanding of bindctl, and BIND 10 configuration in general, I suggest entering the commands manually for now. Connect to your BIND 10 instance viabindctl:
|
1 2 3 |
# ./bindctl ["login success "] login as root > |
Next, enable the appropriate components. Looking at the Guide, we have to enable b10-auth, b10-xfrin, b10-xfrout and b10-zonemgr. I’ll issue the appropriate commands required to enable the authoritative DNS service within BIND 10, and then go over the commands used and try to explain them as best I can using the available resources (i.e. the Guide - there isn’t much else). Let’s enable authoritative DNS:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
> config add /Boss/components b10-auth > config set /Boss/components/b10-auth/kind needed > config set /Boss/components/b10-auth/special auth > config add /Boss/components b10-xfrin > config set /Boss/components/b10-xfrin/address Xfrin > config set /Boss/components/b10-xfrin/kind dispensable > config add /Boss/components b10-xfrout > config set /Boss/components/b10-xfrout/address Xfrout > config set /Boss/components/b10-xfrout/kind dispensable > config add /Boss/components b10-zonemgr > config set /Boss/components/b10-zonemgr/address Zonemgr > config set /Boss/components/b10-zonemgr/kind dispensable > config commit > Boss show_processes [ [ 8056, "Socket creator", null ], [ 8057, "msgq", null ], [ 8058, "cfgmgr", "ConfigManager" ], [ 8059, "b10-stats", "Stats" ], [ 8060, "b10-cmdctl", "Cmdctl" ], [ 8102, "b10-zonemgr", "Zonemgr" ], [ 8103, "b10-xfrin", "Xfrin" ], [ 8105, "b10-auth", "Auth" ], [ 8108, "b10-xfrout", "Xfrout" ] ] > |
OK - a lot has just happened. Firstly, we’ve enabled all four required components, using config add. b10-auth has the kind parameter set to needed. If a component fails at startup and its kind is needed, BIND 10 will shut down and exit with an error code. If it fails at some time after startup, it’ll be restarted. The dispensable kind is the default, and means that the process will be restarted if it fails (though it will not cause BIND 10 to fail to start if the component fails to start when BIND 10 initially starts up). The address parameter defines the address of the component used on the b10-msgq message bus. By convention, this is the name of the component less the b10-, and with the first letter capitalised. Thus, b10-xfrinhas the address Xfrin on the bus. Lastly, no configuration is written until we run config commit. After issuing the commit, a Boss show_processes shows that all our original components are still running, as well as the four new components we configured. Let’s exit bindctl now, and see what’s happened:
|
1 2 3 |
> quit Exit from bindctl |
Running a netstat confirms that a Python process is listening on 0.0.0.0:53 - both TCP and UDP:
|
1 2 3 4 5 |
# netstat -anlp | grep ':53' tcp 0 0 0.0.0.0:53 0.0.0.0:* LISTEN 8055/python3 tcp 0 0 :::53 :::* LISTEN 8055/python3 udp 0 0 0.0.0.0:53 0.0.0.0:* 8055/python3 udp 0 0 :::53 :::* 8055/python3 |
A quick look at the PID shows that it’s actually the bind10 process that listens on port 53 - NOT b10-auth:
|
1 2 3 |
# ps -fp8055 UID PID PPID C STIME TTY TIME CMD root 8055 1 0 01:25 pts/1 00:00:00 /usr/local/python3/bin/python3 ./bind10 |
b10-auth is running, however, and will handle the actual business-end of authoritative DNS. I’ve yet to test whether both the authoritative and recursive components can run on the same server.
Looking under <BIND_10_BASE>/var/bind10, we can see that b10-config.db has now been created:
|
1 2 3 4 5 6 7 8 |
# cd /usr/local/bind10/var/bind10/ # ls -l total 20 srwxr-xr-x. 1 root root 0 Jan 31 01:37 auth_xfrout_conn -rw-------. 1 root root 385 Jan 31 01:37 b10-config.db -rw-rw----. 1 root root 0 Jan 31 01:25 logger_lockfile srwxr-xr-x. 1 root root 0 Jan 31 01:25 msgq_socket -rw-r--r--. 1 root root 14336 Jan 31 01:37 zone.sqlite3 |
We can view that configuration too:
|
1 2 |
# cat b10-config.db {"version": 2, "Boss": {"components": {"b10-xfrin": {"kind": "dispensable", "address": "Xfrin"}, "b10-cmdctl": {"kind": "needed", "special": "cmdctl"}, "b10-xfrout": {"kind": "dispensable", "address": "Xfrout"}, "b10-auth": {"kind": "needed", "special": "auth"}, "b10-zonemgr": {"kind": "dispensable", "address": "Zonemgr"}, "b10-stats": {"kind": "dispensable", "address": "Stats"}}}} |
You can now see why this file shouldn’t be modified directly. The more configuration we apply to BIND 10, the more complicated this file will become. Querying this configuration should also be performed via bindctl.
Before we move on to loading a zone or two into our new authoritative BIND 10 instance, let’s confirm that it is serving DNS data authoritatively. The trusty CHAOS class (CH) is present in a default BIND 10 authoritative server install, so we can query version.bind and friends:
|
1 2 |
# dig CH TXT version.bind @localhost +short "bind10 1.0.0-beta" |
If this were a Production server, I’d look to remove the CH class entirely, or modify the version of BIND being returned via a query for version.bind to an empty string or similar.
You will also observe that zone.sqlite3 has now been created. This is the default location of the zonefile database. Time to have a poke around in there.
|
1 2 3 4 5 6 7 8 9 10 11 |
# sqlite3 zone.sqlite3 SQLite version 3.6.20 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .tables diffs nsec3 records schema_version zones sqlite> select count(*) from zones; 0 sqlite> select count(*) from records; 0 sqlite> .exit |
Once we load some zone data proper, we’ll see the database being populated. I’ll park SQLite for now, and revisit once a zone has been loaded.
Loading a Zone
Let’s create a sample zonefile. I’ll presume that you understand basic zonefile syntax as defined in RFC 1035 section 5 and RFC 1034 (section 3.6.1):
|
1 2 3 4 5 6 7 8 9 10 11 |
# cat /var/tmp/db.example.com $ORIGIN example.com. $TTL 1h example.com. IN SOA ns1.example.com. hostmaster.example.com. ( 2013140201 172800 900 1209600 3600 ) example.com. IN NS ns1.example.com. example.com. IN MX 10 mail.example.com. @ IN A 192.168.0.1 ns1 IN A 192.168.0.1 www IN CNAME example.com. mail IN A 192.168.0.2 |
The b10-loadzone command is used to load the zone. In the following example, the -c option to b10-loadzone can be omitted as we’re using the default database location - but I’ve specified it below to show how the full command is formed:
|
1 2 3 4 |
# cd /usr/local/bind10/bin # ./b10-loadzone -c '{"database_file": "/usr/local/bind10/var/bind10/zone.sqlite3"}' example.com /var/tmp/db.example.com 2013-01-31 02:47:35.474 INFO [b10-loadzone.loadzone/8207] LOADZONE_ZONE_CREATED Zone example.com./IN does not exist in the data source, newly created 2013-01-31 02:47:35.478 INFO [b10-loadzone.loadzone/8207] LOADZONE_DONE Loaded (at least) 0 RRs into zone example.com./IN in 0.00 seconds |
“Loaded (at least) 0 RRs” - hmm - you’d hope so. Let’s use sqlite to confirm that BIND 10 has actually loaded the zone into the sqlite database:
|
1 2 3 4 5 6 7 8 9 |
# cd /usr/local/bind10/var/bind10 # sqlite3 zone.sqlite3 SQLite version 3.6.20 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> select count(*) from zones; 1 sqlite> select count(*) from records; 7 |
OK - we can see that BIND 10 has loaded a single zone with 7 resource records. Our original zonefile had 7 RRs so this is promising. Let’s dig further:
|
1 2 3 4 5 6 7 8 9 10 |
sqlite> select * from zones; 1|example.com.|IN|0 sqlite> select * from records; 1|1|example.com.|com.example.|3600|SOA||ns1.example.com. hostmaster.example.com. 2013010201 172800 900 1209600 3600 2|1|example.com.|com.example.|3600|NS||ns1.example.com. 3|1|example.com.|com.example.|3600|MX||10 mail.example.com. 4|1|example.com.|com.example.|3600|A||192.168.0.1 5|1|ns1.example.com.|com.example.ns1.|3600|A||192.168.0.1 6|1|www.example.com.|com.example.www.|3600|CNAME||example.com. 7|1|mail.example.com.|com.example.mail.|3600|A||192.168.0.2 |
All of our zone data has been loaded correctly. Exiting SQLite, we can query BIND:
|
1 2 3 4 |
# dig SOA +short example.com @localhost ns1.example.com. hostmaster.example.com. 2013010201 172800 900 1209600 3600 # dig CNAME +short www.example.com @localhost example.com. |
So, we’re now serving example.com authoritatively out of BIND 10. Let’s modify the SQLite backend directly and update the IP address for the example.com A record:
|
1 2 3 4 5 |
sqlite> select * from records where rdtype = 'A' and name = 'example.com.'; 4|1|example.com.|com.example.|3600|A||192.168.0.1 sqlite> update records set rdata = '192.168.0.2' where rdtype = 'A' and name = 'example.com.'; sqlite> select * from records where rdtype = 'A' and name = 'example.com.'; 4|1|example.com.|com.example.|3600|A||192.168.0.2 |
Let’s check it’s worked from BIND 10′s perspective:
|
1 2 |
# dig A example.com @localhost +short 192.168.0.2 |
Excellent. One thing to note is that within SQLite you can use the “.schema <tablename>” command to understand the (basic) schema employed by BIND 10.
Conclusion
This article has shown how to enable the authoritative DNS server component within BIND 10, and how to load a sample zone to demonstrate the ability of BIND 10 to serve this data. It’s also shown how to make trivial updates directly in the SQLite database.
In future BIND 10 related articles, I’ll look at the recursive component, zone transfers, ACLs and the DHCP components of BIND 10. Hopefully, the first two articles in this series will give you enough to get you started.
My recommendation is (obviously) to continue to use BIND 9 for any Production purposes - or better yet switch to PowerDNS as I did. I will also be writing an article on getting PowerDNS 3.2 up and running, so stay tuned to tokiwinter.com for that soon.