116 lines
6.2 KiB
Bash
Executable File
116 lines
6.2 KiB
Bash
Executable File
#!/usr/bin/env sh
|
||
|
||
#################################################################################################################
|
||
# DNS challenge Script für ipv64.net
|
||
# Das Script soll genutzt werden um die DNS-01 Challenge per EXEC Methode über
|
||
# den "Let’s Encrypt client and ACME library written in Go" (LEGO) und die API von ipv64.net
|
||
# LEGO Dokumentation: https://go-acme.github.io/lego/dns/exec/
|
||
# API Dokumentation: https://ipv64.net/dyndns_updater_api.php
|
||
# Mit dem Nginx Proxy Manager ist das Skript nicht kompatibel, da der NPM die EXEC Methode nicht unterstützt.
|
||
# Daher wurde das Skript für die Nutzung mit Traefik umgesetzt.
|
||
# Traefik Dokumentation: https://doc.traefik.io/traefik/https/acme/#providers
|
||
# Getestet wurde es mit Traefik 2.9 aber auch 1.7 sollte es laut Dokumentation unterstützen:
|
||
# https://doc.traefik.io/traefik/v1.7/configuration/acme/#provider
|
||
#################################################################################################################
|
||
# Es wird dringend empfohlen mit neuem certresolver, nur einem Dienst und dem Staging CA zu arbeiten.
|
||
#################################################################################################################
|
||
|
||
# Der Traefik Container kennt curl nicht, mit folgendem Befehl wird es installiert,
|
||
# Tipp hierfür habe ich von: https://community.traefik.io/t/using-external-program-for-dns-challenge-and-lets-encrypt/8072/12
|
||
apk add -U curl
|
||
|
||
# Alle Konfigurationsparameter werden aus der config.env Datei gelesen, diese Datei sowie das Skript müssen im
|
||
# Container bekannt sein. Ich habe beides in einem Configordner, den ich nach /etc/traefik durchreiche.
|
||
# für debug auf der eigenen Umgebung $configfile anpassen oder eine Kopie/Link der configfile auch lokal
|
||
# unter /etc/traefik ablegen
|
||
configfile="/etc/traefik/config.env"
|
||
|
||
if [ ! -r "$configfile" ]; then
|
||
echo "Configfile: $configfile does not exist or isn't readable"
|
||
exit 1
|
||
fi
|
||
|
||
# aus der configfile wird eine Zeile gesucht die mit "apitoken=" beginnt, der text direkt darauf gefolgt wird als apitoken
|
||
# interpretiert und sollte nicht leer sein, sonst bricht das skript ab.
|
||
# Der API-Token wird auf ipv64.net im Reiter "DynDNS" rechts im Account Status Block unter "API Key" generiert und angezeigt.
|
||
# Alternativ sieht man es auch an gleicher Stelle, wenn man auf den Account selbst geht.
|
||
# da API Aufrufe auf 64/24h limitiert sind, könnte man erste Versuche mit falschem Token machen
|
||
# Traefik würde dann folgende Fehlermeldung werfen (zumindest bei Loglevel debug):
|
||
# level=debug msg="fd=_acme-challenge.meinesub.domain.ipv64.net, domain=domain.ipv64.net, praefix=_acme-challenge.meinesub, content=abc..xyz"
|
||
# direkt gefolgt von:
|
||
# level=debug msg="{\"status\":\"401 Unauthorized\",\"info\":\"Unauthorized\"}"
|
||
# ich nutze graylog und filter dann nach "praefix"
|
||
apitoken=$(grep ^"apitoken=" "$configfile" | sed -e "s/apitoken=//")
|
||
|
||
if [ -z "$apitoken" ]; then
|
||
echo "apitoken is not defined in $configfile"
|
||
exit 1
|
||
fi
|
||
|
||
|
||
set -e
|
||
# hier wird auf den ersten Parameter geprüft, present und cleanup gehören zum LEGO, debug habe ich ergänzt um eine Ausgabe ohne API Aufruf zu machen
|
||
# bis auf den curl Aufruf sind alle drei Blöcke gleich, daher wird alles nur einmal beschrieben
|
||
case "$1" in
|
||
"present")
|
||
echo "Present"
|
||
# Der FQDN im zweiten Übergabeparameter enthält am Ende ein Punkt, dieser wird nun entfernt, da sonst der API Aufruf nicht funktioniert.
|
||
full_domain=${2%"."}
|
||
# Nun wird von rechts beginnend 3 mal alles bis zum Punkt gemerkt, und so die registrierte dyndns Domain ermittelt. "sub.domain.ipv64.net" wird "domain.ipv64.net"
|
||
domain=$(echo $full_domain | rev | cut -d . -f -3 | rev)
|
||
# Daraus wird nun der Präfix für den DNS Eintrag ermittelt indem beim full_domain von rechts ausgehend die Domain abgeschnitten wird. Aus "sub.domain.ipv64.net" wird "sub."
|
||
praefix=${full_domain%"$domain"}
|
||
# vom präefix wird noch der rechts . entfernt, also aus "sub." wird "sub"
|
||
praefix=${praefix%"."}
|
||
# Nun werden die einzelnen Bestandteile des API Calls analog der API Dokumentation von ipv64.net vorbereitet.
|
||
auth_h="Authorization: Bearer $apitoken"
|
||
# die Domain mus mit einer registrierten Domain übereinstimmen, der relevante Parameter ist "add_record"
|
||
domain_pl="add_record=$domain"
|
||
praefix_pl="praefix=$praefix"
|
||
# Es wird ein DNS Record vom Typ TXT benötigt
|
||
type_pl="type=TXT"
|
||
# Und der Inhalt aus dem dritten Parameter soll als Wert zum DNSRECORD gesetzt werden.
|
||
content_pl="content=$3"
|
||
# Hier die Ausgabe für Debuging zwecke, um den Aufruf im Log zu finden
|
||
echo "fd=$full_domain, domain=$domain, praefix=$praefix, $content_pl"
|
||
# Bei der Anlage wird ein POST abgesetzt um den Eintrag abzusetzen.
|
||
curl -s -X POST -d "$domain_pl" -d "$praefix_pl" -d "$type_pl" -d "$content_pl" -H "$auth_h" https://ipv64.net/api
|
||
;;
|
||
"cleanup")
|
||
full_domain=${2%"."}
|
||
domain=$(echo $full_domain | rev | cut -d . -f -3 | rev)
|
||
praefix=${full_domain%"$domain"}
|
||
praefix=${praefix%"."}
|
||
auth_h="Authorization: Bearer $apitoken"
|
||
# Zum entfernen ist der API Paramter "del_record" notwendig
|
||
domain_pl="del_record=$domain"
|
||
praefix_pl="praefix=$praefix"
|
||
type_pl="type=TXT"
|
||
content_pl="content=$3"
|
||
echo "fd=$full_domain, domain= $domain, praefix=$praefix, $content_pl"
|
||
# Beim der Aufräumen wird ein DELETE abgesetzt um den Eintrag wieder zu entfernen
|
||
curl -s -X DELETE -d "$domain_pl" -d "$praefix_pl" -d "$type_pl" -d "$content_pl" -H "$auth_h" https://ipv64.net/api
|
||
;;
|
||
"debug")
|
||
echo "Debug"
|
||
full_domain=${2%"."}
|
||
domain=$(echo $full_domain | rev | cut -d . -f -3 | rev)
|
||
praefix=${full_domain%"$domain"}
|
||
praefix=${praefix%"."}
|
||
auth_h="Authorization: Bearer $apitoken"
|
||
domain_pl="add_record=$domain"
|
||
praefix_pl="praefix=$praefix"
|
||
type_pl="type=TXT"
|
||
content_pl="content=$3"
|
||
##########
|
||
# Achtung: im Debugmodus wird der Token im log ausgegeben, ggf. nach debug einen neuen API Key generieren
|
||
##########
|
||
echo "fd=$full_domain, domain=$domain, praefix=$praefix, $content_pl $auth_h"
|
||
;;
|
||
*)
|
||
# Falls das Skript mit einem ungültigen ersten Paramter aufgerufen wird, bricht es mit einem Fehler ab.
|
||
echo "OOPS"
|
||
exit 1
|
||
;;
|
||
esac
|