+++
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 RFC[2136](https://datatracker.ietf.org/doc/html/rfc2136.html).

## 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** :


```bash
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](https://datatracker.ietf.org/doc/html/rfc8738) is again something simple but robust: [dehydrated](https://github.com/dehydrated-io/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](https://datatracker.ietf.org/doc/html/rfc2845.html)

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

* https://doc.powerdns.com/authoritative/dnsupdate.html
* https://doc.powerdns.com/authoritative/tsig.html