Last active
March 21, 2026 16:31
-
-
Save syncip/75289540aad4afa2f6fe27d1d3366acd to your computer and use it in GitHub Desktop.
IPv64 DynDNS Updater (Bash): prüft IPv4/IPv6 via icanhazip, vergleicht mit DNS und updated nur bei Änderung. Optional ntfy-Benachrichtigungen. Keine State-Dateien nötig, ideal für dynamische IPs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -u | |
| ######################################## | |
| # Konfiguration | |
| ######################################## | |
| # IPv64 | |
| ENABLE_IPV64=true | |
| IPV64_DOMAIN="XXX.ipv64.net" | |
| IPV64_TOKEN="XXXXXXXXXXXXXXXXXXXXXXXXXXXX" | |
| IPV64_UPDATE_URL="https://ipv64.net/nic/update" | |
| # IPv4 | |
| ENABLE_IPV4=true | |
| IPV4_CHECK_URL="https://ipv4.icanhazip.com" | |
| # IPv6 | |
| ENABLE_IPV6=false | |
| IPV6_CHECK_URL="https://ipv6.icanhazip.com" | |
| # IPv64 autoritativer DNS | |
| ENABLE_DNS_CHECK=true | |
| DNS_SERVER_V4="ns1.ipv64.net" | |
| DNS_SERVER_V6="ns1.ipv64.net" | |
| # ntfy | |
| ENABLE_NTFY=true | |
| NTFY_URL="https://ntfy.sh/dein-topic" | |
| NTFY_TITLE_PREFIX="IPv64 DDNS" | |
| # Sonstiges | |
| CURL_TIMEOUT=15 | |
| DIG_TIMEOUT=5 | |
| ######################################## | |
| # Funktionen | |
| ######################################## | |
| log() { | |
| printf '%s %s\n' "$(date '+%F %T')" "$*" | |
| } | |
| send_ntfy() { | |
| local title="$1" | |
| local message="$2" | |
| local priority="${3:-default}" | |
| [ "$ENABLE_NTFY" = true ] || return 0 | |
| curl -fsS \ | |
| -H "Title: ${NTFY_TITLE_PREFIX} - ${title}" \ | |
| -H "Priority: ${priority}" \ | |
| -d "$message" \ | |
| "$NTFY_URL" >/dev/null 2>&1 || true | |
| } | |
| fetch_ipv4() { | |
| curl -4 -fsS --max-time "$CURL_TIMEOUT" "$IPV4_CHECK_URL" | tr -d '[:space:]' | |
| } | |
| fetch_ipv6() { | |
| curl -6 -fsS --max-time "$CURL_TIMEOUT" "$IPV6_CHECK_URL" | tr -d '[:space:]' | |
| } | |
| fetch_dns_ipv4() { | |
| dig @"$DNS_SERVER_V4" +short A "$IPV64_DOMAIN" +time="$DIG_TIMEOUT" +tries=1 | head -n1 | tr -d '[:space:]' | |
| } | |
| fetch_dns_ipv6() { | |
| dig @"$DNS_SERVER_V6" +short AAAA "$IPV64_DOMAIN" +time="$DIG_TIMEOUT" +tries=1 | head -n1 | tr -d '[:space:]' | |
| } | |
| update_ipv64() { | |
| local ipv4="$1" | |
| local ipv6="$2" | |
| local url="${IPV64_UPDATE_URL}?key=${IPV64_TOKEN}&domain=${IPV64_DOMAIN}" | |
| if [ "$ENABLE_IPV4" = true ] && [ -n "$ipv4" ]; then | |
| url="${url}&ip=${ipv4}" | |
| fi | |
| if [ "$ENABLE_IPV6" = true ] && [ -n "$ipv6" ]; then | |
| url="${url}&ip6=${ipv6}" | |
| fi | |
| curl --retry 5 --retry-delay 3 --retry-all-errors -fsS --max-time "$CURL_TIMEOUT" "$url" | |
| } | |
| ######################################## | |
| # Start | |
| ######################################## | |
| if [ "$ENABLE_IPV64" != true ]; then | |
| log "IPv64 deaktiviert." | |
| exit 0 | |
| fi | |
| if [ "$ENABLE_IPV4" != true ] && [ "$ENABLE_IPV6" != true ]; then | |
| log "Weder IPv4 noch IPv6 aktiviert." | |
| exit 0 | |
| fi | |
| CURRENT_IPV4="" | |
| CURRENT_IPV6="" | |
| DNS_IPV4="" | |
| DNS_IPV6="" | |
| NEED_UPDATE=false | |
| CHANGED_IPV4=false | |
| CHANGED_IPV6=false | |
| # IPv4 | |
| if [ "$ENABLE_IPV4" = true ]; then | |
| if ! CURRENT_IPV4="$(fetch_ipv4)"; then | |
| log "Fehler beim Abrufen der aktuellen IPv4." | |
| send_ntfy "Fehler" "Fehler beim Abrufen der aktuellen IPv4 über ${IPV4_CHECK_URL}" urgent | |
| exit 1 | |
| fi | |
| if [ "$ENABLE_DNS_CHECK" = true ]; then | |
| if ! DNS_IPV4="$(fetch_dns_ipv4)"; then | |
| log "Fehler beim DNS-Check der IPv4 bei IPv64." | |
| send_ntfy "Fehler" "Fehler beim DNS-Check der IPv4 für ${IPV64_DOMAIN}" urgent | |
| exit 1 | |
| fi | |
| if [ "$CURRENT_IPV4" != "$DNS_IPV4" ]; then | |
| NEED_UPDATE=true | |
| CHANGED_IPV4=true | |
| fi | |
| else | |
| NEED_UPDATE=true | |
| CHANGED_IPV4=true | |
| fi | |
| fi | |
| # IPv6 | |
| if [ "$ENABLE_IPV6" = true ]; then | |
| if ! CURRENT_IPV6="$(fetch_ipv6)"; then | |
| log "Fehler beim Abrufen der aktuellen IPv6." | |
| send_ntfy "Fehler" "Fehler beim Abrufen der aktuellen IPv6 über ${IPV6_CHECK_URL}" urgent | |
| exit 1 | |
| fi | |
| if [ "$ENABLE_DNS_CHECK" = true ]; then | |
| if ! DNS_IPV6="$(fetch_dns_ipv6)"; then | |
| log "Fehler beim DNS-Check der IPv6 bei IPv64." | |
| send_ntfy "Fehler" "Fehler beim DNS-Check der IPv6 für ${IPV64_DOMAIN}" urgent | |
| exit 1 | |
| fi | |
| if [ "$CURRENT_IPV6" != "$DNS_IPV6" ]; then | |
| NEED_UPDATE=true | |
| CHANGED_IPV6=true | |
| fi | |
| else | |
| NEED_UPDATE=true | |
| CHANGED_IPV6=true | |
| fi | |
| fi | |
| if [ "$NEED_UPDATE" != true ]; then | |
| log "Kein Update nötig." | |
| exit 0 | |
| fi | |
| if RESPONSE="$(update_ipv64 "$CURRENT_IPV4" "$CURRENT_IPV6" 2>&1)"; then | |
| MSG="IPv64 Update erfolgreich | |
| Domain: $IPV64_DOMAIN" | |
| if [ "$CHANGED_IPV4" = true ]; then | |
| MSG="${MSG} | |
| IPv4: ${DNS_IPV4:-leer} -> ${CURRENT_IPV4}" | |
| fi | |
| if [ "$CHANGED_IPV6" = true ]; then | |
| MSG="${MSG} | |
| IPv6: ${DNS_IPV6:-leer} -> ${CURRENT_IPV6}" | |
| fi | |
| log "$MSG" | |
| send_ntfy "Update" "$MSG" default | |
| else | |
| log "IPv64 Update fehlgeschlagen: $RESPONSE" | |
| send_ntfy "Fehler" "IPv64 Update fehlgeschlagen: | |
| $RESPONSE" urgent | |
| exit 1 | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment