Dynamic DNS (DDNS) allows automated updates to DNS records, essential for servers with changing IP addresses, auto-scaling infrastructure, and service discovery. TSIG (Transaction Signature) keys provide secure authentication for these updates, preventing unauthorized DNS modifications. This guide covers configuring DDNS with BIND and nsupdate using TSIG authentication.
Generating TSIG Keys
# Generate a TSIG key for DDNS updates
tsig-keygen -a hmac-sha256 ddns-key > /etc/bind/ddns-key.conf
# Output looks like:
# key "ddns-key" {
# algorithm hmac-sha256;
# secret "base64-encoded-secret==";
# };
BIND Configuration
# /etc/bind/named.conf
include "/etc/bind/ddns-key.conf";
zone "example.com" {
type master;
file "/var/lib/bind/example.com.zone";
allow-update { key "ddns-key"; }; # Allow DDNS with TSIG
journal "/var/lib/bind/example.com.jnl"; # Journal file for changes
};
# For reverse DNS
zone "0.168.192.in-addr.arpa" {
type master;
file "/var/lib/bind/192.168.0.rev";
allow-update { key "ddns-key"; };
};
Sending Updates with nsupdate
# Interactive mode
nsupdate -k /etc/bind/ddns-key.conf
> server ns1.example.com
> zone example.com
> update delete myhost.example.com A
> update add myhost.example.com 300 A 192.168.0.100
> send
> quit
# One-liner for scripts
nsupdate -k /etc/bind/ddns-key.conf /dev/null)
if [ "$CURRENT_IP" = "$LAST_IP" ]; then
exit 0 # No change
fi
echo "[$(date)] IP changed from $LAST_IP to $CURRENT_IP" >> /var/log/ddns.log
nsupdate -k "$KEY_FILE" "$IP_FILE"
echo "[$(date)] DNS updated successfully" >> /var/log/ddns.log
else
echo "[$(date)] DNS update FAILED" >> /var/log/ddns.log
fi
# Crontab: check every 5 minutes
*/5 * * * * /usr/local/bin/ddns-update.sh
Per-Host TSIG Keys
# Generate separate keys for each host
tsig-keygen -a hmac-sha256 host1-key > /etc/bind/host1-key.conf
tsig-keygen -a hmac-sha256 host2-key > /etc/bind/host2-key.conf
# Restrict updates per host
zone "example.com" {
type master;
file "/var/lib/bind/example.com.zone";
update-policy {
grant host1-key name host1.example.com A AAAA;
grant host2-key name host2.example.com A AAAA;
};
};
PowerDNS DDNS
# PowerDNS supports DDNS via the API
# Enable API in pdns.conf
api=yes
api-key=your-api-key
webserver=yes
# Update via API
curl -X PATCH http://localhost:8081/api/v1/servers/localhost/zones/example.com. \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"rrsets": [{"name": "myhost.example.com.", "type": "A", "ttl": 300, "changetype": "REPLACE", "records": [{"content": "192.168.0.100", "disabled": false}]}]}'
Best Practices
- Use TSIG keys (not IP-based ACLs) for DDNS authentication
- Generate separate TSIG keys per host using
update-policyto limit what each key can modify - Set low TTL (60-300 seconds) on dynamically updated records
- Log all DDNS updates for audit purposes
- Secure TSIG key files with restrictive permissions (600)
- Use the journal file system in BIND for efficient incremental updates