DNSSEC on a .co.uk domain with BIND and IPv6


I finally managed to sign my .co.uk with DNSSEC, whereas the signing happens via IPv6. As the original Nominet documentation about DNSSEC points out (this article is based on that documentation), you would need two nameservers. Familiar with BIND, its concept of "views" came to mind and here is how you can do this - with one server.

When reading that documentation I was intrigued by the fact that Nominet's DSS is also offering that service via IPv6. As I already had IPv6 running and I do not pay for any additional IPv6 address, I thought - why not? This brings me to how Nominet's DSS actually works.

Using "Nominet DSS"

"DSS" stands for "DNSSEC Signing Service" first of all. At its heart it basically transfers your unsigned zone data out, signs them, and makes them available for you to be transferred in. So DSS has frontend addresses of and 2A01:618:8009:0:988:B84B:769D:7D96 which "AXFR" your zone from your unsigned master, hosting your unsigned zone data. Then you have a signed slave, which sees the DSS as the master, and transfers the signed zone back in and presents them to your clients.

I had already a nameserver running on IPv4 and I thought this is gonna be then my signed slave. This also has the advantage that you don't need to change nameserver IPs, in my case I only needed to add IPv6 support. Also, an existing slave setup won't need to be changed. I am using 9.8.4.dfsg.P1-6+nmu2+deb7u2 on a latest and greatest Debian.

So let's jump straight into configuring it what we have so far:

acl NominetDSS {;

ACLs are always handy. I just like them. This looks useful. You might want to create ACLs for your (signed) slave servers as well, if you haven't already.

options {
  listen-on {; $SIGNED_SLAVE_4; };
  listen-on-v6 { ::1; $UNSIGNED_MASTER_6; $SIGNED_SLAVE_6; };

  allow-transfer {; $SLAVES; NominetDSS; };
  recursion no;
  • $SIGNED_SLAVE_4: Your own existing nameserver, which will be the signed slave, on IPv4.
  • $UNSIGNED_MASTER_6: Your unsigned master on IPv6.
  • $SIGNED_SLAVE_6: Your signed slave on IPv6.

Still with me? Draw it out for your case, unsigned master on the left, signed slave on the right and DSS in the middle. DSS pulls the zone data from your unsigned master, so that's an arrow from DSS to your unsigned master. Another arrow from your signed slave to DSS. Then add your IP addresses to it. If you have only IPv4, then skip all the IPv6 stuff and just add your IPv4 addresses. With a picture it will be fairly easy going. IPv6 here makes it a bit complicated, but it isn't.

Adding a DSS View

Now next comes our first BIND view:

view DSS {
  key master.preissler.co.uk {
    algorithm hmac-sha256;
    secret "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=";

  server {
    keys master.preissler.co.uk;

  server 2A01:618:8009:0:988:B84B:769D:7D96 {
    keys master.preissler.co.uk;

  match-destinations { $UNSIGNED_MASTER_6; };
  allow-query { NominetDSS; };
  allow-transfer { NominetDSS; };
  notify-source-v6 $UNSIGNED_MASTER_6;

  zone "preissler.co.uk" {
    type master;
    file "preissler.co.uk";
    notify explicit;
    also-notify { 2A01:618:8009:0:988:B84B:769D:7D96; };
  • key: This has been generated via "dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST master.preissler.co.uk"; and then I just copied the generated key into this config. The name of this key definition is very important, make sure you get this right, or either the transfer out, in or both won't work. It doesn't really matter which name you choose, but it has to be the same one everywhere (it is very important that your registrar is also using the same name, as this determines which key name DSS will be using.)
  • server: These two definitions ensure that any communications with Nominet's DSS IPs are always using this defined key. We don't want that NOTIFYs are using a key, but not actual transfers for example.
  • match-destinations: This took a while to figure out and do it right. The thing what is important here is that Nominet DSS is using one single IP for querying your unsigned master but the same IP for making your zone data available signed. On our side we have to decide what they are talking to and the destinction is the destination address. Only fairly recent BIND versions support this feature.
  • notify-source-v6: We have to explicitely set this to the IP address of our unsigned master.

Adding your zone

view NS {
  key slave.preissler.co.uk {
    algorithm hmac-sha256;
    secret "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=";

  server {
    keys slave.preissler.co.uk;
    request-ixfr no;

  server 2A01:618:8009:0:988:B84B:769D:7D96 {
    keys slave.preissler.co.uk;
    request-ixfr no;

  match-clients { "any"; };
  transfer-source-v6 $SIGNED_SLAVE_6;
  allow-query { "any"; };

#       zone "preissler.co.uk" {
#               type master;
#               file "preissler.co.uk";
#               allow-update { key domain-admin.preissler.co.uk.; };
#       };

  zone "preissler.co.uk" {
    type slave;
    masters { 2A01:618:8009:0:988:B84B:769D:7D96; };
    allow-notify { NominetDSS; };
    file "preissler-signedslave.co.uk";

  // More unsigned and/or signed zones.
  • request-ixfr: As pointed out in the Nominet documentation some BIND clients fall back to incremental transfers and these won't work due to the nature of DNSSEC (or would make signing unnecessarily complicated).
  • transfer-source-v6: Again we have to explicitely set it to the IP address of the signed slave.
  • With this setup you can have signed and/or unsigned zones as well, signed ones will be just slave zones, unsigned ones will be master zones as usual. To make your life easier, keep serving your old unsigned zone and when testing just comment it out and uncomment the signed slave one - and you are good to go (after you have successfully verified your DNSSEC signed zone!)

To get your zone then DNSSEC signed just tell your registrar and they can enable it via their interface for your domain (you won't have access to that interface, only registrars). They will need

  • Key names and the actual secret for your unsigned master and your signed slave. It is crucial here, to use the same names as defined in your config, no "." or anything added. Or you keep getting errors ("TSIG errors" or "unknown key").
  • Go!

Finale: Tests and logs

That's all. Then they see whether your unsigned zone has been transfer successfully and whether it was successfully signed. If both are the case, do first a test whether DNSSEC looks alright:

$ dig @ -b <slave IP as configured> -y [TSIG alg:]<TSIG name>:<TSIG secret> <zone name> SOA
$ dig @ -b <slave IP as configured> -y [TSIG alg:]<TSIG name>:<TSIG secret> <zone name> AXFR

(or use the -k option) and if it looks alright (you will see what I mean) then you can activate in your config the signed slave section for all your shiny-new DNSSEC enabled domains!

To validate your domain via DNSSEC (there are hardly DNSSEC enabled resolvers out there) you go visit http://dnsviz.net/ and you  see the DNSSEC relationship nicely displayed.

And last but not least in your BIND logs you will see usually every day

  1. AXFR of your zone (TSIG unsigned master)
  2. Another AXFR of your zone (why that is, I don't know). (TSIG unsigned master again)
  3. NOTIFY of your signed slave (TSIG signed slave)
  4. And finally some SUCCESS message and statistics.
Show Comments