User Tools

Site Tools


Bind dns server


options {
  auth-nxdomain no;
  recursion no;
  listen-on-v6 port 53 { any; };
  listen-on port 53 { any; };
  notify explicit;
  rate-limit {
    responses-per-second 10;

Zone configuration

key {                
  algorithm hmac-sha512;        
  secret "XXX XXX==";

zone "" {
  type master;                                                                                                                                                                           
  file "zones/";                                                                                                                                                           
  allow-transfer {                                                                                                                                                                       
  also-notify { key;

This configure zone “” with one secondary dns server on “”. Primary and secondary master use a symetric hmac-sha512 keys. Theses keys can be generated with dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST keyname.

DNS zone transfer occur in two times:

  1. Master notifies all secondary servers about the new zone serial
  2. Secondary issue a AXFR (full) or IXFR (incremental) zone transfer

Bind can be used for secondary servers as well, but you might consider using NSD instead.

Dynamic DNS update

You can dynamically modify a zone using RFC 2136, at time of writting, only bind and knot server implement this. But only Bind implement fine grained update policy.

DNS update script

I use this script running in crontab every minutes on a router behind a dynamic ip address.

set -e
export PATH
DNS_TTL="300" # 5 minutes
LOGGER="logger -t dyndns"
# address on $IFACE
# addr=$(ip a show $PPP_IFACE | awk '$1 = "inet" && $3 == "peer" { print $2 }')
# use an external service
# addr=$(wget -O -
old_addr=$(dig @$DNS_SERVER +short +time=1 +tries=3 $DNS_NAME) # WAIT max 3 seconds
if [ "$addr" != "$old_addr" ]; then
  $LOGGER "update dns from '$old_addr' to '$addr'"
  cat << EOF | nsupdate -t 5 -k $DNS_KEY
server $DNS_SERVER
update delete $DNS_NAME A
update add $DNS_NAME $DNS_TTL A $addr
  $LOGGER "update dns from '$old_addr' to '$addr': done"

On server side, only allow the key to update A entry for “”

key {
  algorithm hmac-sha512;
  secret "XXX XXX==";

zone "" {
  # [...]
  update-policy {
    grant name a;

letsencrypt acme dns challenge

This is useful to issue letsencrypt certificates for internal domain names (belong a public domain), or for wildcard certificates.

On client side, install and configure certbot-dns-rfc2136:

apt-get install certbot python3-certbot-dns-rfc2136
dns_rfc2136_server =
dns_rfc2136_port = 53
dns_rfc2136_name =
dns_rfc2136_secret = XXX XXX==
dns_rfc2136_algorithm = HMAC-SHA512

Ensure to chmod 600 /etc/letsencrypt/rfc2136.ini

On server side, configure the secret key and add a grant policy:

key {
  algorithm hmac-sha512;
  secret "XXX XXX==";

zone "" {
  # [...]
  update-policy {
    # allow and/or *
    grant name txt;
    # allow all subdomain of
    # grant zonesub txt;

Then back on client, issue the certificate with:

certbot certonly --dns-rfc2136 --dns-rfc2136-credentials /etc/letsencrypt/rfc2136.ini -d -d '*'
soft/bind.txt · Last modified: 2019/07/15 00:57 by phil