Configuring a reliable, internal Domain Name System (DNS) is a foundational step in establishing a stable network infrastructure. BIND9 (Berkeley Internet Name Domain) remains the industry-standard software component for this task on Linux platforms. This guide provides a comprehensive walkthrough for deploying, configuring, and testing BIND9 on a Debian-based server to operate as both a recursive resolver and an authoritative DNS server for your infrastructure.
Environment Overview
Before modifying configuration files, establish the parameters of your network topology. This deployment uses the following infrastructure values:
- Domain: mylab.local, techncloud.xyz
- Network: 172.20.0.0/16 (utilizing subnets 172.20.5.0/24 and 172.20.6.0/24)
- DNS Server: ns1.mylab.local (172.20.6.184)
- Purpose: Internal recursive and authoritative DNS server
Installation
Update your package index and install BIND9 along with its essential utilities and documentation packages:
# Update package list
sudo apt update
# Install BIND9 and utilities
sudo apt install bind9 bind9utils bind9-doc dnsutils -y
# Check installation
named -v
1. Main Configuration File: /etc/bind/named.conf.options
On Ubuntu and Debian systems, the primary configuration is modularized across multiple files. Define global operation parameters by modifying the options file:
sudo nano /etc/bind/named.conf.options
options {
directory "/var/cache/bind";
// Listen on all interfaces
listen-on port 53 { any; };
listen-on-v6 { any; };
// Allow queries from any source
allow-query { any; };
// Enable recursion for internal queries
recursion yes;
allow-recursion { any; };
// Forwarders (optional - use Google DNS or your ISP's DNS)
forwarders {
8.8.8.8;
8.8.4.4;
};
// DNSSEC validation
dnssec-validation auto;
// Other settings
auth-nxdomain no; # conform to RFC1035
};
2. Zone Configuration: /etc/bind/named.conf.local
Declare the forward and reverse lookup zones for your domains inside the local configuration file:
sudo nano /etc/bind/named.conf.local
// Forward zone for local domain
zone "mylab.local" {
type master;
file "/etc/bind/zones/db.mylab.local";
allow-update { none; };
};
// Forward zone for public domain
zone "techncloud.xyz" {
type master;
file "/etc/bind/zones/db.techncloud.xyz";
allow-update { none; };
};
// Reverse zone for 172.20.5.0/24 subnet
zone "5.20.172.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.172.20.5";
allow-update { none; };
};
// Reverse zone for 172.20.6.0/24 subnet
zone "6.20.172.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.172.20.6";
allow-update { none; };
};
3. Create Zone Files Directory
To keep configurations organized, isolate the database files within a dedicated subdirectory and assign correct service permissions:
# Create directory for zone files
sudo mkdir -p /etc/bind/zones
# Set proper ownership
sudo chown bind:bind /etc/bind/zones
4. Forward Zone File (Local): /etc/bind/zones/db.mylab.local
Create the file responsible for translating local hostnames to IPv4 addresses:
sudo nano /etc/bind/zones/db.mylab.local
$TTL 86400
@ IN SOA ns1.mylab.local. admin.mylab.local. (
2024102301 ; Serial (YYYYMMDDNN)
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ; Minimum TTL
)
; Name servers
@ IN NS ns1.mylab.local.
; A records
ns1 IN A 172.20.6.184
server1 IN A 172.20.6.187
server2 IN A 172.20.6.120
workstation1 IN A 172.20.6.103
printer IN A 172.20.5.160
; CNAME records
www IN CNAME server1
mail IN CNAME server2
; TXT Records
info IN TXT "Contact: admin@mylab.local"
5. Forward Zone File (Public): /etc/bind/zones/db.techncloud.xyz
Configure the forward lookup parameters for your secondary domain space:
sudo nano /etc/bind/zones/db.techncloud.xyz
$TTL 3600
@ IN SOA ns1.techncloud.xyz. admin.techncloud.xyz. (
2024102301 ; Serial
7200 ; Refresh
3600 ; Retry
1209600 ; Expire
3600 ; Minimum TTL
)
; Name servers
@ IN NS ns1.techncloud.xyz.
; A records for nameservers
ns1 IN A 139.185.54.150
; Main Records
@ IN A 203.0.113.10
www IN A 203.0.113.10
web IN A 203.0.113.10
6. Reverse Zone File: /etc/bind/zones/db.172.20.5
Establish pointer (PTR) resource records to resolve the 172.20.5.0/24 subnet IP addresses back to canonical hostnames:
sudo nano /etc/bind/zones/db.172.20.5
$TTL 86400
@ IN SOA ns1.mylab.local. admin.mylab.local. (
2024102301 ; Serial
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ; Minimum TTL
)
; Name server
@ IN NS ns1.mylab.local.
; PTR records
160 IN PTR printer.mylab.local.
7. Reverse Zone File: /etc/bind/zones/db.172.20.6
Configure the pointer entries for network devices operating inside the 172.20.6.0/24 block:
sudo nano /etc/bind/zones/db.172.20.6
$TTL 86400
@ IN SOA ns1.mylab.local. admin.mylab.local. (
2024102301 ; Serial
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ; Minimum TTL
)
; Name server
@ IN NS ns1.mylab.local.
; PTR records
184 IN PTR ns1.mylab.local.
187 IN PTR server1.mylab.local.
120 IN PTR server2.mylab.local.
103 IN PTR workstation1.mylab.local.
8. File Permissions
Secure the newly created database files by adjusting system ownership patterns and restrictive read/write execution permissions:
# Set ownership for zone files
sudo chown bind:bind /etc/bind/zones/db.mylab.local
sudo chown bind:bind /etc/bind/zones/db.techncloud.xyz
sudo chown bind:bind /etc/bind/zones/db.172.20.5
sudo chown bind:bind /etc/bind/zones/db.172.20.6
# Set permissions (read-write for owner, read for group)
sudo chmod 640 /etc/bind/zones/db.mylab.local
sudo chmod 640 /etc/bind/zones/db.techncloud.xyz
sudo chmod 640 /etc/bind/zones/db.172.20.5
sudo chmod 640 /etc/bind/zones/db.172.20.6
9. Verification Commands
To avoid runtime service failures, explicitly check the structural validity of both your primary options file and your target zone records before initialization:
Check Configuration Syntax
# Check main configuration
sudo named-checkconf
# Check forward zones
sudo named-checkzone mylab.local /etc/bind/zones/db.mylab.local
sudo named-checkzone techncloud.xyz /etc/bind/zones/db.techncloud.xyz
# Check reverse zones
sudo named-checkzone 5.20.172.in-addr.arpa /etc/bind/zones/db.172.20.5
sudo named-checkzone 6.20.172.in-addr.arpa /etc/bind/zones/db.172.20.6
Expected output for valid zones:
zone mylab.local/IN: loaded serial 2024102301
OK
10. Service Management
Once syntax validation passes, restart the underlying system service and ensure execution persistency across system boot sequences:
# Restart BIND after configuration
sudo systemctl restart bind9
# Check service status
sudo systemctl status bind9
# Enable BIND to start on boot
sudo systemctl enable bind9
# View logs
sudo journalctl -u bind9 -f
# Reload zones without restart
sudo rndc reload
11. Firewall Configuration (UFW)
Ensure network firewalls permit active communication through the standardized transport ports allocated for DNS requests:
# Allow DNS traffic
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
# Check firewall status
sudo ufw status
# If firewall is inactive, enable it
sudo ufw enable
12. Configure System to Use Local DNS
Modify the local resolving agent to prioritize the newly created instance for handling system-wide resolution loops:
Edit the system’s DNS configuration:
sudo nano /etc/systemd/resolved.conf
Add or modify:
[Resolve]
DNS=127.0.0.1
FallbackDNS=8.8.8.8
Restart systemd-resolved:
sudo systemctl restart systemd-resolved
13. Testing DNS Resolution
Execute functional end-to-end lookups against the localized service loop to prove functionality across both vector planes:
Forward Lookups (hostname → IP)
dig @localhost ns1.mylab.local
dig @localhost server1.mylab.local
dig @localhost printer.mylab.local
dig @localhost www.techncloud.xyz
# Or using nslookup
nslookup server1.mylab.local localhost
# Using host command
host server1.mylab.local localhost
Reverse Lookups (IP → hostname)
dig @localhost -x 172.20.6.184
dig @localhost -x 172.20.5.160
# Or using nslookup
nslookup 172.20.6.187 localhost
# Using host command
host 172.20.6.187 localhost
Test from External Host
# Replace with your DNS server's IP
dig @172.20.6.184 server1.mylab.local
nslookup www.techncloud.xyz 172.20.6.184
14. Adding New Hosts
When extending network boundaries, maintain structural accuracy by following a sequence-based change process across zone sets:
Step 1: Add Forward DNS Entry
Edit /etc/bind/zones/db.mylab.local:
sudo nano /etc/bind/zones/db.mylab.local
Add:
newserver IN A 172.20.6.200
Step 2: Add Reverse DNS Entry
Edit /etc/bind/zones/db.172.20.6:
sudo nano /etc/bind/zones/db.172.20.6
Add:
200 IN PTR newserver.mylab.local.
Step 3: Increment Serial Number
In both zone files, update:
2024102301 → 2024102302
Step 4: Verify and Reload
sudo named-checkzone mylab.local /etc/bind/zones/db.mylab.local
sudo named-checkzone 6.20.172.in-addr.arpa /etc/bind/zones/db.172.20.6
sudo rndc reload
15. Common Issues and Solutions
Review these operational isolation measures to resolve frequent deployment errors:
Issue: BIND won’t start
# Check configuration
sudo named-checkconf
# Check zone files
sudo named-checkzone mylab.local /etc/bind/zones/db.mylab.local
# View detailed errors
sudo journalctl -u bind9 -n 50 --no-pager
# Check for syntax errors in logs
sudo tail -f /var/log/syslog | grep named
Issue: DNS not accessible from outside
# Check if listening on all interfaces
sudo ss -tulpn | grep :53
# Should show: 0.0.0.0:53
# Check firewall
sudo ufw status
# Verify listening addresses in config
sudo named-checkconf -p | grep listen-on
Issue: Permission denied errors
# Fix ownership
sudo chown -R bind:bind /etc/bind/zones/
# Fix permissions
sudo chmod 755 /etc/bind/zones/
sudo chmod 640 /etc/bind/zones/db.*
Issue: Changes not taking effect
# Increment serial number in zone file
# Then reload
sudo rndc reload
# Or restart service
sudo systemctl restart bind9
# Clear local DNS cache
sudo systemd-resolve --flush-caches
Issue: SELinux/AppArmor blocking BIND
# Check AppArmor status (Ubuntu uses AppArmor, not SELinux)
sudo aa-status | grep named
# If issues persist, check AppArmor logs
sudo journalctl -xe | grep apparmor
# Temporarily disable AppArmor for bind (not recommended for production)
sudo aa-complain /usr/sbin/named
17. Monitoring and Maintenance
To preserve long-term operational health, implement structured diagnostic oversight strategies:
View Query Statistics
# View query statistics
sudo rndc stats
sudo cat /var/cache/bind/named.stats
Monitor DNS Queries in Real-time
# Enable query logging
sudo rndc querylog on
# View queries
sudo tail -f /var/log/syslog | grep named
Backup Configuration
# Backup all BIND configuration
sudo tar -czf bind-backup-$(date +%Y%m%d).tar.gz /etc/bind/
Deploying a local BIND9 infrastructure provides full administrative control over your network resolution path, improving internal latency and scaling capacity. By following proper zone file documentation habits, updating serial tokens linearly, and integrating systematic maintenance processes, your DNS system will remain highly resilient and performant.
