Comprehensive configuration guidance for BIND DNS server with detailed examples for server settings, zones, ACLs, DNSSEC, and advanced features. This guide covers all aspects of configuring BIND for production environments.
BIND configuration is typically split across multiple files:
/etc/bind/named.conf (Debian/Ubuntu) or /etc/named.conf (RHEL)/etc/bind/named.conf.options (Debian/Ubuntu) or included in main conf (RHEL)/etc/bind/named.conf.local (Debian/Ubuntu)/etc/bind/named.conf.default-zones (Debian/Ubuntu)/var/lib/bind/ (Debian/Ubuntu) or /var/named/ (RHEL)The main configuration file typically includes:
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
Edit /etc/bind/named.conf.options (Debian/Ubuntu) or main config file (RHEL):
options {
// Directory where zone files are stored
directory "/var/cache/bind"; // Debian/Ubuntu
// directory "/var/named"; // RHEL
// Listen on specific interfaces (recommended for security)
listen-on port 53 { 127.0.0.1; YOUR_SERVER_IP; };
listen-on-v6 port 53 { ::1; };
// Allow queries from specific networks
allow-query { localhost; 192.168.0.0/16; 10.0.0.0/8; };
// Recursion settings
recursion yes;
allow-recursion { localhost; 192.168.0.0/16; 10.0.0.0/8; };
// Forwarders (for recursive queries)
forwarders {
8.8.8.8;
8.8.4.4;
};
// DNSSEC validation
dnssec-enable yes;
dnssec-validation auto;
// Logging
pid-file "/var/run/named/named.pid";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
// Security
auth-nxdomain no; // conform to RFC1035
empty-zones-enable no; // Disable empty zones for private networks
listen-on-v6 { none; }; // Disable IPv6 if not needed
};
Add to /etc/bind/named.conf.local (Debian/Ubuntu) or main config (RHEL):
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-transfer { 192.168.1.10; 192.168.1.11; }; // Slave servers
};
zone "1.168.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192.168.1";
};
zone "internal.company.com" {
type forward;
forward only;
forwarders { 10.0.0.10; 10.0.0.11; };
};
For secondary DNS servers:
zone "example.com" {
type slave;
file "slaves/db.example.com";
masters { 192.168.1.10; }; // Primary server IP
};
Create /etc/bind/db.example.com:
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
2026021401 ; Serial (YYYYMMDDNN format)
3600 ; Refresh
1800 ; Retry
1209600 ; Expire
86400 ) ; Negative Cache TTL
; Name servers
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
; A records
@ IN A 192.168.1.10
ns1 IN A 192.168.1.10
ns2 IN A 192.168.1.11
www IN A 192.168.1.20
mail IN A 192.168.1.30
; CNAME records
ftp IN CNAME www.example.com.
; MX records
@ IN MX 10 mail.example.com.
; TXT records (for SPF, DKIM, etc.)
@ IN TXT "v=spf1 mx ~all"
# Debian/Ubuntu
sudo chown bind:bind /etc/bind/db.example.com
sudo chmod 644 /etc/bind/db.example.com
# RHEL
sudo chown named:named /var/named/db.example.com
sudo chmod 644 /var/named/db.example.com
Add to named.conf.local:
zone "1.168.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192.168.1";
};
Create /etc/bind/db.192.168.1:
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
2026021401 ; Serial
3600 ; Refresh
1800 ; Retry
1209600 ; Expire
86400 ) ; Negative Cache TTL
; Name servers
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
; PTR records
10 IN PTR ns1.example.com.
11 IN PTR ns2.example.com.
20 IN PTR www.example.com.
30 IN PTR mail.example.com.
Define ACLs at the top of your configuration file:
acl "trusted" {
localhost;
192.168.0.0/16;
10.0.0.0/8;
};
acl "slaves" {
192.168.1.10;
192.168.1.11;
};
options {
allow-query { trusted; };
allow-transfer { slaves; };
allow-recursion { trusted; };
allow-query-cache { trusted; };
};
Configure different responses for internal and external clients:
// Define ACLs first
acl "internal" { 192.168.0.0/16; 10.0.0.0/8; };
acl "external" { any; };
view "internal" {
match-clients { internal; };
zone "company.com" {
type master;
file "/etc/bind/internal/db.company.com";
};
// Include other internal zones
include "/etc/bind/named.conf.internal-options";
};
view "external" {
match-clients { external; };
zone "company.com" {
type master;
file "/etc/bind/external/db.company.com";
};
// Include other external zones
include "/etc/bind/named.conf.external-options";
};
options {
// Threading and performance
num-workers 4; // Match number of CPU cores
max-cache-size 256m; // Limit cache size
// Query processing
max-clients-per-query 100;
max-journal-size 100m;
// Response rate limiting (RRL) - for authoritative servers
rate-limit {
responses-per-second 5;
window 10;
slip 2; // Only respond to 1 out of every 2 queries during rate limiting
};
// TCP/UDP settings
tcp-clients 100;
udp-buffer-size 65536;
};
sudo named-checkconf
sudo named-checkzone example.com /etc/bind/db.example.com
Reload configuration without restarting service:
sudo rndc reload
Or restart the service:
sudo systemctl restart bind9 # Debian/Ubuntu
sudo systemctl restart named # RHEL
sudo named-checkconf
sudo named-checkzone example.com /etc/bind/db.example.com
# Test local resolution
dig @localhost example.com
nslookup example.com localhost
# Test specific record types
dig @localhost example.com A
dig @localhost example.com MX
# Check server status
rndc status
Always increment the serial number in zone files after making changes:
Ensure proper ownership and permissions:
# Debian/Ubuntu
sudo chown -R bind:bind /etc/bind/
sudo chmod -R 644 /etc/bind/
# RHEL
sudo chown -R named:named /var/named/
sudo chmod -R 644 /var/named/
Open required ports:
# Debian/Ubuntu with UFW
sudo ufw allow 53/udp
sudo ufw allow 53/tcp
# RHEL with firewalld
sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --reload
If BIND fails to start:
sudo named-checkconfjournalctl -u bind9 (Debian/Ubuntu) or journalctl -u named (RHEL)sudo ss -tulnp | grep :53sudo named-checkzoneEvery DNS deployment is unique. We provide consulting for:
Get personalized assistance: office@linux-server-admin.com | Contact Page