Secure Zone transfer in BIND using TSIG(Transaction Signatures)
In this post i will explain some of the concepts related to DNS zone transfer, and how to secure zone transfer. As other tutorials i will begin with the basics and concepts, and then we will look into configuration part (i will include the configuration details in between.)
BIND is a highly used DNS server package available for both Linux and windows. It’s much flexible compared to other DNS server packages.
For those who don’t know what is a DNS zone file i will recommend reading the below article i wrote sometime back, which will explain the content of a zone file.
Read: What is a DNS zone file and its contents
DNS must always be deployed in a distributed architecture (in other words there must never be a single point of failure). There is a reason for that. The main reason is that DNS is the main building block of how internet functions, in a more accurate term it’s an important technology that keeps your publicly available as well as private services running and accessible.
Imagine a situation where you have only one DNS server, for your publicly available service in one location. If something happens on that server and due to some reason it goes down or becomes unreachable, then all your publicly available services will be down, till the server comes back online (it’s not correct to say that your services will be down, but it will be correct to say that people will not be able to reach the IP address that runs your website or services. But who remembers your website’s IP address? People remember just names not numbers. That’s the reason our parents kept a name for us and not a numberJ.
Let’s take an example with the help of a domain called example.com (this is a reserved domain name by IANA, for showing illustrations). And you have a website running at www.example.com and you have one DNS server for your domain (i will be using private ip address range for showing you this example).
In the above shown example there is only one DNS server 172.16.202.3 for the domain example.com. Suppose this is a publicly available server and it goes down due to some maintenance in your data centre, people will not be able to reach your website and all other domains related to your domain, as well as people will not be able to send mails to your something@example.com domain. This is the main reason why people distribute their DNS servers in different locations and region. Your services would have stayed online if you had at least two DNS servers for example.com domain.
As i told DNS must always be distributed and most of the times it has a master slave relationship. People keep master slave relationship between DNS servers simply because you can administer the domain zone from one master server itself, and the slaves will automatically sync with the master server. But there is a serious risk involved when you send zone information over the internet.
Zone file consists of very important details of all your hosts and its addresses. Anybody in between can simply open the packet with the help of any packet scanning tool and read your zone content.
In this tutorial we will be walking through the steps to create a zone for example.com, and then configure secure zone transfer to its slave servers in another location.
The main prerequisite for understanding this tutorial is BIND dns software package, which is freely available from almost all distribution repositories. I will be using Ubuntu 12 version for this tutorial (the configuration file locations might vary slightly according to your distribution, however the content inside the configuration files will be exactly the same.)
The first step is to install the bind software package, which can be done as shown below.
#apt-get install bind9 bindutils
If you are using a red hat based system then the yum command would be something like the below.
#yum install bind bind-utils -y
The main configuration file for bind is /etc/bind/named.conf, or in red hat based systems it will be located at /etc/named.conf (on some versions of bind this file might not be present by default, in that case you need to create that file.)
As i told before, i will be showing this example tutorial inside ubuntu distribution. This named.conf file consists of directives to include other configuration files. Or you can include the configuration here itself. However i would suggest to keep everything seperated so that it becomes easy for modifying the configuration in future.
Let's include some of the important files that we will be using in this zone and secure zone transfer configuration.
# cat named.conf // This is the primary configuration file for the BIND DNS server named. // // Please read /usr/share/doc/bind9/README.Debian.gz for information on the // structure of BIND configuration files in Debian, *BEFORE* you customize // this configuration file. // // If you are just adding zones, please do that in /etc/bind/named.conf.local include "/etc/bind/named.conf.options"; include "/etc/bind/named.conf.local"; include "/etc/bind/named.conf.default-zones";
There are three important files that are included in this configuration file. Include directive used in named.conf file will make bind read and load configurations mentioned in those files.
Now if you see the above file output the three main files included are named.conf.options, named.conf.local, named.conf.default-zones. You can also include all configuration details inside named.conf file itself but its better to seperate each of them to avoid confusion. The comment section of the above shown named.conf file says that "if you are just adding zones, please do that in /etc/bind/named.conf.local". So let's add our zone called example.com inside that file.
zone "example.com" in { type master; file "/etc/bind/zones/master.example.com"; allow-transfer { key dns-server.example.com; }; allow-query { any; }; also-notify { 172.16.200.23; 172.16.202.23; }; notify yes; };
Let's understand each line and its meaning in the above shown zone clause inside our bind installation.
- zone "example.com": is the opening of the zone clause and it specifies the zone for which this configuration is applicable.
- type master: this statement is used to specify that this server is going to be the master server for the zone example.com, and will be authoritatively modifying the zone content.
- file "/etc/bind/zones/master.example.com": This statement denotes the file on our DNS server which contains the zone file and its records(we will see that file in some time).
- allow-transfer {key dns-server.example.com}: This line is the most important line that is part of the security feature in bind for secure zone transfer. This line says that zone trasfer is allowed only to servers that have this key named dns-server.example.com. Please note the fact that the name of this key must be same on the slave servers as well.
- allow-query {any;}: This line specifies that this zone can be queried by any ip address.
- also-notify {172.16.200.23; 172.16.202.23; }: This line says that the bind server should notify these servers whenever a zone modification happens. If you see the statement, it is also-notify, means bind is will already be informing some servers about its zone modification, along with that include these servers as well(i will exaplain this a little later while making the zone file for example.com).
- notify yes; is an option used to convey bind to notify slaves about the zone modification.
Now let's create our zone file in our specified location, which we mentioned in named.conf.local inside the zone clause.
Let's see our zone file content inside /etc/bind/zones/master.example.com.
;zone file for domain example.com $TTL 300 ; zone default of 5 minutes $ORIGIN example.com. @ IN SOA ns1.example.com. admin.example.com. ( 2013100702 ; serial number 2h ; refresh 15m ; update retry 5w ; retry 2h ; minimum ) IN MX 10 mail.example.com. IN NS ns1.example.com. IN NS ns2.example.com. ns1 IN A 172.16.202.55 ns2 IN A 172.16.203.85 www IN A 172.16.200.18 apps IN A 172.16.200.19 ftp IN A 172.16.200.22
As far as this article is concerned its primary focus will be towards zone transfer and its security. But i have shown the zone file to make you understand two important parameters in zone file that effects the zone trasfer operation as well as notify operations.
The first paramter that needs to be understood is the serial number shown in the above zone file. It is a number with a format that is used by slave dns servers to detect whether the zone has been modified. If the serial number is greater than the one that the slave has, then it will initiate a zone transfer, other wise it will not.
The standard format that must be used is as shown below.
YYYYMMDD(number of times modified per day)
The first three field of year, month, day is easy to understand. The last filed is the number of times you have modified the zone file on that particular date of month.
So our serial number is 2013100702. Which means we have modified our zone file two times on 7 th day of 10th month of 2013. If you modify this same zone one more time on the same day the last field needs to to be modified to 03 from 02. Although you can simply increase serial number by 1 everytime you modify it without worrying about the date and day, following a standard will reduce the number of errors, and you can be rest assured that your serial number is always greater than the one in slave servers each time you modify.
Now let's go ahead and unerstand the second important thing in our zone file. We have two NS record in our zone file shown above named ns1 & ns2.
IN NS ns1.example.com. IN NS ns2.example.com.
These NS servers will automatically be notified by bind, whenever you modify the zone. That's the reason why we have mentioned, the below statement inside our named.conf.local file
also-notify { 172.16.200.23; 172.16.202.23; };
By the above statement in named.conf.local, we are telling bind to notify 172.16.200.23 & 172.16.202.23 other than the default ns1 and ns2.
Now as our zone file is ready with its configuration, let's discuss the security part that will help slave servers to initiate a secure zone transfer. This security is achieved through a key file which we defined inside named.conf.local while defining our zone.
If you remember, our previously created named.conf.local file for zone clause did contain a statement as shown below.
allow-transfer { key dns-server.example.com; };
The above statement tells bind to only allow those servers to initiate a zone transfer who has a key named dns-server-example.com. But yet we have not definined this key. Lets create another configuration file that will contain the key and its statement.
As i told before, if you want bind software to load your configuration file at startup, then you must explicitly include that file in named.conf. So lets first create a file which will contain the key and include it in named.conf, also we need to first create a key for this configuration. So let's begin by creating a key file for this zone transfer.
dnssec-keygen -a HMAC-MD5 -b 256 -r /dev/urandom -n HOST dns-server.example.com
The above command will create two key files with HMAC-MD5 algorithm with 256 bit size, and will use /dev/urandom for generating random bytes for key generation purpose.
There will be two files in the directory where you ran the above command. We will be using one .private file among the two. Let's see the content of .private file.
# cat Kdns-server.example.com.+157+48197.private Private-key-format: v1.3 Algorithm: 157 (HMAC_MD5) Key: wI6XiocuMR8X/DySzKVbp2SdzZZeXCsQLjEs6HRlnkY= Bits: AAA= Created: 20131009070939 Publish: 20131009070939 Activate: 20131009070939
The main field in the file is the key field shown below
Key: wI6XiocuMR8X/DySzKVbp2SdzZZeXCsQLjEs6HRlnkY=
We will be using that key in our zone transfer for signing and verifying the zone trasfer request and response. Now let's create a configuration file that will contain this key file which bind can use for zone transfer operations.
Now let's create a file named tsig.example.com
key dns-server.example.com { algorithm hmac-md5; secret "wI6XiocuMR8X/DySzKVbp2SdzZZeXCsQLjEs6HRlnkY="; };
Now as you have created the key file and entered the key file value inside a new configuration file called as tsig.example.com, you need to include that file inside named.conf. So the final named.conf file should look something like the below.
include "/etc/bind/named.conf.options"; include "/etc/bind/named.conf.local"; include "/etc/bind/named.conf.default-zones"; include "/etc/bind/tsig.example.com";
Please remember the fact that the owner of the file you created must be the user with which your bind service is running. On ubuntu its "bind".
Now reload the bind service and you are ready for a secure zone transfer.
If you want to test whether your secure zone transfer is working or not, then you need to run the below dig command.
$ dig @yourdnsserverIP example.com axfr ; <<>> DiG 9.8.1-P1 <<>> @172.16.200.26 ns.example.com axfr ; (1 server found) ;; global options: +cmd ; Transfer failed.
The above dig command for zone transfer will fail, as you have not provided the key for zone transfer. Providing the key for zone transfer will give you a success.
Your slave name servers should have a similar key clause statement with the same key name, to initiate a successful zone transfer. For that you need to first copy or send a secure e-mail containing the key you are using to the administrators handling the slave servers. Or copy it through secure copy scp or some other tls method.
Read: How to send secure email
Once your slave servers have deployed the same key with the same name, zone transfer between the two will happen based on this key and signatures. I will come up with another article in some days, that will cover security in bind in a little more detail.
Add new comment