Introduction
The Domain Name
System (DNS) is a replicated, distributed, hierarchical
database of information that is a core service needed for the
modern internet to function. If you're new to the Domain Name
System please read
Thomas Bridge's article. This article is primarily aimed at
those familiar with basic DNS concepts and the operation and
configuration of a DNS server.
This article concentrates on BIND, the de-facto standard
implementation of DNS. Other implementations can achieve the same
results using these directions, however the instructions and
examples below are for administrators of a BIND 8.x or BIND 9.x
nameserver.
What is TSIG and why do I want it?
The DNS works on a question-answer model. If a client needs
information from the DNS it sends a question to a DNS server and
the server returns an answer. Until recently it was only possible
for a server to examine a question and determine whether or not to
answer it based on the IP address the question originated from.
This is not ideal. Authentication using source IP address alone is
considered insecure. Transaction Signatures, or TSIG for short, add
cryptographic signatures as a method of authenticating a DNS
conversation. It uses a shared secret to establish trust between
the communicating parties.
TSIG is used to ensure that DNS information purporting to be
from a certain server is actually from that server. I have mostly
put it to use to authenticate zone transfers between master and
slave nameservers. I want to be sure that my slave nameserver is
never fooled into accepting a copy of my zone from an imposter who
spoofs my master nameserver's IP address.
Transactions signatures are defined in RFC 2845.
For the examples below we will presume to be using TSIG to
authenticate DNS traffic between two servers; server1 (10.0.0.1)
and server2 (10.0.0.2).
Create your secret
TSIG uses a shared secret which is incorporated into an MD5 hash of
the information to be signed. BIND comes with a tool to create
suitable secrets; dnskeygen. In TSIG parlance secrets are
also called keys. dnskeygen takes many options -- run it
with no flags to see a list.
$ dnskeygen -H 256 -h -n 2000011501.linuxservers.tsigkey.
Generating 256 bit HMAC-MD5 Key for 2000011501.linuxservers.tsigkey.
Generated 256 bit Key for 2000011501.linuxservers.tsigkey. id=0 alg=157 flags=513
$ ls *tsigkey*
K2000011501.linuxservers.tsigkey.+157+00000.key
K2000011501.linuxservers.tsigkey.+157+00000.private
$ cat K2000011501.linuxservers.tsigkey.+157+00000.private
Private-key-format: v1.2
Algorithm: 157 (HMAC)
Key: HW/WyHCn8q312B7tzjAx3X2XmmZG86AqHQmn+QyB6CA=
-H 256 sets the key size, in the range 1-512.
-h requests creation of a host key. -n
2000011501.linuxservers.tsigkey. specifies the name of the
key.
The name of each key needs to be unique. i.e. two keys should
not share the same name, hence the slightly unusual name I've given
it. That said, you should try to give them names that will be
meaningful to you -- it will make your life easier. The generated
key will be saved into two files both of whose names will begin
with the letter K followed by the name of the key and some
other text. The file ending in .private is slightly easier
to read though they both contain the same secret (in different
formats). The key/secret is the sequence of characters after
Key: .
Tell your nameserver about the key
To add the new key to your nameserver configuration use a
key clause in the nameserver configuration file. The file is
called named.conf and is usually located in /etc.
Add the following to the named.conf file (changing the key name and
secret to match your own):
key 2000011501.linuxservers.tsigkey. {
algorithm "hmac-md5";
secret "HW/WyHCn8q312B7tzjAx3X2XmmZG86AqHQmn+QyB6CA=";
};
The key clause should be included in the configuration file of
the nameservers that will use this key to authenticate. We want
server1 and server2 to use this secret so the above clause should
be included on both machines.
Tell your nameserver when to use the key
The nameserver must be told when it should use the key. A
server clause does this. Using this clause we can direct the
nameserver to use a certain key when communicating with a given IP
address. On each server add a server clause specifying the
IP address of the other machine and the name of the key to use.
On server1 use:
server 10.0.0.2 { # 10.0.0.2 is the IP address of server2
keys {
"2000011501.linuxservers.tsigkey.";
};
};
and on server2 use:
server 10.0.0.1 { # 10.0.0.1 is the IP address of server1
keys {
"2000011501.linuxservers.tsigkey.";
};
};
Use ndc reconfig to get each nameserver to read its
configuration file. It should now be aware of the secrets and of
the servers for which to use them. Watch the nameserver's log files
to see if it logs any warnings or errors.
You're done! To test it, update a zone and see if your slave
nameserver will transfer it. Alternatively, change a character of
the secret on the master nameserver, reload the configuration and
try to get the slave to transfer the zone. It should log messages
about failed verifications.
Other important points
Your secret is just that; a secret. You need to place it onto
the two servers in a secure fashion. You need to set appropriate
modes on named.conf so that it can't be read from
named.conf by unauthorised local users.
Use NTP or some other system to keep good time on your
nameservers. If time on the machines sharing a secret gets too far
out of whack signature verification will fail. Make sure you add
the elements above to the named.conf in the order above.
Specifically make sure a key clause appears before any
server clause that references it in named.conf.
Verifying a TSIG requires writing a temporary file. Make sure
that named can write to its default directory.
Microsoft's implementation of TSIG doesn't use the algorithim
from RFC 2845 (HMAC-MD5) *sigh*
Microsoft GSS-TSIG is non-standard and will not inter-operate with
BIND.
James Raftery
17th January 2001.
|