BIND9 Authoritative DNS Server
Deploy and configure BIND9 authoritative DNS server with zones, records, DNSSEC, and zone transfers
What is BIND9?
BIND9 (Berkeley Internet Name Domain) is the most widely used open-source authoritative DNS server. It's production-ready, highly configurable, and supports advanced features like DNSSEC, zone transfers, and dynamic DNS updates. BIND9 is ideal for hosting multiple domains and managing DNS infrastructure at scale.
Installation on Ubuntu/Debian
sudo apt update
sudo apt install bind9 bind9utils bind9-doc dnsutilsVerify installation:
named -v
# BIND 9.18.x (Ubuntu)Basic BIND9 Configuration
Main Configuration File
Edit /etc/bind/named.conf.options:
options {
# Directory containing zone files
directory "/var/lib/bind";
# Listen on all interfaces (change if needed)
listen-on { any; };
listen-on-v6 { any; };
# Allow DNS queries from anywhere (restrict if needed)
allow-query { any; };
# Disable recursive queries (authoritative only)
recursion no;
# Enable DNSSEC validation
dnssec-validation auto;
# Forwarders (optional, for fallback)
# forwarders {
# 8.8.8.8;
# 8.8.4.4;
# };
# Transfer settings
allow-transfer {
192.168.1.101; # Secondary nameserver IP
};
# Response policy zone (optional, for DNS filtering)
# response-policy { zone "rpz.example.com"; };
# Query logging (disable in production for performance)
# querylog yes;
# Rate limiting
rate-limit {
responses-per-second 10;
window 1;
};
};
# Logging configuration (optional)
logging {
channel default_log {
file "/var/log/bind/bind.log" versions 3 size 5m;
severity dynamic;
print-time yes;
};
category default { default_log; };
};Zone Configuration
Edit /etc/bind/named.conf.local:
# Primary zone for example.com
zone "example.com" {
type primary;
file "/etc/bind/zones/db.example.com";
allow-transfer { 192.168.1.101; };
};
# Reverse zone for PTR records (192.168.1.x)
zone "1.168.192.in-addr.arpa" {
type primary;
file "/etc/bind/zones/db.192.168.1";
};
# Secondary zone (slave) - read-only copy from primary
zone "example.org" {
type secondary;
primaries { 192.168.1.100; };
file "/etc/bind/zones/db.example.org";
};Create Zone Files
Forward Zone File
Create /etc/bind/zones/db.example.com:
; Zone file for example.com
$ORIGIN example.com.
$TTL 3600
; SOA (Start of Authority) record
@ IN SOA ns1.example.com. admin.example.com. (
2024032801 ; Serial (YYYYMMDDNN format)
3600 ; Refresh (1 hour)
1800 ; Retry (30 minutes)
604800 ; Expire (7 days)
86400 ; Minimum TTL (24 hours)
)
; Nameserver records
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
; Nameserver A records
ns1 IN A 192.168.1.100
ns2 IN A 192.168.1.101
; MX records (mail servers)
@ IN MX 10 mail.example.com.
@ IN MX 20 mail2.example.com.
; A records
@ IN A 203.0.113.10
www IN A 203.0.113.10
mail IN A 203.0.113.11
mail2 IN A 203.0.113.12
; AAAA records (IPv6)
@ IN AAAA 2001:db8::1
www IN AAAA 2001:db8::1
; CNAME records
blog IN CNAME www.example.com.
ftp IN CNAME www.example.com.
; TXT records
@ IN TXT "v=spf1 mx -all"
_acme-challenge IN TXT "verification-code-here"
; SRV records (optional)
_sip._tcp IN SRV 10 60 5060 sipserver.example.com.Set proper permissions:
sudo chown bind:bind /etc/bind/zones/db.example.com
sudo chmod 644 /etc/bind/zones/db.example.comReverse Zone File (PTR Records)
Create /etc/bind/zones/db.192.168.1:
; Reverse zone for 192.168.1.0/24
$ORIGIN 1.168.192.in-addr.arpa.
$TTL 3600
; SOA record
@ IN SOA ns1.example.com. admin.example.com. (
2024032801
3600
1800
604800
86400
)
; Nameserver records
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
; PTR records
100 IN PTR ns1.example.com.
101 IN PTR ns2.example.com.
10 IN PTR www.example.com.
11 IN PTR mail.example.com.
12 IN PTR mail2.example.com.Validate Configuration
Check syntax before loading:
# Check main configuration
sudo named-checkconf /etc/bind/named.conf
# Check zone file syntax
sudo named-checkzone example.com /etc/bind/zones/db.example.com
# zone example.com/IN: loaded serial 2024032801
# OK
# Check reverse zone
sudo named-checkzone 1.168.192.in-addr.arpa /etc/bind/zones/db.192.168.1Start and Reload BIND9
# Start the service
sudo systemctl start bind9
sudo systemctl enable bind9
# Check status
sudo systemctl status bind9
# Reload configuration (without restart)
sudo rndc reload
# Reload specific zone
sudo rndc reload example.com
# Reload all zones
sudo rndc reconfigQuery Your DNS Server
Test locally:
nslookup www.example.com localhost
dig @localhost www.example.com
# Query with verbose output
dig +trace @localhost www.example.com
# Query specific record type
dig @localhost example.com MX
dig @localhost example.com TXTTest from remote:
dig @ns1.example.com www.example.comSecondary (Slave) Zone Setup
On secondary nameserver, configure /etc/bind/named.conf.local:
zone "example.com" {
type secondary;
primaries { 192.168.1.100; };
file "/var/lib/bind/zones/db.example.com";
};The secondary server will automatically download the zone from primary via zone transfer (AXFR).
Verify zone transfer:
sudo systemctl restart bind9
ls -la /var/lib/bind/zones/Allow Zone Transfers
In primary server's /etc/bind/named.conf.local, restrict transfers:
zone "example.com" {
type primary;
file "/etc/bind/zones/db.example.com";
# Only allow transfers to secondary nameserver
allow-transfer {
192.168.1.101; ; Secondary nameserver
192.168.1.102; ; Another secondary (if needed)
};
};Test zone transfer from secondary:
dig @ns1.example.com example.com AXFRDNSSEC Basics
Generate DNSSEC Keys
cd /etc/bind/zones
# Generate KSK (Key Signing Key)
sudo dnssec-keygen -a ECDSAP256SHA256 -f KSK example.com
# Generate ZSK (Zone Signing Key)
sudo dnssec-keygen -a ECDSAP256SHA256 example.com
# Change ownership
sudo chown bind:bind K*Sign the Zone
sudo dnssec-signzone -A -3 $(head -c 1000 /dev/urandom | md5sum | cut -b 1-16) \
-N INCREMENT -o example.com -t -x example.com.key \
db.example.com Kexample.com*.key
# This creates db.example.com.signedLoad Signed Zone
Edit /etc/bind/named.conf.local:
zone "example.com" {
type primary;
file "/etc/bind/zones/db.example.com.signed";
};Reload BIND:
sudo rndc reloadVerify DNSSEC:
dig +dnssec www.example.com
# Should show RRSIG recordsFirewall Configuration
Allow DNS queries through firewall:
# UFW
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
# iptables
sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 53 -j ACCEPTRestrict zone transfers to secondary nameserver only:
sudo iptables -A INPUT -p tcp --dport 53 -s 192.168.1.101 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 53 -j DROPMonitoring and Logs
View BIND logs:
tail -f /var/log/syslog | grep named
# Or if using custom log file
tail -f /var/log/bind/bind.logMonitor statistics:
rndc stats
# Writes to /var/log/bind/named.statsCheck zone transfers:
rndc zonestatus example.comDynamic DNS (DDNS)
Allow dynamic updates from specific IP:
zone "example.com" {
type primary;
file "/etc/bind/zones/db.example.com";
allow-update { 203.0.113.50; };
};Generate TSIG key for authentication:
tsig-keygen -a hmac-sha256 example.com.keyAlternatives to BIND9
For simpler setups, consider these alternatives:
- PowerDNS: More modern, better performance, easier API integration
- CoreDNS: Cloud-native, Kubernetes-friendly, plugin-based architecture
- Knot DNS: High-performance, DNSSEC support, modern codebase
- NSD: Lightweight authoritative-only server, suitable for small deployments
BIND9 remains the industry standard for flexibility and feature completeness.
Common Tasks
Add a New Subdomain
Edit zone file and increment SOA serial:
subdomain IN A 203.0.113.20
www.subdomain IN CNAME subdomain.example.com.Reload zone:
sudo rndc reload example.comUpdate Zone Serial
Increment serial in SOA record (use YYYYMMDDNN format):
; Before: 2024032801
; After: 2024032802Reload and check propagation:
sudo rndc reload example.com
dig +short NS example.com @ns1.example.comDelete a Record
Remove from zone file and reload:
sudo nano /etc/bind/zones/db.example.com
# Remove old record, increment serial
sudo rndc reload example.comTroubleshooting
Zone won't load
Check syntax errors:
sudo named-checkzone example.com /etc/bind/zones/db.example.com
# Error output shows line numbers and issuesSecondary zone not transferring
Verify network connectivity:
telnet 192.168.1.100 53
dig @192.168.1.100 example.com AXFRCheck BIND logs for transfer errors:
tail -f /var/log/syslog | grep "example.com"DNS queries slow or timing out
Check for query logging overhead:
sudo rndc querylog off
sudo rndc reloadMonitor BIND memory usage:
ps aux | grep namedIncrease cache sizes in named.conf.options if needed.