Table of Contents

Bind dns server

Configuration

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 schwarz.in.philpep.org. {                
  algorithm hmac-sha512;        
  secret "XXX XXX==";
};             

zone "philpep.org" {
  type master;                                                                                                                                                                           
  file "zones/philpep.org.db";                                                                                                                                                           
  allow-transfer {                                                                                                                                                                       
    key schwarz.in.philpep.org.;                                                                                                                                                         
  };                                                                                                                                                                                     
  also-notify {
    192.168.96.5 key schwarz.in.philpep.org.;
  };                            
};  

This configure zone “philpep.org” with one secondary dns server on “192.168.96.5”. 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.

#!/bin/sh
 
set -e
 
PATH=/sbin:/bin:/usr/sbin:/usr/bin
export PATH
 
IFACE="pppoe-wan"
DNS_SERVER="5.39.85.37"
DNS_NAME="foo.philpep.org"
DNS_TTL="300" # 5 minutes
DNS_KEY="/root/K0foo.philpep.org.+157+00000.private"
 
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 - https://ifconfig.co/ip)
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
send
EOF
  $LOGGER "update dns from '$old_addr' to '$addr': done"
fi

On server side, only allow the key to update A entry for “foo.example.com”

key foo.philpep.org. {
  algorithm hmac-sha512;
  secret "XXX XXX==";
};

zone "philpep.org" {
  # [...]
  update-policy {
    grant foo.philpep.org. name foo.philpep.org. 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
/etc/letsencrypt/rfc2136.ini
dns_rfc2136_server = 192.168.62.2
dns_rfc2136_port = 53
dns_rfc2136_name = foo.in.philpep.org.
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 foo.in.philpep.org. {
  algorithm hmac-sha512;
  secret "XXX XXX==";
};

zone "philpep.org" {
  # [...]
  update-policy {
    # allow foo.in.philpep.org and/or *.foo.in.philpep.org
    grant foo.philpep.org. name _acme-challenge.foo.in.philpep.org. txt;
    # allow all subdomain of in.philpep.org
    # grant foo.in.philpep.org. zonesub txt;
  };
};

Then back on client, issue the certificate with:

certbot certonly --dns-rfc2136 --dns-rfc2136-credentials /etc/letsencrypt/rfc2136.ini -d foo.in.philpep.org -d '*.foo.in.philpep.org'