bind9
Installation
SKILL.md
Identity
- Unit:
named.service(Debian/Ubuntu) orbind9.service(newer Debian) - Config (Debian/Ubuntu):
/etc/bind/named.conf,/etc/bind/named.conf.options,/etc/bind/named.conf.local,/etc/bind/named.conf.default-zones - Config (RHEL/Fedora):
/etc/named.conf,/etc/named/(included zone configs) - Zone dir (Debian):
/var/lib/bind/(dynamic/slave zones),/etc/bind/(static master zones) - Zone dir (RHEL):
/var/named/ - Logs:
journalctl -u named/journalctl -u bind9,/var/log/named/(if configured),journalctl -u named -ffor live - Runtime control socket:
rndccommunicates withnamedvia port 953 (loopback only by default) - Distro install:
apt install bind9 bind9utils/dnf install bind bind-utils
Key Operations
| Operation | Command |
|---|---|
| Service status | systemctl status named (RHEL) or systemctl status bind9 (Debian) |
| Reload all zones (no restart) | rndc reload |
| Reload a specific zone | rndc reload example.com |
| Check entire named.conf syntax | named-checkconf /etc/bind/named.conf (Debian) or named-checkconf /etc/named.conf (RHEL) |
| Check a specific zone file | named-checkzone example.com /etc/bind/db.example.com |
| Flush entire cache | rndc flush |
| Flush cache for one domain | rndc flushname example.com |
| View statistics | rndc stats → writes to /var/named/data/named_stats.txt |
| Dump current cache | rndc dumpdb -cache → writes to /var/named/data/named_dump.db |
| Stop accepting queries | rndc stop (graceful shutdown) |
| Reload config without restart | rndc reconfig (picks up new/removed zones; does not reload existing zone data) |
| Query the local server | dig @localhost example.com A |
| Query with full trace | dig +trace example.com A |
| Reverse lookup test | dig @localhost -x 192.168.1.10 |
| Check DNSSEC validation | dig @localhost example.com A +dnssec |
| Sign a zone (DNSSEC) | dnssec-keygen -a ECDSAP256SHA256 -n ZONE example.com && dnssec-signzone -A -3 $(head -c 6 /dev/urandom | base64) -N INCREMENT -o example.com -t db.example.com |
| Show active zones | rndc zonestatus example.com |
Expected Ports
- 53/udp — Standard DNS queries (all responses up to 512 bytes; EDNS0 allows larger)
- 53/tcp — Zone transfers, large responses, and EDNS0 overflow fallback
- 953/tcp —
rndccontrol channel (loopback only; never expose externally)
Verify: ss -ulnp | grep :53 and ss -tlnp | grep :53
Firewall (ufw): sudo ufw allow 53/udp && sudo ufw allow 53/tcp
Firewall (firewalld): sudo firewall-cmd --permanent --add-service=dns && sudo firewall-cmd --reload
Health Checks
systemctl is-active named(orbind9) →activenamed-checkconf /etc/bind/named.conf 2>&1→ no output (silent = success)dig @localhost . SOA +short→ returns root zone SOA (confirms named is answering)dig @localhost example.com A +short→ returns expected IP (confirms zone is loaded)
Common Failures
| Symptom | Likely cause | Check / Fix |
|---|---|---|
Zone not loading; SERVFAIL for zone records |
Syntax error in zone file | named-checkzone example.com /path/to/db.example.com — shows exact line and error |
SERVFAIL for delegated subdomains |
Missing or wrong NS delegation in parent zone | Verify NS and glue records at parent; check with dig NS sub.example.com @parent-ns |
REFUSED on queries from clients |
allow-query ACL too restrictive |
Add client subnet to allow-query in named.conf.options; reload |
| Open recursive resolver (security risk) | recursion yes with no allow-recursion ACL |
Set allow-recursion { trusted-clients; }; or allow-recursion { none; }; for authoritative-only |
| Zone transfer denied to secondary | allow-transfer not set or wrong IP |
Add secondary IP to allow-transfer in the primary zone definition; reload |
| Slaves not picking up changes | Serial number not incremented | Increment SOA serial (YYYYMMDDNN format); run rndc reload on primary; secondary will NOTIFY and re-transfer |
| AppArmor blocking zone file reads (Debian) | Zone files outside /etc/bind/ or /var/lib/bind/ |
Move zone files to an AppArmor-allowed path, or add a rule to /etc/apparmor.d/usr.sbin.named |
| SELinux blocking named (RHEL) | Zone files have wrong SELinux context | chcon -t named_zone_t /var/named/db.example.com or restorecon -v /var/named/db.example.com |
rndc: connect failed: 127.0.0.1#953: connection refused |
named not running, or rndc key mismatch | Check systemctl status named; verify /etc/bind/rndc.key matches controls block in named.conf |
transfer of 'example.com' from x.x.x.x: Transfer completed: 0 messages |
Empty zone transfer | Check allow-transfer on primary; verify secondary's masters IP matches primary |
| named starts but ignores config changes | rndc reconfig vs rndc reload confusion |
reconfig adds/removes zones; reload re-reads zone data — use rndc reload after zone file edits |
Pain Points
- Serial number format: The YYYYMMDDNN convention (e.g.,
2024031501) is only a convention — named treats it as a plain 32-bit integer. Slaves compare serials using RFC 1982 sequence arithmetic; never decrement a serial or jump it forward by more than 2^31. If you forget to increment,rndc reloadloads the new file locally but slaves never NOTIFY because the serial hasn't changed. allow-recursionvsallow-querysecurity:allow-querycontrols who can send queries at all;allow-recursioncontrols who can use the server as a recursive resolver. An authoritative-only server should setrecursion noorallow-recursion { none; };— leaving recursion open to the internet creates an open resolver usable for DNS amplification attacks.- Debian vs RHEL config layout: Debian splits named.conf into
named.conf.options(global options),named.conf.local(your zones), andnamed.conf.default-zones(root hints, localhost). RHEL uses a single/etc/named.conf. Include-based edits must target the correct file. rndc reloadvsrndc reconfigvs full restart:rndc reloadre-reads zone files for all currently configured zones.rndc reconfigonly picks up zone additions and removals from named.conf — it does not re-read zone file data. A fullsystemctl restart namedis rarely needed and causes a brief outage; preferrndc reload.- DNSSEC complexity: Key management (ZSK/KSK rotation), signing, NSEC vs NSEC3 choice, DS record submission to parent zone, and key rollover timing are all manual steps unless using automated DNSSEC (
dnssec-policyin BIND 9.16+). A zone with stale DNSSEC signatures causes SERVFAIL for all DNSSEC-validating resolvers. - Forwarders vs recursive resolution:
forwardersin the options block makes named forward all recursive queries to the listed servers instead of resolving from root. This is appropriate for internal resolvers that should use corporate DNS. For a public authoritative server,forwardersis usually wrong andrecursion nois the right choice.
References
See references/ for:
named.conf.annotated— complete named.conf with every directive explained, plus an annotated zone filecommon-patterns.md— authoritative server, recursive resolver, split-horizon views, zone transfers, DNSSEC, and moredocs.md— official ISC BIND documentation links
Related skills