How to List All Authoritative Zones Loaded in BIND DNS Server


24 views

When migrating BIND DNS servers with deeply nested include structures, manually tracing zone declarations becomes impractical. The standard named.conf may contain:

include "zones/primary/*.conf";
include "zones/secondary/legacy.conf";
// include "zones/decommissioned/old.conf"; 

Commented-out entries and recursive includes make traditional file inspection error-prone.

Method 1: Using rndc with Zone Filters

While rndc dumpdb produces excessive output, we can filter for authoritative zones:

rndc dumpdb -all
grep "zone " /var/cache/bind/named_dump.db | 
  grep -v "IN NS" | 
  awk '{print $2}' | 
  sort -u

Method 2: XML Statistics Channel

Enable statistics in named.conf:

statistics-channels {
    inet 127.0.0.1 port 8053;
};

Then query and parse:

curl -s http://localhost:8053/ 2>/dev/null | 
  xmllint --xpath '//zones/zone[@type="primary" or @type="secondary"]/@name' - | 
  sed 's/ name="//g; s/" /\
/g'

Method 3: Direct Memory Inspection (BIND 9.16+)

For modern BIND versions:

rndc zonestatus * | 
  awk '/zone name:/ {print $3}' | 
  grep -v '^[.*]$'

For views or multi-instance setups, specify the view name:

rndc -s dns1.example.com zonestatus internal_view * | 
  grep "zone name:" | 
  cut -d: -f2

Remember to exclude DNSSEC metadata zones:

grep -vE '\.(key|rev|ds)$'

Python script using dnspython:

import dns.query
import dns.message

query = dns.message.make_query('.', 'SOA')
response = dns.query.udp(query, '127.0.0.1')
if response.rcode() == dns.rcode.REFUSED:
    print("Server refused AXFR - try TSIG authentication")

When dealing with large-scale BIND DNS server migrations, administrators often encounter configuration files that resemble spaghetti code - multiple nested includes, commented-out sections, and legacy entries. The challenge is extracting just the currently active authoritative zones from this mess.

While rndc dumpdb provides extensive information, it's not zone-specific. A better approach is:

rndc status | grep "number of zones"

This gives a count, but not the actual zone names. For detailed listing:

rndc zonestatus

When includes make manual inspection difficult, use this recursive grep command:

grep -rh "zone \"" /etc/bind/ | awk '{print $2}' | tr -d \"

For a more structured approach with zone types:

named-checkconf -z /etc/bind/named.conf | grep "zone" | awk '{print $2}'

For complex environments, a Python script can parse the configuration:


import os
import re

def find_zones(config_path):
    zones = set()
    with open(config_path) as f:
        content = f.read()
    
    # Find all includes
    includes = re.findall(r'include\s+"([^"]+)"', content)
    
    # Find zones in main file
    zones.update(re.findall(r'zone\s+"([^"]+)"', content))
    
    # Recursively process includes
    for include in includes:
        if os.path.isfile(include):
            zones.update(find_zones(include))
    
    return sorted(zones)

print("\n".join(find_zones("/etc/bind/named.conf")))

Combine the above with actual runtime verification:

for zone in $(named-checkconf -z /etc/bind/named.conf | grep "zone" | awk '{print $2}'); do
    rndc zonestatus $zone | grep -q "OK" && echo "$zone: ACTIVE" || echo "$zone: INACTIVE"
done