DNS Server with BIND9: Complete Setup Guide
Introduction
The Domain Name System (DNS) serves as the internet's phonebook, translating human-readable domain names into IP addresses that computers use to communicate. BIND9 (Berkeley Internet Name Domain version 9) stands as the most widely deployed DNS server software globally, powering a significant portion of internet infrastructure, from Fortune 500 corporate networks to individual domains.
Developed by the Internet Systems Consortium (ISC) and continuously maintained since 1986, BIND9 offers comprehensive DNS functionality including authoritative name serving, recursive resolution, DNSSEC validation, dynamic updates, and advanced zone management. Its proven stability, extensive feature set, and standards compliance make it the gold standard for DNS server deployment.
This comprehensive guide provides everything needed to deploy a production-ready BIND9 DNS server. You'll learn installation procedures, authoritative zone configuration, recursive resolver setup, DNSSEC implementation, split-horizon DNS, dynamic updates, security hardening, performance optimization, and troubleshooting techniques.
Whether running an authoritative DNS server for your domains, deploying an internal corporate DNS infrastructure, creating a caching recursive resolver for improved performance, implementing DNSSEC for security, or building a complete DNS solution from scratch, this guide provides the foundation for professional DNS deployment.
Use Case Overview
Why Deploy Your Own DNS Server?
Running your own DNS server provides significant advantages:
Complete Control: Manage DNS records directly without relying on third-party providers. Make instant changes without waiting for propagation through external systems.
Performance: Local caching DNS servers dramatically improve resolution speed by caching frequently accessed records, reducing latency for end users and applications.
Privacy: Prevent DNS query logging by third parties. Your DNS queries reveal browsing habits, application usage, and network behavior.
Reliability: Eliminate dependency on external DNS providers. Network continues operating even if internet connectivity is lost (for internal resources).
Cost Savings: Avoid recurring fees for premium DNS hosting services, especially for organizations managing numerous domains.
Advanced Features: Implement split-horizon DNS, geographic load balancing, dynamic updates, or custom DNS-based solutions impossible with basic DNS providers.
Internal Network Resolution: Resolve internal hostnames and services not exposed to the public internet, essential for corporate environments.
Development and Testing: Create isolated DNS environments for development, staging, and testing without affecting production systems.
Common Deployment Scenarios
Authoritative DNS Server: Hosting DNS zones for your domains, serving public DNS queries for websites, mail servers, and other internet-facing resources.
Recursive Resolver: Internal DNS server caching responses and forwarding queries, improving response times and reducing bandwidth for corporate networks.
Split-Horizon DNS: Different DNS responses for internal vs external queries, providing private IP addresses to internal clients and public IPs to external clients.
Active Directory Integration: DNS servers supporting Microsoft Active Directory domains, providing name resolution for domain controllers and services.
ISP DNS Infrastructure: Internet service providers deploying caching DNS servers improving subscriber experience and reducing upstream bandwidth.
Development Environment: Isolated DNS for development and testing, using .dev or .test TLDs for local services without affecting production.
Geographic Load Balancing: Directing users to geographically nearest servers based on query source for improved performance.
DNSSEC Implementation: Securing DNS infrastructure against cache poisoning and spoofing attacks through cryptographic validation.
DNS Server Types
Authoritative DNS Server:
- Hosts master copies of DNS zones
- Responds authoritatively for configured domains
- Provides zone transfer to secondary servers
- Use case: Domain hosting, zone management
Recursive Resolver:
- Resolves queries by recursively querying authoritative servers
- Caches results for improved performance
- Serves client queries for any domain
- Use case: Corporate networks, ISP infrastructure
Forwarding Resolver:
- Forwards queries to upstream DNS servers
- Caches responses locally
- Simpler than full recursive resolution
- Use case: Small networks, DMZ environments
Caching-Only Server:
- Only caches responses, no authoritative zones
- Reduces load on authoritative servers
- Improves local query performance
- Use case: Branch offices, high-traffic networks
Requirements
System Requirements
Minimum Requirements (Small Network, < 100 clients):
- CPU: 1 core at 1.5+ GHz
- RAM: 512MB
- Storage: 10GB
- Network: 10 Mbps
- OS: Ubuntu 20.04/22.04, Debian 11/12, CentOS 8, Rocky Linux 8/9
Recommended Requirements (Medium Network, 100-1000 clients):
- CPU: 2 cores at 2.0+ GHz
- RAM: 2GB
- Storage: 20GB
- Network: 100 Mbps
- OS: Ubuntu 22.04 LTS
High-Performance Requirements (Large Network, > 1000 clients or public authoritative):
- CPU: 4+ cores at 2.5+ GHz
- RAM: 8GB+
- Storage: 50GB SSD
- Network: 1 Gbps
- OS: Ubuntu 22.04 LTS with optimizations
Network Requirements
Port Configuration:
- 53/UDP: Primary DNS protocol (queries and responses)
- 53/TCP: Zone transfers (AXFR), large responses
- 953/TCP: rndc remote control (optional, local only)
IP Addressing: Static IP address required. DNS servers cannot use DHCP.
Network Positioning: Typically placed in DMZ for external authoritative servers, or internal network for recursive resolvers.
Software Requirements
BIND9: Latest stable version (9.16+ recommended).
Optional Tools:
- dnsutils: dig, nslookup, host for testing
- bind9utils: DNS utilities and helpers
- bind9-doc: Documentation
Prerequisites Knowledge
- Understanding of DNS concepts (A, AAAA, CNAME, MX, NS, SOA records)
- Basic networking knowledge
- Linux command-line proficiency
- Domain registration and nameserver configuration (for authoritative servers)
Step-by-Step Setup
Step 1: Install BIND9
Update system:
# Ubuntu/Debian
sudo apt update && sudo apt upgrade -y
# CentOS/Rocky Linux
sudo dnf update -y
Install BIND9:
# Ubuntu/Debian
sudo apt install bind9 bind9utils bind9-doc dnsutils -y
# CentOS/Rocky Linux
sudo dnf install bind bind-utils -y
Verify installation:
named -v
Step 2: Backup Default Configuration
sudo cp /etc/bind/named.conf /etc/bind/named.conf.original
sudo cp /etc/bind/named.conf.options /etc/bind/named.conf.options.original
(On CentOS/Rocky, configuration is in /etc/named.conf)
Step 3: Configure Basic Caching DNS Server
Edit main configuration:
# Ubuntu/Debian
sudo nano /etc/bind/named.conf.options
# CentOS/Rocky
sudo nano /etc/named.conf
Ubuntu/Debian configuration:
options {
directory "/var/cache/bind";
// Listen on all interfaces
listen-on port 53 { any; };
listen-on-v6 port 53 { any; };
// Allow queries from local network
allow-query { localhost; 192.168.1.0/24; };
// Allow recursion for local network
allow-recursion { localhost; 192.168.1.0/24; };
recursion yes;
// Forwarders (Google DNS and Cloudflare)
forwarders {
8.8.8.8;
8.8.4.4;
1.1.1.1;
};
// DNSSEC validation
dnssec-validation auto;
// Disable zone transfers
allow-transfer { none; };
// IPv4/IPv6 configuration
auth-nxdomain no;
listen-on-v6 { any; };
};
Replace 192.168.1.0/24 with your actual network range.
Step 4: Configure Firewall
Allow DNS ports:
# UFW (Ubuntu/Debian)
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
# Firewalld (CentOS/Rocky)
sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --reload
Step 5: Test Configuration and Start BIND9
Test configuration syntax:
# Ubuntu/Debian
sudo named-checkconf
# CentOS/Rocky
sudo named-checkconf /etc/named.conf
No output means configuration is valid.
Enable and start BIND9:
# Ubuntu/Debian
sudo systemctl enable bind9
sudo systemctl start bind9
sudo systemctl status bind9
# CentOS/Rocky
sudo systemctl enable named
sudo systemctl start named
sudo systemctl status named
Step 6: Test DNS Resolution
From the server:
dig @localhost google.com
Should return DNS response with IP address.
From a client on the network:
dig @DNS_SERVER_IP google.com
Configure client to use your DNS server:
Linux/macOS:
# Edit /etc/resolv.conf (temporary)
nameserver DNS_SERVER_IP
Windows:
- Network Settings → Network Adapter → Properties
- Internet Protocol Version 4 → Properties
- Use DNS Server: Enter DNS_SERVER_IP
Configuration
Authoritative Zone Configuration
Host authoritative DNS zones for your domains:
Create zone file:
sudo nano /etc/bind/db.example.com
Add zone data:
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
2024011101 ; Serial (YYYYMMDDNN)
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
; Name servers
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
; A records
@ IN A 192.0.2.10
www IN A 192.0.2.10
ns1 IN A 192.0.2.5
ns2 IN A 192.0.2.6
; Mail server
@ IN MX 10 mail.example.com.
mail IN A 192.0.2.20
; Additional services
ftp IN A 192.0.2.30
blog IN CNAME www
Add zone to BIND configuration:
sudo nano /etc/bind/named.conf.local
Add:
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-transfer { 192.0.2.6; }; // Secondary DNS server IP
notify yes;
};
Test zone file:
sudo named-checkzone example.com /etc/bind/db.example.com
Reload BIND:
sudo rndc reload
Test authoritative query:
dig @localhost example.com
dig @localhost www.example.com
Reverse DNS Zone
Create reverse DNS zone for PTR records:
sudo nano /etc/bind/db.192.0.2
Add:
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
2024011101
3600
1800
604800
86400 )
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
; PTR records (reverse IP mapping)
10 IN PTR example.com.
10 IN PTR www.example.com.
5 IN PTR ns1.example.com.
6 IN PTR ns2.example.com.
20 IN PTR mail.example.com.
30 IN PTR ftp.example.com.
Add zone to configuration:
sudo nano /etc/bind/named.conf.local
Add:
zone "2.0.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192.0.2";
allow-transfer { 192.0.2.6; };
};
Test and reload:
sudo named-checkzone 2.0.192.in-addr.arpa /etc/bind/db.192.0.2
sudo rndc reload
dig -x 192.0.2.10 @localhost
Split-Horizon DNS (Views)
Serve different DNS responses for internal vs external queries:
sudo nano /etc/bind/named.conf
Configure views:
acl "internal" {
192.168.1.0/24;
10.0.0.0/8;
localhost;
};
view "internal-view" {
match-clients { internal; };
recursion yes;
zone "example.com" {
type master;
file "/etc/bind/internal/db.example.com";
};
include "/etc/bind/named.conf.default-zones";
};
view "external-view" {
match-clients { any; };
recursion no;
zone "example.com" {
type master;
file "/etc/bind/external/db.example.com";
};
};
Create separate zone files:
Internal zone (/etc/bind/internal/db.example.com):
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (...)
@ IN NS ns1.example.com.
@ IN A 10.0.0.10 ; Internal IP
www IN A 10.0.0.10
intranet IN A 10.0.0.50
External zone (/etc/bind/external/db.example.com):
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (...)
@ IN NS ns1.example.com.
@ IN A 192.0.2.10 ; Public IP
www IN A 192.0.2.10
Dynamic DNS Updates
Allow dynamic record updates (useful for DHCP integration):
Generate update key:
sudo tsig-keygen -a HMAC-SHA256 ddns-key | sudo tee /etc/bind/ddns-key.conf
Include key in configuration:
sudo nano /etc/bind/named.conf.local
Add:
include "/etc/bind/ddns-key.conf";
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-update { key ddns-key; };
};
Make zone file writable:
sudo chown bind:bind /etc/bind/db.example.com
sudo chmod 644 /etc/bind/db.example.com
Test dynamic update:
echo "server localhost
zone example.com
update add test.example.com. 300 A 192.0.2.100
send" | nsupdate -k /etc/bind/ddns-key.conf
Verify:
dig test.example.com @localhost
DNSSEC Implementation
Enable DNSSEC for zone security:
Generate zone signing key (ZSK):
cd /etc/bind
sudo dnssec-keygen -a RSASHA256 -b 2048 -n ZONE example.com
Generate key signing key (KSK):
sudo dnssec-keygen -a RSASHA256 -b 4096 -f KSK -n ZONE example.com
Sign the zone:
sudo dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) \
-N INCREMENT -o example.com -t db.example.com
Update zone configuration:
zone "example.com" {
type master;
file "/etc/bind/db.example.com.signed";
allow-transfer { 192.0.2.6; };
};
Reload BIND:
sudo rndc reload
Extract DS record for domain registrar:
cat /etc/bind/dsset-example.com.
Add this DS record to your domain registrar.
Test DNSSEC:
dig +dnssec example.com @localhost
Optimization
Cache Tuning
Optimize cache size and TTL:
options {
// Cache size (memory)
max-cache-size 512M;
// Cache TTL limits
max-cache-ttl 86400; // 1 day
max-ncache-ttl 3600; // 1 hour for negative caching
// Cleaning interval
cleaning-interval 60;
};
Rate Limiting
Prevent DNS amplification attacks:
options {
rate-limit {
responses-per-second 10;
window 5;
};
};
Query Performance
Optimize query handling:
options {
// Use all CPU cores
cpus 4;
// Minimal responses
minimal-responses yes;
// Prefetch
prefetch 2 9;
};
Logging Configuration
Configure detailed logging:
sudo nano /etc/bind/named.conf.logging
Add:
logging {
channel default_log {
file "/var/log/bind/default.log" versions 3 size 5m;
severity info;
print-time yes;
print-severity yes;
print-category yes;
};
channel query_log {
file "/var/log/bind/query.log" versions 3 size 10m;
severity info;
print-time yes;
};
category default { default_log; };
category queries { query_log; };
};
Create log directory:
sudo mkdir -p /var/log/bind
sudo chown bind:bind /var/log/bind
Troubleshooting
DNS Not Resolving
Check BIND status:
sudo systemctl status bind9
Test configuration:
sudo named-checkconf
Check listening ports:
sudo netstat -tlnp | grep named
View logs:
sudo tail -f /var/log/syslog | grep named
Test locally:
dig @localhost google.com
If works locally but not remotely, check firewall.
Zone Transfer Fails
Verify allow-transfer:
zone "example.com" {
allow-transfer { SECONDARY_IP; };
};
Test zone transfer:
dig @PRIMARY_IP example.com AXFR
Check notify settings:
notify yes;
also-notify { SECONDARY_IP; };
DNSSEC Validation Failures
Disable validation temporarily:
dnssec-validation no;
Check trust anchors:
sudo rndc managed-keys status
Verify time synchronization:
timedatectl
DNSSEC requires accurate time.
High CPU/Memory Usage
Monitor BIND performance:
sudo rndc status
Check query rate:
sudo rndc stats
cat /var/cache/bind/named.stats
Implement rate limiting (see Optimization section).
Reduce cache size if memory constrained.
Conclusion
You now have a production-ready BIND9 DNS server providing authoritative name serving, recursive resolution, or both. This professional DNS infrastructure offers the control, performance, and security needed for modern network environments.
Key achievements:
- Flexible DNS infrastructure supporting authoritative and recursive modes
- Advanced features including DNSSEC, split-horizon, and dynamic updates
- Security hardening through rate limiting and access controls
- Performance optimization with caching and query tuning
- Production-ready configuration for reliable name resolution
Regular maintenance includes monitoring query logs, updating zone serial numbers when making changes, renewing DNSSEC signatures, and keeping BIND updated for security patches.
Resolve reliably!


