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