Knowledge Base ISC Main Website Ask a Question/Contact ISC
Using Access Control Lists (ACLs) with both addresses and keys
Author: Evan Hunt Reference Number: AA-00723 Views: 9548 Created: 2012-07-18 20:16 Last Updated: 2017-07-03 14:00 100 Rating/ 2 Voters


How can I configure allow-update to permit updates, only if BOTH of the following are true:

  • They hold the secret key (TSIG)
  • They're in the 'permitted' subnet


Here's the long version:
acl address_allow { 10/8; };
acl address_reject { !address_allow; any; };
allow-update { !address_reject; key "...."; };

And now in shorthand:

allow-update { !{!10/8;any;}; key update-key; };

Doesn't this permit any clients on the 10/8 network?

Intuitively, by (mistakenly) attempting to apply Boolean logic (despite the lack of an AND operator in BIND ACLs), you might think that it does, but it doesn't.  What it actually says is 'deny anyone who isn't in subnet 10/8', and then 'allow anyone using this key'.

ACLs aren't boolean.  The ACL elements are processed in order (from left to right) and each ACL element has three possible results instead of two:

  • match and accept
  • match and reject
  • no match (which means "continue processing")

When an ordinary ACL element matches and is negated (for example, the element is "!10/8;" and the address is that means "match and reject".  But if the match is inside of a *nested* ACL, then it's treated differently.  A negative result means "the nested ACL didn't match"--and so you continue processing.

Remember that a 'match' inside a nested ACL is treated differently to a match of an ordinary ACL element.

The point explained immediately above this information box is significant and important, hence the repetition with emphasis!

Therefore if you're checking address A against an ACL of one of the following
forms, these will be the results:

    {     A;    B; }   == A is allowed, accept immediately
    {  {  A; }; B; }   == A is allowed, accept immediately
    {    !A;    B; }   == A is forbidden, reject immediately
    { !{  A; }; B; }   == A is forbidden, reject immediately
    {  { !A; }; B; }   == A matched but was negated, try element B
    { !{ !A; }; B; }   == A matched but was negated, try element B

Those last two lines there are confusingly similar (and, as written, useless).  The difference is what happens if you're checking an address other than A, and something else in the nested ACL matches it.

    {  { !A; any; }; B; }  == any address other than A is accepted at once,
                              but A is only accepted if B matches too.
                              boolean translation: ((not A) or (A and B))

    { !{ !A; any; }; B; }  == any address other than A is *rejected* at once,
                              but A is accepted as long as B matches too.
                              boolean translation: (A and B)

Hope that's helpful!

© 2001-2018 Internet Systems Consortium

For assistance with problems and questions for which you have not been able to find an answer in our Knowledge Base, we recommend searching our community mailing list archives and/or posting your question there (you will need to register there first for your posts to be accepted). The bind-users and the dhcp-users lists particularly have a long-standing and active membership.

ISC relies on the financial support of the community to fund the development of its open source software products. If you would like to support future product evolution and maintenance as well having peace of mind knowing that our team of experts are poised to provide you with individual technical assistance whenever you call upon them, then please consider our Professional Subscription Support services - details can be found on our main website.

  • There is no feedback for this article
Quick Jump Menu