TKEY and zone transfer

Evan Hunt each at
Tue Jan 29 21:27:50 UTC 2013

On Tue, Jan 29, 2013 at 04:22:07PM +0800, Kent Tong wrote:
> I read that Bind9 supports using TKEY for zone transfers. However, I don't
> understand how the TKEY negotiation is triggered.

Huh.  That is much harder than it ought to be (a fact I hadn't realized
until now, as I'd never had occasion to look closely at this feature until
you asked your question).  I've just put in a bug report suggesting we
improve it in a future release.

For now, this is the best I can do for you... though quite honestly, I
think this approach is probably more trouble than it's worth; if it were
me, I'd just use conventional TSIG until there've been some improvements.
But if you really want to use TKEY, here you go, this formula worked for

There's a program in the BIND 9 test suite that you can adapt
to your purposes if you're comfortable with C programming --
bind9/bin/tests/system/tkey/keycreate.c (also keydelete.c for removing
keys after they've been created).  You'll need to modify the code to use
port 53 instead of port 5300, and to use different key material (see

First, you need to create a DH (diffie-hellman) key for your server:

    $ dnssec-keygen -T KEY -a DH -b 768 -n HOST server

Note the key ID (in this example 32204).  Put the resulting .key
and .private files into named's working directory, and configure
named.conf to reference that key:

    options {
        tkey-domain "server";
        tkey-dhkey "server" 32204;

Also, generate a TSIG key to use for the initial TKEY negotiation.
The simplest way to generate TSIG keys is with ddns-confgen:

    $ ddns-confgen -q -a hmac-md5 -k tkeyinit
    key "tkeyinit" {
        algorithm hmac-md5;
        secret "RzLQq6b1oBN1QveexTf76g==";

Add that key information to your named.conf.

You'll need to copy the name and secret into keycreate.c and keydelete.c:
these written to be test programs; the key material is hard-coded into them.

At this point, you can create a diffie-hellman key for the client, and use
it with keycreate to negotiate a TSIG key with the server:

    $ dnssec-keygen -T KEY -a DH -b 768 -n HOST client
    $ keycreate Kclient.+002+11382 negotiated-key
    $ cat Knegotiated-key.server.+157+19753.key
    negotiated-key.server. IN KEY 512 3 157 MlNODIuzTrNMgSLRCFB1Iw==

The key generated by keycreate can then be used on the client side
to sign transfer requests:

    key negotiated-key.server {
        algorithm hmac-md5;
        secret "MlNODIuzTrNMgSLRCFB1Iw==";

    zone { 
        type slave;
        masters { key negotiated-key.server };

...and that should work as long as the server side was configured to allow
transfers using the *initial* TSIG key that was used to create the
negotiated key -- not the negotiated key itself:

    zone {
        type master;
        allow-transfer { key tkeyinit; };

The transfer request to the server will be signed with the key
negotiated-key.server, not with tkeyinit.  The server will still
allow it, though, because tkeyinit is the parent key of
negotiated-key.server.  (Note, however, that transfers will also
be allowed for any request signed with tkeyinit, or with any other
key that was negotiated using tkeyinit.  I don't know whether there's
a way to make the server accept only one specific negotiated key.)

Evan Hunt -- each at
Internet Systems Consortium, Inc.

More information about the bind-users mailing list