How to Configure BIND9 for Secure Recursive DNS Resolution Without Exposing Your Server


2 views

Many administrators face this paradox: disabling recursion breaks external resolution while enabling it opens security risks. The key is implementing selective recursion combined with proper access controls.

Your named.conf.options shows several potential issues:

allow-recursion { any; };  // This is dangerously permissive
allow-query { any; };      // Similarly open
dnssec-validation yes;     // Good practice

Here's a hardened configuration that maintains functionality while improving security:

options {
    directory "/var/cache/bind";
    
    // Restrict recursion to trusted networks
    allow-recursion {
        192.168.1.0/24;    // Your internal network
        10.0.0.0/8;        // Additional private ranges
    };
    
    // Allow queries from anywhere (adjust as needed)
    allow-query {
        any;
    };
    
    // Cache access restrictions
    allow-query-cache {
        localhost;
        192.168.1.0/24;
    };
    
    dnssec-validation auto;
    recursion yes;         // Explicitly enable recursion
    
    // Recommended forwarders for better performance
    forwarders {
        8.8.8.8;
        8.8.4.4;
        1.1.1.1;
    };
    forward only;          // Important for security
    
    listen-on-v6 { any; };
    auth-nxdomain no;
};

Key security considerations:

  • Never use any in allow-recursion - this makes your server vulnerable to DNS amplification attacks
  • Combine recursion restrictions with rate limiting in your firewall
  • Consider using Response Rate Limiting (RRL) for additional protection

After implementing changes:

sudo named-checkconf
sudo systemctl restart bind9
dig @your_server google.com  # Should resolve externally
dig @your_server internal.yourdomain.com  # Should resolve internally

For more complex environments, consider a split-horizon DNS configuration:

view "internal" {
    match-clients { 192.168.1.0/24; };
    recursion yes;
    zone "example.com" {
        type master;
        file "/etc/bind/internal/example.com.zone";
    };
};

view "external" {
    match-clients { any; };
    recursion no;
    zone "example.com" {
        type master;
        file "/etc/bind/external/example.com.zone";
    };
};

When running a BIND9 DNS server, you'll encounter a common security vs functionality trade-off: Disabling recursion blocks external domain resolution while enabling it without restrictions makes your server vulnerable to DNS amplification attacks. The key is implementing controlled recursion.

Here's a properly secured named.conf.options setup that allows recursion only for trusted networks:

options {
    directory "/var/cache/bind";
    
    // Enable recursion only for internal networks
    recursion yes;
    allow-recursion {
        192.168.1.0/24;
        10.0.0.0/8;
        ::1/128;
    };
    
    // Restrict queries
    allow-query {
        any;  // Or specify allowed networks
    };
    
    // Additional security
    allow-query-cache { none; };
    allow-transfer { none; };
    dnssec-validation auto;
    
    // Recommended forwarders for better performance
    forwarders {
        8.8.8.8;
        8.8.4.4;
    };
    forward only;
};

1. Network Segmentation: Only allow recursion from your internal subnets. Public IPs should only get authoritative responses.

2. Rate Limiting (BIND 9.10+): Add this to prevent abuse:

rate-limit {
    responses-per-second 10;
    window 5;
};

After making changes, verify with:

sudo named-checkconf
sudo systemctl reload bind9

Test recursion from an allowed client:

dig @your-dns-server example.com +trace

For complex environments, consider implementing views to separate internal and external resolution:

view "internal" {
    match-clients { 192.168.1.0/24; };
    recursion yes;
    // Internal zone configuration
};

view "external" {
    match-clients { any; };
    recursion no;
    // Public zone configuration
};

Add these options to improve recursive resolution:

max-cache-size 256M;
max-cache-ttl 86400;
min-cache-ttl 300;