How to List All Authoritative Zones Loaded in BIND DNS Server


2 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