yann.verry.org/content/posts/dns/dnsupdate/index.en.md

3.7 KiB

+++ title = "A little dynamic in my DNS" date = 2022-05-28T18:40:11+02:00 draft = false categories = ["dns"] tags = ["dns"] author = "Yann Verry" description = "" +++

Today in the computer world almost 100% works with API. DNS servers are no exception, for example with PowerDNS without surprise there is an API but let's explore what works very well since years: DNSUpdate with its little RFC2136.

DynDNS

In 2022 many ISPs do not provide fixed IPv4 or IPv6. So it changes regularly depending on a power cut or more from your operator. There are many online services to do this job via an API, maybe even your registrar. But when you host your own DNS, it is easier to use nsupdate which is often already installed on your machine when you need to dig into the question. Otherwise it is present for example via the bind9-dnsutils package under debian.

So we will make a small script that will get its ipv4 and v6 public and update them, here on the server dnsupdate.verry.org :

DOMAIN="verry.org"
HOST="raoul.verry.org"
ORIG_IPv4=$(dig +short a $HOST @dnsupdate.verry.org)
ORIG_IPv6=$(dig +short aaaa $HOST @dnsupdate.verry.org)
IPv4=$(curl -4 https://ip.verry.org)
IPv6=$(curl -6 https://ip.verry.org)
SERVER=$(dig +short aaaa dnsupdate.verry.org)

if [ "$ORIG_IPv4" != "$IPv4" ] || [ "$ORIG_IPv6" != "$IPv6" ];
then

nsupdate -y '<algo ici hmac-sha512>:<tsig name>:<ma clef TSIG base64>' <<!
server $SERVER 53
zone $DOMAIN
update delete $HOST. A
update delete $HOST. AAAA
update add $HOST. 3600 A $IPv4
update add $HOST. 3600 AAAA $IPv6
send
!

fi

Let's Encrypt

A second use case I use is to obtain a let's encrypt certificate via a DNS challenge. My own ACME is again something simple but robust: dehydrated

With dehydrated it's possible to add a hook in config HOOK=/etc/dehydrated/hook/hook.sh.

This script need to call two function deploy_challenge() :

deploy_challenge() {
  nsupdate -y '<algo ici hmac-sha512>:<tsig name>:<ma clef TSIG base64>' <<!
  server fd00::42:3 53
  zone ${DOMAIN}
  update add _acme-challenge.${DOMAIN} 60 TXT ${TOKEN_VALUE}
  send
  !
  
  sleep 3
}

and clean_challenge() :

clean_challenge() {
  nsupdate -y '<algo ici hmac-sha512>:<tsig name>:<ma clef TSIG base64>' <<!
  server fd00::42:3 53
  zone ${DOMAIN}
  update delete _acme-challenge.${DOMAIN} TXT ${TOKEN_VALUE}
  send
  !
}

The DNS server (dnsupdate.verry.org) is fd00::42:3 in private ipv6 address (vpn wireguard tunnel)

Setup

Let's go to the server side setup now. Without surprise I will show you how it is done with PowerDNS.

TSIG

All exchanges are done securely with TSIG RFC2845

You have to generate it on your master by specifying the algorithm hmac-sha512 and a name:

pdnsutil generate-tsig-key tsig.verry.org hmac-sha512

We can finely authorize domain by domain, the right that we will put on this key, for example the right to make changes in the zone (dnsupdate) or to transfer this zone (axfr).

pdnsutil show-zone verry.org

On the metadata side we can see:

Zone has following allowed TSIG key(s): tsig.verry.org
Metadata items:
	TSIG-ALLOW-AXFR	tsig.verry.org
	TSIG-ALLOW-DNSUPDATE	tsig.verry.org

DNSUpdate

Let's add the authorization to do dnsupdate by whitelisting an IP. In /etc/powerdns/pdns.d/dnsupdate.conf :

allow-dnsupdate-from=::/0
dnsupdate=yes

A small restart of powerdns and tada!

Link