traefik_v2x/config/ipv64-dns-challenge.sh

116 lines
6.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 "Lets 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