How to Extract All A and CNAME Records from BIND DNS Server Zone Files Using Command Line Tools


6 views

Managing a BIND DNS server with multiple zone files often requires extracting complete DNS record information for auditing, migration, or troubleshooting purposes. Here are efficient methods to gather all A and CNAME records without manual inspection.

The most reliable approach uses BIND's built-in named-checkzone utility with output formatting:

for zone in $(ls /var/named/*.zone); do
    named-checkzone -k fail -o - $(basename $zone .zone) $zone | \
    awk '/IN A|IN CNAME/ {print $1,$4,$5}'
done

This command:

  • Iterates through all zone files in /var/named
  • Validates each zone's syntax while outputting records
  • Filters for only A and CNAME records
  • Prints hostname, record type, and value

For a faster but less validated approach:

grep -hE 'IN[[:space:]]+(A|CNAME)' /var/named/*.zone | \
awk '{print $1,$4,$5}' | \
sort | uniq

To generate CSV output suitable for spreadsheets:

echo "Host,Type,Value,ZoneFile" > dns_records.csv
for zone in /var/named/*.zone; do
    zone_name=$(basename $zone .zone)
    named-checkzone -k fail -o - $zone_name $zone | \
    awk -v zn="$zone_name" '/IN A|IN CNAME/ {print $1","$4","$5","zn}'
done >> dns_records.csv

For servers with hundreds of zone files, consider parallel processing:

find /var/named -name "*.zone" -print0 | \
xargs -0 -P 8 -I {} sh -c '\
    named-checkzone -k fail -o - $(basename {} .zone) {} | \
    awk '\''/IN A|IN CNAME/ {print $1,$4,$5}'\'' \
    ' > all_dns_records.txt

When managing a BIND DNS server with numerous zone files, manually parsing each file for A and CNAME records becomes impractical. Here's how to automate this process using standard DNS tools and scripting.

If AXFR transfers are enabled, you can retrieve all records for a zone with:

dig @your_dns_server example.com AXFR

However, this requires proper permissions and may not be available in all configurations.

For direct zone file processing, this Bash script recursively searches for zone files and extracts records:

#!/bin/bash
ZONE_PATH="/var/named/zones/"
RECORD_TYPES=("A" "CNAME")

for zone_file in $(find $ZONE_PATH -type f -name "*.db"); do
    echo "Processing $zone_file"
    for record_type in "${RECORD_TYPES[@]}"; do
        grep -E "^[^;].*IN[[:space:]]+$record_type" $zone_file | while read -r line; do
            echo "$zone_file: $line"
        done
    done
done

Combine your extraction with BIND's built-in validation tool:

for zone in $(ls /etc/named/*.zone); do
    zone_name=$(basename $zone .zone)
    named-checkzone $zone_name $zone
    grep -E 'IN[[:space:]]+(A|CNAME)' $zone
done

For more advanced processing, this Python script handles zone files more robustly:

import os
import re

def parse_zone_files(root_path):
    record_pattern = re.compile(r'^([^\s;]+)\s+.*?\s+IN\s+(A|CNAME)\s+(.*)$', re.M)
    for root, _, files in os.walk(root_path):
        for file in files:
            if file.endswith('.db'):
                with open(os.path.join(root, file)) as f:
                    content = f.read()
                    for match in record_pattern.finditer(content):
                        print(f"File: {file} | Record: {match.group(0)}")

parse_zone_files('/var/named/zones')

For servers hosting hundreds of zones, consider:

  • Processing files in parallel with GNU parallel
  • Implementing output filtering to focus on specific record patterns
  • Caching results for subsequent queries