BIND Access Control Lists (ACLs) let you define named sets of IP addresses or networks, enabling granular control over who can query your DNS server and what operations they can perform.

Let’s see BIND ACLs in action. Imagine you have a BIND server (named) running on 192.168.1.100 and you want to restrict access to internal clients primarily.

Here’s a snippet from a named.conf file:

acl "internal_clients" {
    192.168.1.0/24;
    10.0.0.0/8;
    localhost;
    localnets;
};

acl "trusted_partners" {
    203.0.113.0/24;
};

options {
    directory "/var/cache/bind";

    allow-query { internal_clients; trusted_partners; };
    // Other options...
};

In this example:

  • We define internal_clients to include our primary internal subnet, another private range, the server itself, and any networks directly attached to the server’s interfaces.
  • We define trusted_partners for a specific external network.
  • The allow-query option in the options block then explicitly permits queries only from clients within either of these ACLs.

This configuration means that if a client from 192.168.1.50 (within internal_clients) queries the server, the query is allowed. If a client from 203.0.113.10 (within trusted_partners) queries, it’s also allowed. However, a query from 198.51.100.20 (not in any defined ACL) would be silently dropped by named.

The problem BIND ACLs solve is moving beyond a simple "allow all" or "deny all" for DNS queries. Without ACLs, you’d either expose your DNS server to the entire internet (risking it being used in DDoS amplification attacks, or revealing internal network structures) or lock yourself out of your own DNS service. ACLs provide a middle ground, allowing you to specify precisely which IP addresses or networks are permitted to interact with your DNS server and for what purposes.

Internally, when named receives a query, it checks the source IP address of the query against the configured allow-query, allow-recursion, and deny-query (and their allow- counterparts) directives. These directives can reference named ACLs. The evaluation is generally top-down and the first match wins. If an IP address matches an ACL, the action associated with that ACL (e.g., allow-query) is applied. If it doesn’t match any explicit allow or deny list, the default behavior is usually to deny.

The exact levers you control are primarily within the named.conf file. You define ACLs using the acl keyword, followed by a name in quotes, and then a block containing a list of IP addresses, CIDR-notation networks, or other defined ACLs. These ACLs can then be referenced in various options and zone specific directives, most commonly:

  • allow-query: Controls who can send any query to the server.
  • allow-recursion: Controls who can perform recursive lookups (i.e., ask the server to query other DNS servers on their behalf). This is crucial for preventing your server from becoming an open resolver.
  • allow-transfer: Controls who can request zone transfers (AXFR/IXFR), typically used for secondary DNS servers.

You can also use deny-query and deny-recursion for explicit blocking, though allow directives often serve the same purpose by only permitting what’s explicitly listed. The order of evaluation matters; a more specific rule (e.g., a deny rule for a single IP) might need to appear before a broader allow rule if there’s overlap.

A common pitfall is forgetting to include localhost or localnets in your allow-query or allow-recursion ACLs when trying to restrict external access. This can lead to the DNS server itself being unable to resolve names for its own operations or for local services that rely on it. For example, if you have a zone file that references another hostname within your internal network, and your named process tries to look up that hostname to validate it, it might fail if localhost isn’t permitted.

The next concept you’ll likely encounter is using these same ACLs to control zone transfers, which is critical for securing your authoritative DNS data.

Want structured learning?

Take the full Bind course →