Level 2

BIND DNS server: named.conf and zone management

Maximilian B. 9 min read 15 views

BIND DNS server is the most widely deployed authoritative and recursive DNS server on the internet, powering the majority of Linux-based name resolution infrastructure. If you administer Linux servers in production, you will encounter BIND9 and its named.conf configuration sooner or later, whether running your own DNS zones or debugging resolution problems caused by someone else's setup. This article covers the architecture of BIND 9.18+, the structure of named.conf, zone file syntax, zone transfers, TSIG authentication, and operational tools like rndc and the named-check utilities.

BIND9 Architecture and How the named Daemon Works

BIND DNS server: named.conf and zone management visual summary diagram
Visual summary of the key concepts in this guide.

The named daemon is the BIND DNS server process that answers DNS queries. It reads its configuration from /etc/named.conf (RHEL/Fedora) or /etc/bind/named.conf (Debian/Ubuntu), loads zone data into memory, and listens on configured interfaces.

BIND9 architecture diagram showing the named daemon at the center reading from named.conf and zone files, receiving queries from internal clients (recursion allowed) and external clients (recursion denied) via split-horizon DNS views, transferring zones to secondary servers via AXFR/IXFR with TSIG authentication, forwarding recursive queries to upstream resolvers, being controlled by rndc over TCP 953, and writing to logging channels

BIND 9.18 (the current LTS branch shipped with Debian 13.3, Ubuntu 24.04, and RHEL 10.1) introduced several defaults worth knowing:

  • DNSSEC validation is enabled by default (dnssec-validation auto;).
  • The allow-recursion directive defaults to localhost and localnets only, so a fresh install will not act as an open resolver.
  • The old dnssec-enable option was removed; DNSSEC support is always compiled in.

On systemd-based distributions, BIND runs as the named.service unit. On Debian/Ubuntu the package is bind9; on RHEL/Fedora it is bind.

# Install on Debian/Ubuntu
sudo apt install bind9 bind9-utils bind9-dnsutils

# Install on RHEL 10 / Fedora 43
sudo dnf install bind bind-utils

named.conf Structure: Options, Zone, ACL, and View Blocks

The main named.conf configuration file is modular. On Debian systems it uses include directives to split into named.conf.options, named.conf.local, and named.conf.default-zones. On RHEL the default is a single /etc/named.conf. Either approach works; the syntax is identical.

The options block

This controls global server behavior. A production-ready options block looks like this:

options {
    directory "/var/cache/bind";           # Working directory for zone files
    listen-on { 127.0.0.1; 10.0.1.5; };   # Only bind to specific IPs
    listen-on-v6 { ::1; };
    allow-recursion { 10.0.0.0/8; 127.0.0.1; };
    forwarders { 9.9.9.9; 149.112.112.112; };  # Quad9 as upstream
    forward only;                          # Do not fall back to root hints
    dnssec-validation auto;
    recursion yes;
    max-cache-size 256m;
    version "not disclosed";               # Hide BIND version from queries
};

Setting version "not disclosed"; prevents attackers from fingerprinting your BIND release via dig @server version.bind chaos txt. This is an important DNS server security hardening step that every production deployment should include.

ACLs (Access Control Lists)

Access control lists let you name groups of IP addresses and reference them throughout the config:

acl "internal" {
    10.0.0.0/8;
    172.16.0.0/12;
    192.168.0.0/16;
    localhost;
};

acl "dmz-servers" {
    10.0.2.10;
    10.0.2.11;
};

Then use them: allow-recursion { "internal"; };. This is cleaner than scattering CIDR blocks through multiple directives. Well-structured ACLs also tie in with your broader Linux networking and IP subnet design.

Zone declarations

Each DNS zone block tells named where to find the data and what role it plays (primary or secondary):

zone "example.com" {
    type primary;
    file "zones/db.example.com";
    allow-transfer { key "xfer-key"; };    # Only allow TSIG-authenticated transfers
    also-notify { 10.0.1.6; };             # Push notifications to secondary
};

zone "example.com" {
    type secondary;
    file "zones/db.example.com";
    primaries { 10.0.1.5 key "xfer-key"; };
};

Note: BIND 9.18 accepts both master/slave and primary/secondary keywords but the old terms are deprecated and will be removed in a future release. Use the new terms.

Views for split-horizon DNS

Split-horizon DNS lets a single BIND server return different answers depending on the source of the query. This is common when internal clients should resolve to private IPs while external clients get public addresses:

view "internal" {
    match-clients { "internal"; };
    recursion yes;

    zone "example.com" {
        type primary;
        file "zones/db.example.com.internal";
    };
};

view "external" {
    match-clients { any; };
    recursion no;

    zone "example.com" {
        type primary;
        file "zones/db.example.com.external";
    };
};

When using views, every zone (including the root hints and localhost zones) must be inside a view block. You cannot mix view and non-view zones in the same configuration.

DNS Zone File Format and Record Types

A DNS zone file starts with a SOA record and NS records, followed by the actual resource records. Here is a complete forward zone:

$TTL 3600
@   IN  SOA  ns1.example.com. admin.example.com. (
            2026022801  ; serial — YYYYMMDDNN format
            3600        ; refresh (1 hour)
            900         ; retry (15 minutes)
            1209600     ; expire (2 weeks)
            300         ; negative cache TTL (5 minutes)
)

; Name servers
        IN  NS      ns1.example.com.
        IN  NS      ns2.example.com.

; A and AAAA records
ns1     IN  A       10.0.1.5
ns2     IN  A       10.0.1.6
@       IN  A       93.184.216.34
@       IN  AAAA    2606:2800:220:1:248:1893:25c8:1946
www     IN  CNAME   example.com.

; Mail
@       IN  MX  10  mail.example.com.
@       IN  MX  20  backup-mail.example.com.
mail    IN  A       10.0.1.20

; SPF and DKIM
@       IN  TXT     "v=spf1 mx ip4:10.0.1.20 -all"
dkim._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCS..."

; Service discovery
_sip._tcp  IN  SRV  10 60 5060 sip.example.com.

The MX records above are critical for mail delivery. If you are building out a complete mail infrastructure, the zone file must align with your email architecture and MTA/MDA setup.

Common zone file mistakes to avoid

Even experienced administrators encounter these zone file errors in production:

  • Missing trailing dot on FQDNs: Writing ns1.example.com instead of ns1.example.com. causes BIND to append the zone origin, resulting in ns1.example.com.example.com. — a record that will never resolve.
  • Forgetting to increment the serial: Secondary servers compare serials during zone transfers. If the serial has not changed, the secondary assumes the zone is unchanged and skips the transfer entirely.
  • TTL values too low or too high: A 60-second TTL generates heavy query load on your authoritative servers. A 86400-second (1-day) TTL means DNS changes take 24 hours to propagate. The $TTL directive sets the default for all records; override it per-record when needed.

Reverse zone

Reverse DNS zones map IP addresses back to hostnames using PTR records. For the 10.0.1.0/24 network:

$TTL 3600
@   IN  SOA  ns1.example.com. admin.example.com. (
            2026022801 3600 900 1209600 300 )

    IN  NS   ns1.example.com.
    IN  NS   ns2.example.com.

5   IN  PTR  ns1.example.com.
6   IN  PTR  ns2.example.com.
20  IN  PTR  mail.example.com.

The zone name for this file would be 1.0.10.in-addr.arpa. The file is declared in named.conf like any other zone. Proper reverse DNS is essential for mail servers — many receiving MTAs reject connections from IP addresses without valid PTR records.

Zone Transfers, TSIG Authentication, and rndc Management

AXFR and IXFR zone transfers

A full zone transfer (AXFR) copies the entire zone from primary to secondary. An incremental transfer (IXFR) sends only the changes since the secondary's last known serial. BIND negotiates IXFR automatically when journal files exist. You trigger an immediate transfer on the secondary with:

rndc retransfer example.com

TSIG authentication for secure zone transfers

Zone transfers should always be authenticated with TSIG keys to prevent unauthorized data exfiltration. Generate a key:

# Generate TSIG key using HMAC-SHA256
tsig-keygen -a hmac-sha256 xfer-key > /etc/bind/keys/xfer-key.conf

The generated file looks like:

key "xfer-key" {
    algorithm hmac-sha256;
    secret "r3aLBas364SeCr3tH3rE=";
};

Include this file on both primary and secondary, then reference the key in zone transfer directives as shown earlier. TSIG authentication is part of a broader server hardening strategy — see also nftables and firewalld security practices for securing the network layer around your DNS infrastructure.

rndc commands for BIND management

The rndc utility communicates with named over a control channel (TCP 953 by default). Common operations:

# Reload all zones
rndc reload

# Reload a specific zone
rndc reload example.com

# Freeze zone for manual editing, then thaw
rndc freeze example.com
# ... edit zone file, increment serial ...
rndc thaw example.com

# Flush resolver cache
rndc flush

# Dump statistics
rndc stats    # writes to /var/cache/bind/named.stats

# Show server status
rndc status

BIND DNS Validation Tools and Logging Configuration

named-checkconf and named-checkzone

Always validate before reloading:

# Check configuration syntax
named-checkconf /etc/bind/named.conf

# Validate a zone file
named-checkzone example.com /var/cache/bind/zones/db.example.com
# Output: zone example.com/IN: loaded serial 2026022801 — OK

Run these in your deployment pipeline. A single misplaced semicolon in named.conf will prevent named from starting, which takes your DNS offline.

Logging channels

BIND's default logging goes to syslog, which mixes DNS events with everything else. Configure dedicated log files for easier troubleshooting:

logging {
    channel queries_log {
        file "/var/log/named/queries.log" versions 5 size 50m;
        severity info;
        print-time yes;
        print-category yes;
    };
    channel xfer_log {
        file "/var/log/named/xfer.log" versions 3 size 10m;
        severity info;
        print-time yes;
    };
    category queries { queries_log; };
    category xfer-in { xfer_log; };
    category xfer-out { xfer_log; };
};

Create the log directory and set ownership before starting named:

sudo mkdir -p /var/log/named
sudo chown bind:bind /var/log/named   # 'named' user on RHEL

Enabling query logging in production generates enormous log volumes. On a busy recursive resolver, you can produce gigabytes per hour. Only enable it for targeted debugging, then disable it.

BIND DNS Server Quick Reference

Task Command / Directive
Install BIND (Debian) sudo apt install bind9 bind9-utils
Install BIND (RHEL/Fedora) sudo dnf install bind bind-utils
Check config syntax named-checkconf /etc/bind/named.conf
Validate zone file named-checkzone example.com db.example.com
Reload all zones rndc reload
Reload one zone rndc reload example.com
Freeze zone for editing rndc freeze example.com
Thaw after editing rndc thaw example.com
Flush cache rndc flush
Generate TSIG key tsig-keygen -a hmac-sha256 keyname
Force zone transfer rndc retransfer example.com
Query with dig dig @10.0.1.5 example.com A +short
Test zone transfer dig @10.0.1.5 example.com AXFR
Hide BIND version version "not disclosed"; in options

Summary

BIND9 DNS server configuration comes down to a clean named.conf with well-defined ACLs, proper zone declarations with correct SOA serials, and TSIG-authenticated zone transfers between primary and secondary servers. Use named-checkconf and named-checkzone before every reload to catch syntax errors early. For environments where internal and external clients need different answers, split-horizon DNS views give you separate responses without running multiple servers. Keep query logging off in production unless you are actively debugging. And always increment the serial number when editing zone files — a forgotten serial increment is one of the most common causes of secondaries serving stale data. Once your DNS zones are correctly configured and secured with TSIG, you can extend your infrastructure with DNSSEC zone signing and chain of trust to protect DNS integrity end to end.

Share this article
X / Twitter LinkedIn Reddit