Bei der DNS-01-Challenge weisen Sie die Kontrolle über eine Domain mit einem TXT-Eintrag statt einer Webseite nach. Nur so erhalten Sie ein Wildcard-Zertifikat, und es funktioniert auch für Server, die aus dem Internet nicht erreichbar sind. Mit diesem Hook veröffentlicht certbot diesen Eintrag über die NameOcean API.
POST /ssl/example.com). Nutzen Sie diese Anleitung, wenn Ihr Server sein eigenes Zertifikat beziehen und verlängern soll.dns:read und dns:write. Beschränken Sie ihn nach Möglichkeit auf die IP-Adresse des Servers.# curl -fsSL https://nameocean.net/install.sh | sh # curl -fsSL https://nameocean.net/developers/guides/letsencrypt-dns-01/nameocean-hook.sh \ -o /etc/letsencrypt/nameocean-hook.sh # chmod 700 /etc/letsencrypt/nameocean-hook.sh # echo 'NAMEOCEAN_API_KEY=no_live_…' > /etc/letsencrypt/nameocean.env # chmod 600 /etc/letsencrypt/nameocean.env
Der Schlüssel liegt in einer Datei, die nur root lesen kann; die gespeicherten Verlängerungseinstellungen von certbot enthalten ihn nie.
# certbot certonly --manual --preferred-challenges dns \
--manual-auth-hook "/etc/letsencrypt/nameocean-hook.sh auth" \
--manual-cleanup-hook "/etc/letsencrypt/nameocean-hook.sh cleanup" \
-d example.com -d "*.example.com"
Für jeden Namen ermittelt der Hook die zugehörige Zone unter Ihren NameOcean-Zonen, legt _acme-challenge als TXT-Eintrag an und wartet, bis alle vier Nameserver ihn ausliefern – meist innerhalb von zehn Sekunden. Nach der Prüfung löscht der Cleanup-Schritt genau den Eintrag, den er angelegt hat. example.com und *.example.com verwenden beide _acme-challenge.example.com; die beiden Werte werden nebeneinander veröffentlicht.
certbot speichert die Hooks zusammen mit dem Zertifikat, sodass sein Timer es auf dieselbe Weise verlängert. Testen Sie das einmal:
# certbot renew --dry-run
Jeder Eintrag, den der Hook anlegt und löscht, erscheint unter Dashboard → Aktivität mit dem verwendeten Schlüssel und löst die Webhook-Ereignisse dns.record.created und dns.record.deleted aus.
Lesen Sie ihn, bevor Sie ihn als root ausführen. Er ruft nur die nameocean CLI und dig auf.
#!/bin/sh
# certbot DNS-01 hooks for NameOcean DNS:
# --manual-auth-hook "/etc/letsencrypt/nameocean-hook.sh auth"
# --manual-cleanup-hook "/etc/letsencrypt/nameocean-hook.sh cleanup"
# Needs the nameocean CLI and an API key with dns:write, in /etc/letsencrypt/nameocean.env:
# NAMEOCEAN_API_KEY=no_live_...
set -e
[ -f /etc/letsencrypt/nameocean.env ] && . /etc/letsencrypt/nameocean.env && export NAMEOCEAN_API_KEY
# the zone CERTBOT_DOMAIN is in: the longest of your zones it ends with
zone="$NAMEOCEAN_ZONE"
if [ -z "$zone" ]; then
for z in $(nameocean dns ls --json | sed -n 's/.*"name": *"\([^"]*\)".*/\1/p'); do
case "$CERTBOT_DOMAIN" in "$z" | *".$z") [ ${#z} -gt ${#zone} ] && zone="$z" ;; esac
done
fi
[ -n "$zone" ] || { echo "no NameOcean DNS zone for $CERTBOT_DOMAIN" >&2; exit 1; }
name="_acme-challenge"
[ "$CERTBOT_DOMAIN" = "$zone" ] || name="_acme-challenge.${CERTBOT_DOMAIN%.$zone}"
case "$1" in
auth)
id=$(nameocean dns add "$zone" TXT "$name" "$CERTBOT_VALIDATION" --ttl 5m --json \
| sed -n 's/.*"id": *\([0-9][0-9]*\).*/\1/p' | head -n 1)
[ -n "$id" ] || { echo "could not add the TXT record" >&2; exit 1; }
echo "$id" # certbot passes this to the cleanup hook as CERTBOT_AUTH_OUTPUT
# wait until all four nameservers answer with it (usually a few seconds)
for i in $(seq 1 60); do
n=0
for ns in ns1 ns2 ns3 ns4; do
dig +short TXT "$name.$zone" "@$ns.nameocean.net" | grep -q -- "$CERTBOT_VALIDATION" && n=$((n + 1))
done
[ "$n" -eq 4 ] && exit 0
sleep 2
done
echo "the TXT record is not on every nameserver after 2 minutes" >&2
exit 1
;;
cleanup)
[ -z "$CERTBOT_AUTH_OUTPUT" ] || nameocean dns rm "$zone" TXT "$CERTBOT_AUTH_OUTPUT"
;;
*)
echo "usage: $0 auth|cleanup" >&2
exit 2
;;
esac
Der Hook führt zwei API-Aufrufe aus, die Sie aus jedem ACME-Client und jeder Sprache heraus nutzen können:
$ curl -X POST https://nameocean.net/api/v1/dns/example.com/records \ -H "Authorization: Bearer $NAMEOCEAN_API_KEY" -H "Content-Type: application/json" \ -d '{"type": "TXT", "hostname": "_acme-challenge", "text": "<validation>", "ttl": "5m"}' {"id": 4190, "type": "TXT", "hostname": "_acme-challenge", …} $ curl -X DELETE https://nameocean.net/api/v1/dns/example.com/records/TXT/4190 \ -H "Authorization: Bearer $NAMEOCEAN_API_KEY"