Debugging BIND DNS SERVER SERVFAIL Error During Dynamic Updates with nsupdate


5 views

When attempting dynamic DNS updates using nsupdate with BIND, receiving a SERVFAIL response typically indicates a fundamental misconfiguration in either the key authentication setup or zone file permissions. Let's break down the complete solution.

The HMAC-MD5 key generation appears correct, but let's verify the complete implementation:

key "sub.example.com." {
    algorithm hmac-md5;
    secret "your-base64-secret-here";
};

Critical points about key configuration:

1. Ensure the key name matches exactly in named.conf and nsupdate command
2. Verify the secret is base64-encoded without spaces
3. Check key file permissions (600 recommended)

The zone file must:

- Exist before first update attempt
- Contain proper SOA record
- Have correct permissions (bind:bind with 644 rights)

Example minimal zone file:

$ORIGIN sub.example.com.
$TTL 86400
@    IN SOA ns1.example.com. admin.example.com. (
        2023080601 ; serial
        3600       ; refresh
        1800       ; retry
        604800     ; expire
        86400      ; minimum TTL
)

The configuration shown needs these adjustments:

zone "sub.example.com" {
    type master;
    file "/etc/bind/primary/sub.example.com";
    allow-update { key "sub.example.com."; };
    journal "/var/lib/bind/sub.example.com.jnl";
};

Your update file should include proper authentication:

key sub.example.com. your-base64-secret
server dns-server-ip
zone sub.example.com
update add test.sub.example.com. 300 A 192.168.1.1
show
send

These directory permissions are essential:

chown bind:bind /etc/bind/primary
chmod 775 /etc/bind/primary
chown bind:bind /var/cache/bind
setfacl -Rm u:bind:rwx /var/cache/bind

Enable detailed logging in named.conf:

logging {
    channel update_debug {
        file "/var/log/bind/update.log";
        severity debug 3;
    };
    category update { update_debug; };
    category security { update_debug; };
};
- Key name mismatch between config and command
- Incorrect key algorithm specification
- Missing journal file permissions
- Firewall blocking TCP/53 (needed for updates)
- SELinux/AppArmor restrictions
- Zone file serial number not incrementing

Here's a verified nsupdate sequence:

nsupdate -k Ksub.example.com.+157+12345.private
> server 192.168.1.100
> zone sub.example.com
> update add test.sub.example.com. 300 A 192.168.1.50
> show
> send
> quit

Remember to verify with dig after update:

dig @dns-server test.sub.example.com A +short

The SERVFAIL error during DNS dynamic updates typically indicates a server-side rejection of the update request, despite the client successfully authenticating. From the logs, we can see the authentication succeeds (request has valid signature) but the update itself fails.

For successful TSIG-authenticated updates, these elements must align:

// named.conf.local minimum working example
key "sub.example.com." {
    algorithm hmac-md5;
    secret "base64-encoded-key-here";
};

zone "sub.example.com" {
    type master;
    file "/etc/bind/dynamic/sub.example.com.db";
    allow-update { key "sub.example.com."; };
    journal "/var/lib/bind/sub.example.com.db.jnl";
};

File Structure Considerations

The zone file must exist before the first update attempt. Create it with a minimal SOA record:

; /etc/bind/dynamic/sub.example.com.db
$ORIGIN .
$TTL 86400
sub.example.com    IN SOA ns1.example.com. admin.example.com. (
                        2023080601 ; serial
                        3600       ; refresh
                        900        ; retry
                        604800     ; expire
                        86400 )    ; minimum
                    NS ns1.example.com.

Directory Permissions

BIND needs write access to both the zone file and journal location:

sudo chown bind:bind /etc/bind/dynamic
sudo chmod 775 /etc/bind/dynamic
sudo touch /etc/bind/dynamic/sub.example.com.db
sudo chown bind:bind /etc/bind/dynamic/sub.example.com.db

The client-side update script needs these improvements:

# Working nsupdate command file
server dns-server.example.com
key sub.example.com. hmac-md5 base64-key-here
zone sub.example.com.
update add test.sub.example.com. 300 A 192.168.1.100
show
send

Enable detailed logging in named.conf:

logging {
    channel update_debug {
        file "/var/log/bind/update.log" versions 3 size 5m;
        severity debug 3;
        print-category yes;
        print-severity yes;
        print-time yes;
    };
    category update { update_debug; };
    category security { update_debug; };
};
  • Clock Synchronization: TSIG requires time sync within 5 minutes
  • Key Encoding: Ensure the key in named.conf matches EXACTLY what dnssec-keygen generated
  • Zone File Ownership: The bind user must have write permissions to both the zone file and its parent directory

For production environments, consider these enhancements:

// More secure configuration
options {
    directory "/var/cache/bind";
    allow-update-forwarding { none; };
    update-check-ksk yes;
    dnssec-validation auto;
};

zone "sub.example.com" {
    type master;
    file "/etc/bind/dynamic/sub.example.com.db";
    allow-update { 
        key "sub.example.com."; 
        // Can also restrict by IP:
        // 192.168.1.0/24; 
    };
    update-policy {
        grant sub.example.com. name test.sub.example.com. A;
    };
};