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

128 lines
3.7 KiB
Markdown

+++
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