diff --git a/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_functions.sh b/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_functions.sh index 5afa5547c7877..c07a859740e98 100644 --- a/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_functions.sh +++ b/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_functions.sh @@ -8,6 +8,9 @@ # extended and partial rewritten #.2014-2018 Christian Schoenebeck # +# 2026 Wayne King +# Added use_api_check option for providers with proxied records (e.g., Cloudflare) +# # function timeout # copied from http://www.ict.griffith.edu.au/anthony/software/timeout.sh # @author Anthony Thyssen 6 April 2011 @@ -985,9 +988,40 @@ get_registered_ip() { [ $is_glue -eq 1 -a -z "$BIND_HOST" ] && write_log 14 "Lookup of glue records is only supported using BIND host" write_log 7 "Detect registered/public IP" + # Ensure use_api_check defaults to 0 if not set + [ -z "$use_api_check" ] && use_api_check=0 + # set correct regular expression [ $use_ipv6 -eq 0 ] && __REGEX="$IPV4_REGEX" || __REGEX="$IPV6_REGEX" + # Attempt API check if enabled + if [ "$use_api_check" -eq 1 ]; then + local __SCRIPT + if [ -n "$update_script" ]; then + __SCRIPT="$update_script" + elif [ "$service_name" != "custom" ] && [ -n "$service_name" ]; then + local __SANITIZED + __SANITIZED=$(echo "$service_name" | sed 's/[.-]/_/g') + __SCRIPT="/usr/lib/ddns/update_${__SANITIZED}.sh" + fi + if [ -n "$__SCRIPT" ] && [ -f "$__SCRIPT" ]; then + write_log 7 "Using provider API for registered IP check via '$__SCRIPT'" + REGISTERED_IP="" + GET_REGISTERED_IP=1 + . "$__SCRIPT" + __ERR=$? + unset GET_REGISTERED_IP + if [ $__ERR -eq 0 ] && [ -n "$REGISTERED_IP" ]; then + write_log 7 "Registered IP '$REGISTERED_IP' detected via provider API" + [ -z "$IPFILE" ] || echo "$REGISTERED_IP" > "$IPFILE" + eval "$1=\"$REGISTERED_IP\"" + return 0 + else + write_log 4 "API check failed (error: '$__ERR') - falling back to DNS lookup" + fi + fi + fi + if [ -n "$BIND_HOST" ]; then __PROG="$BIND_HOST" [ $use_ipv6 -eq 0 ] && __PROG="$__PROG -t A" || __PROG="$__PROG -t AAAA" diff --git a/net/ddns-scripts/files/usr/lib/ddns/update_cloudflare_com_v4.sh b/net/ddns-scripts/files/usr/lib/ddns/update_cloudflare_com_v4.sh index b88672c12c889..e469b599f158a 100644 --- a/net/ddns-scripts/files/usr/lib/ddns/update_cloudflare_com_v4.sh +++ b/net/ddns-scripts/files/usr/lib/ddns/update_cloudflare_com_v4.sh @@ -6,6 +6,10 @@ #.based on Ben Kulbertis cloudflare-update-record.sh found at http://gist.github.com/benkulbertis #.and on George Johnson's cf-ddns.sh found at https://github.com/gstuartj/cf-ddns.sh #.2016-2018 Christian Schoenebeck +# +# 2026 Wayne King +# Added GET_REGISTERED_IP mode to retrieve the actual backend IP from Cloudflare API +# (DNS lookups return Cloudflare's proxy IP, not the actual registered IP) # CloudFlare API documentation, section DNS at https://developers.cloudflare.com/api/resources/dns/ # # This script is parsed by dynamic_dns_functions.sh inside send_update() function @@ -214,6 +218,22 @@ else } fi +# Check if we are being called for GET_REGISTERED_IP mode +# This is set by get_registered_ip() in dynamic_dns_functions.sh +if [ -n "$GET_REGISTERED_IP" ]; then + __RUNPROG="$__PRGBASE --request GET '$__URLBASE/zones/$__ZONEID/dns_records/$__RECID'" + cloudflare_transfer || return 1 + __DATA=$(jsonfilter -i "$DATFILE" -e "@.result.content" 2>/dev/null) + if [ -n "$__DATA" ]; then + write_log 7 "Registered IP '$__DATA' detected via Cloudflare API" + REGISTERED_IP="$__DATA" + return 0 + else + write_log 4 "Could not extract IP from Cloudflare API response" + return 127 + fi +fi + # If dns_record_id is specified, grab the stored IP for that specific record # So that the IP checking behavior below works even for domains with multiple IPs if [ -n "$dns_record_id" ]; then