BIND9: Combining key and ACL for allow-update

Alcs are first match. If you exclude the addresses you want, you can reject all non matching addresses using any; then check that the key matches.

   allow-update { !{ !allowed; any; }; key keyname; };

Ugly answer #1

You can do this only if you are willing to be creative, ugly and brute altogether.

To allow updates only from 1.2.3.0/24 having key dns1.example.com.

acl “mix-match” {
! 128.0.0.0/1;
! 64.0.0.0/2
! 32.0.0.0/3
! 16.0.0.0/4
! 8.0.0.0/5
! 4.0.0.0/6
! 2.0.0.0/7
! 0.0.0.0/8     //0 instead of 1 since bit is set in the desired network
! 1.128.0.0/9
! 1.64.0.0/10
! 1.32.0.0/11
! 1.16.0.0/12
! 1.8.0.0/13
! 1.4.0.0/14
! 1.0.0.0/15    //0 instead of 2 since bit is set in the desired network
! 1.3.0.0/16    //1-st bit = 1: we DENY hosts with 1.3.0.0/16 but allow 1.2.0.0/16
! 1.2.128.0/17
! 1.2.64.0/18
! 1.2.32.0/19
! 1.2.16.0/20
! 1.2.8.0/21
! 1.2.4.0/22
! 1.2.0.0/23    //0 instead of 2 since bit is set in the desired network
! 1.2.2.0/24    //1-st bit = 9: we DENY hosts with 1.2.2.0/24 but allow 1.2.3.0/24

key dns1.example.com.;
};

How to do that bitwise math:

  1. For /X subnet you need X rows.
  2. Convert subnet IP into binary form.
  3. You start with 1-st bit - if allowed subnet have this bit set you deny rule will have it clean, and if the bit is 0 in the allowed subnet then your rule will deny that bit set.
  4. For rule #N, N-1 first bits are SAME as in the desired subnet mask, bit N is as described in step 3.

I did not actually try, but should work.

If you have multiple allowed subnets, I wish you a good luck.

For the purpose of this answer, I'm glad IPv6 isn't widely deployed yet. :)

Ugly answer #2

Setup separate stealth (i.e. not listed as NS) primary master nameserver, in it's firewall rules allow packets only from "allowed" subnet and from it's slave nameservers. On this stealth, allow updates with the key alone. Configure slaves to get zone data via AXFR/IXFR and NOTIFY. And don't forget to disable update forwarding on the slaves.

Once you did it either ugly way, keep in mind that anybody from anywhere can spoof source address in that UDP DNS update packet, which makes all those efforts completely pointless. (Though you can disable UDP to make the efforts slightly less pointless).