BIND Zone Security: Views, ACLs, and Query Restrictions
A properly secured DNS server is critical infrastructure. An open resolver can be abused for DNS amplification attacks, leak internal network information, or serve as a reconnaissance tool for attackers. This guide covers BIND's security features: Access Control Lists (ACLs), views for split-horizon DNS, and query restrictions to protect your DNS infrastructure.
Understanding the Threat Model
DNS servers face several security challenges:
- Open resolver abuse: Attackers use your server to amplify DDoS attacks
- Information disclosure: Internal hostnames and IP addresses leaked to the internet
- Cache poisoning: Malicious records injected into resolver caches
- Zone transfer exposure: Unauthorized parties downloading your entire zone
- Resource exhaustion: Query floods consuming server resources
BIND provides multiple layers of defense against these threats.
Access Control Lists (ACLs)
ACLs define groups of IP addresses that can be referenced throughout your configuration. Define them once, use them everywhere.
Basic ACL Syntax
acl "trusted" {
localhost;
localnets;
192.168.0.0/16;
10.0.0.0/8;
};
acl "internal-networks" {
192.168.1.0/24;
192.168.2.0/24;
172.16.0.0/12;
};
acl "secondary-servers" {
192.168.1.10;
192.168.1.11;
};
Built-in ACL Keywords
BIND provides several predefined ACLs:
any- Matches all hostsnone- Matches no hostslocalhost- Matches IP addresses of all local interfaceslocalnets- Matches networks directly connected to local interfaces
Negation in ACLs
Use ! to exclude addresses:
acl "external-only" {
!10.0.0.0/8;
!172.16.0.0/12;
!192.168.0.0/16;
any;
};
Order matters - BIND evaluates rules top to bottom and uses the first match.
Query Restrictions
Restricting Recursion
The most critical security setting. Never allow recursion for the entire internet:
options {
directory "/var/named";
// Only allow recursion for trusted networks
recursion yes;
allow-recursion { trusted; };
// Alternatively, disable recursion entirely for authoritative-only servers
// recursion no;
};
Restricting Queries
Limit who can query your server:
options {
// Global query restriction
allow-query { any; }; // For authoritative servers
// allow-query { trusted; }; // For internal resolvers
// Restrict cache access
allow-query-cache { trusted; };
};
Per-Zone Query Restrictions
Apply different policies to different zones:
zone "public.example.com" {
type primary;
file "zones/public.example.com.zone";
allow-query { any; };
};
zone "internal.example.com" {
type primary;
file "zones/internal.example.com.zone";
allow-query { internal-networks; };
};
Zone Transfer Security
Restricting Zone Transfers
Never allow unrestricted zone transfers:
options {
// Disable by default
allow-transfer { none; };
};
zone "example.com" {
type primary;
file "zones/example.com.zone";
// Only allow transfers to secondary servers
allow-transfer { secondary-servers; };
also-notify { 192.168.1.10; 192.168.1.11; };
};
TSIG-Authenticated Transfers
For maximum security, require TSIG authentication:
key "transfer-key" {
algorithm hmac-sha256;
secret "base64-encoded-secret";
};
zone "example.com" {
type primary;
file "zones/example.com.zone";
allow-transfer { key "transfer-key"; };
};
Views for Split-Horizon DNS
Views allow the same zone to return different answers based on client IP address. This is essential for split-horizon DNS where internal and external clients need different responses.
Basic View Configuration
acl "internal" {
192.168.0.0/16;
10.0.0.0/8;
172.16.0.0/12;
localhost;
};
acl "external" {
!192.168.0.0/16;
!10.0.0.0/8;
!172.16.0.0/12;
any;
};
view "internal" {
match-clients { internal; };
// Internal clients get recursion
recursion yes;
zone "example.com" {
type primary;
file "zones/internal/example.com.zone";
};
zone "." {
type hint;
file "named.ca";
};
};
view "external" {
match-clients { external; };
// No recursion for external clients
recursion no;
zone "example.com" {
type primary;
file "zones/external/example.com.zone";
};
};
Internal Zone File
; zones/internal/example.com.zone
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
2024010101 ; Serial
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
IN NS ns1.example.com.
IN NS ns2.example.com.
IN A 192.168.1.100 ; Internal IP
ns1 IN A 192.168.1.10
ns2 IN A 192.168.1.11
www IN A 192.168.1.100 ; Internal web server
mail IN A 192.168.1.50 ; Internal mail server
db IN A 192.168.1.200 ; Database - internal only
ldap IN A 192.168.1.201 ; LDAP - internal only
External Zone File
; zones/external/example.com.zone
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
2024010101 ; Serial
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
IN NS ns1.example.com.
IN NS ns2.example.com.
IN A 203.0.113.100 ; Public IP
IN MX 10 mail.example.com.
ns1 IN A 203.0.113.10
ns2 IN A 203.0.113.11
www IN A 203.0.113.100 ; Public web server
mail IN A 203.0.113.50 ; Public mail server
; No db or ldap records - not accessible externally
View Ordering
Views are evaluated in order. Place more specific views first:
view "admin" {
match-clients { 192.168.1.5; }; // Admin workstation
// Full access, debugging enabled
};
view "internal" {
match-clients { internal; };
// Standard internal access
};
view "external" {
match-clients { any; }; // Catch-all
// Restricted external access
};
Rate Limiting
Protect against DNS amplification and query floods:
options {
rate-limit {
responses-per-second 10;
referrals-per-second 5;
nodata-per-second 5;
nxdomains-per-second 5;
errors-per-second 5;
all-per-second 20;
window 15;
slip 2;
ipv4-prefix-length 24;
ipv6-prefix-length 56;
};
};
Key parameters:
responses-per-second- Limit identical responsesslip- Send truncated responses (forcing TCP) instead of droppingwindow- Time window for rate calculationipv4-prefix-length- Group clients by /24 instead of individual IPs
Response Policy
Minimal Responses
Reduce response size to limit amplification:
options {
minimal-responses yes;
minimal-any yes;
};
Disable ANY Queries
ANY queries are often used in amplification attacks:
options {
minimal-any yes; // Return minimal response
// Or block entirely with RPZ
};
Logging Security Events
Configure comprehensive security logging:
logging {
channel security_log {
file "/var/log/named/security.log" versions 5 size 10m;
severity info;
print-time yes;
print-severity yes;
print-category yes;
};
channel query_log {
file "/var/log/named/queries.log" versions 5 size 50m;
severity info;
print-time yes;
};
category security { security_log; };
category queries { query_log; };
category xfer-in { security_log; };
category xfer-out { security_log; };
category notify { security_log; };
};
Complete Secure Configuration Example
Here's a comprehensive configuration combining all security features:
// /etc/named.conf
acl "trusted" {
localhost;
localnets;
192.168.0.0/16;
10.0.0.0/8;
};
acl "secondary-ns" {
192.168.1.10;
192.168.1.11;
};
key "transfer-key" {
algorithm hmac-sha256;
secret "your-secret-here";
};
options {
directory "/var/named";
pid-file "/run/named/named.pid";
// Listen configuration
listen-on port 53 { any; };
listen-on-v6 port 53 { any; };
// Security defaults
recursion no; // Disabled by default
allow-query { any; }; // Allow queries
allow-transfer { none; }; // Deny transfers by default
allow-update { none; }; // Deny updates by default
// Version hiding
version "not disclosed";
hostname "not disclosed";
server-id "not disclosed";
// Response minimization
minimal-responses yes;
minimal-any yes;
// Rate limiting
rate-limit {
responses-per-second 10;
window 15;
slip 2;
};
// DNSSEC validation
dnssec-validation auto;
};
view "internal" {
match-clients { trusted; };
recursion yes;
allow-recursion { trusted; };
zone "example.com" {
type primary;
file "zones/internal/example.com.zone";
allow-transfer { key "transfer-key"; };
};
zone "." {
type hint;
file "named.ca";
};
};
view "external" {
match-clients { any; };
recursion no;
zone "example.com" {
type primary;
file "zones/external/example.com.zone";
allow-transfer { key "transfer-key"; };
allow-query { any; };
};
};
logging {
channel default_log {
file "/var/log/named/named.log" versions 5 size 10m;
severity info;
print-time yes;
print-severity yes;
};
channel security_log {
file "/var/log/named/security.log" versions 5 size 10m;
severity info;
print-time yes;
};
category default { default_log; };
category security { security_log; };
category xfer-in { security_log; };
category xfer-out { security_log; };
};
Security Checklist
Before putting your BIND server into production:
- Recursion: Disabled or restricted to trusted networks only
- Zone transfers: Restricted to secondary servers, preferably with TSIG
- Version string: Hidden to prevent fingerprinting
- Rate limiting: Enabled to prevent amplification abuse
- ACLs: Defined and applied consistently
- Views: Configured if split-horizon is needed
- Logging: Security events logged for auditing
- DNSSEC: Validation enabled for resolvers
- Updates: Disabled or restricted with TSIG keys
- Firewall: Port 53 restricted appropriately
Conclusion
DNS security requires defense in depth. ACLs provide the foundation, views enable split-horizon deployments, and query restrictions prevent abuse. Combined with rate limiting, minimal responses, and proper logging, these features create a robust security posture for your DNS infrastructure.
The next post will cover dynamic DNS updates with TSIG authentication, allowing secure automated record management.