BIND isn’t just a DNS server; it’s a distributed database for mapping names to numbers, and its recursive resolver is the part that fetches answers from across the internet for your clients.
Let’s see it in action. Imagine a client on your network asks for www.example.com. Your BIND server, acting as the resolver, doesn’t know the answer. It will then perform these steps:
- Root Servers: It asks one of the root DNS servers (e.g.,
a.root-servers.net) for the IP address of thecomname servers. - TLD Servers: It asks a
.comTLD server for the IP address of theexample.comname servers. - Authoritative Servers: It asks an
example.comauthoritative name server for the IP address ofwww.example.com. - Response: Finally, it receives the IP address and returns it to the client.
This entire process is what we’re setting up.
To configure BIND as a recursive resolver, you’ll primarily be working with the named.conf file (or files included by it), and the options block is your starting point.
options {
directory "/var/named";
recursion yes;
allow-query { localnets; };
forwarders {
8.8.8.8;
8.8.4.4;
};
dnssec-enable yes;
dnssec-validation yes;
};
The recursion yes; line is the core setting that enables BIND to perform recursive lookups on behalf of clients. allow-query { localnets; }; is crucial for security; it restricts who can query your resolver. localnets is a predefined ACL in BIND that typically includes your local network interfaces. You’ll want to define this ACL if you haven’t already, for example:
acl "localnets" { 192.168.1.0/24; 10.0.0.0/8; 127.0.0.1; };
The forwarders block tells your BIND server where to send queries it can’t answer itself. Using public DNS servers like Google’s 8.8.8.8 and 8.8.4.4 is a common practice for simplicity and reliability. If you have your own internal DNS infrastructure, you’d list those servers here instead. dnssec-enable yes; and dnssec-validation yes; are vital for ensuring the integrity and authenticity of DNS responses, protecting against spoofing.
You’ll also need to ensure BIND is running and that its configuration is valid. The command named-checkconf is your best friend here. Run it after making any changes to named.conf:
sudo named-checkconf /etc/named.conf
If it outputs nothing, your syntax is correct. If there are errors, it will point them out. After checking the configuration, you’ll need to reload or restart the BIND service to apply the changes. On systems using systemd:
sudo systemctl reload named
Or, if a reload isn’t sufficient or you prefer a full restart:
sudo systemctl restart named
To test your recursive resolver, you can use dig from a client machine configured to use your BIND server for DNS resolution (or directly query your BIND server if you’re testing from the server itself).
dig @your_bind_server_ip www.cloudflare.com
You should see a "status: NOERROR" in the output, along with the IP addresses for www.cloudflare.com. If you’re using forwarders, the query will hit your BIND server, which then forwards it to 8.8.8.8 (or whichever forwarder you specified), and that server will eventually return the answer.
The allow-query directive is one of the most misunderstood aspects. Many administrators set it too broadly, opening their resolver to become part of a DNS amplification attack. The key is to restrict it to only those IP addresses or networks that need to use your resolver for recursion. localnets is a good start, but for more granular control, you can specify individual IP addresses or larger network blocks.
When BIND performs a recursive query, it doesn’t just ask one root server; it has a list of root hints (usually in a file like /var/named/named.root) and will try multiple root servers if the first one doesn’t respond or provides a referral it can’t follow. This redundancy is why recursion is generally reliable.
The forwarders directive is not mandatory for recursion. If you omit it, BIND will perform full recursion itself, starting from the root hints. Using forwarders offloads the initial iterative queries to other DNS servers, which can sometimes be faster and reduce the load on your own server, especially if your network has high latency to the root servers.
If you’re not using forwarders and want BIND to do the full recursion itself, you’d remove the forwarders block. BIND will then consult its root hints file (named.root) to find the IP addresses of the root DNS servers and begin the iterative process.
Most people don’t realize that BIND’s allow-query directive, when applied to the global options block, affects all zones served by that instance. If you also have authoritative zones configured, clients might be able to query those authoritative zones even if they aren’t allowed to use the recursive resolver. For more specific control, you’d use allow-recursion in the options block and allow-query on individual zone statements.
The next step is often securing your recursive resolver further by preventing it from being used for cache poisoning attacks or by implementing response rate limiting.