ddns-scripts: add curl source IP bind fallback

Keep the existing cURL bind_network behavior of binding to the
logical device first. This preserves the behavior introduced for
PPPoE and multi-WAN setups where the selected network must also be
used for the DDNS update request.

Some setups can still fail when libcurl binds directly to the logical
PPP device. In that case the transfer may time out even though binding
to the source address of the same network succeeds. This can make DDNS
updates fail repeatedly on affected systems.

Retry cURL transfers once with the network source IP when the
device-bound transfer fails. This leaves the normal path unchanged,
keeps the update request on the same network, and matches the existing
GNU Wget behavior which already binds to the network IP address.

Also document the implicit bind_network default and the cURL fallback
in the sample configuration.

Signed-off-by: Jiang Tengfei <admin@shaoxia.xyz>
(cherry picked from commit 9a5e6063f1)
This commit is contained in:
Jiang Tengfei authored and Florian Eckert committed 2026-09-29 08:08:18 +02:00
1 parent 8a16feeed1
commit d1cc4fa659
2 files changed
+25 -5

No files matched your search

@@ -617,6 +617,7 @@ do_transfer() {
local __ERR=0
local __CNT=0 # error counter
local __PROG __RUNPROG
local __FALLBACK_RUNPROG __FALLBACK_DESC
[ $# -ne 1 ] && write_log 12 "Error in 'do_transfer()' - wrong number of parameters"
@@ -674,11 +675,17 @@ do_transfer() {
write_log 13 "cURL: libcurl compiled without https support"
# force network/interface-device to use for communication
if [ -n "$bind_network" ]; then
local __DEVICE
local __DEVICE __BINDIP __BIND_OPT __FALLBACK_BIND_OPT
network_get_device __DEVICE $bind_network || \
write_log 13 "Can not detect local device using 'network_get_device $bind_network' - Error: '$?'"
# set correct program to detect IP
[ $use_ipv6 -eq 0 ] && __RUNPROG="network_get_ipaddr" || __RUNPROG="network_get_ipaddr6"
eval "$__RUNPROG __BINDIP $bind_network" || \
write_log 13 "Can not detect current IP using '$__RUNPROG $bind_network' - Error: '$?'"
write_log 7 "Force communication via device '$__DEVICE'"
__PROG="$__PROG --interface $__DEVICE"
__BIND_OPT=" --interface $__DEVICE"
__FALLBACK_BIND_OPT=" --interface $__BINDIP"
__FALLBACK_DESC="IP '$__BINDIP'"
fi
# force ip version to use
if [ $force_ipversion -eq 1 ]; then
@@ -705,7 +712,9 @@ do_transfer() {
write_log 13 "cURL: libcurl compiled without Proxy support"
fi
__RUNPROG="$__PROG '$__URL'" # build final command
__RUNPROG="$__PROG$__BIND_OPT '$__URL'" # build final command
[ -n "$__FALLBACK_BIND_OPT" ] && \
__FALLBACK_RUNPROG="$__PROG$__FALLBACK_BIND_OPT '$__URL'"
__PROG="cURL" # reuse for error logging
# uclient-fetch possibly with ssl support if /lib/libustream-ssl.so installed
@@ -765,6 +774,14 @@ do_transfer() {
eval $__RUNPROG # DO transfer
__ERR=$? # save error code
[ $__ERR -eq 0 ] && return 0 # no error leave
if [ -n "$__FALLBACK_RUNPROG" ]; then
write_log 3 "$__PROG Error: '$__ERR'"
write_log 7 "$(cat $ERRFILE)" # report error
write_log 4 "Transfer failed - retry using $__FALLBACK_DESC"
__RUNPROG="$__FALLBACK_RUNPROG"
__FALLBACK_RUNPROG=""
continue
fi
[ -n "$LUCI_HELPER" ] && return 1 # no retry if called by LuCI helper script
write_log 3 "$__PROG Error: '$__ERR'"
+5 -2
View File
@@ -269,10 +269,13 @@ config service "myddns"
# In some very special configurations i.e. Multi WAN environment
# in a NAT cascade it might be necessary to define
# a network to use for communication.
# If bind_network is not set and ip_source is "network",
# ip_network is used as the default bind network.
# should use option ip_source "web" (see above)
# Needs GNU Wget (with SSL support) or cURL to be installed.
# GNU Wget will use IP address and cURL the physical device
# of the given network
# GNU Wget will use IP address and cURL the logical device
# of the given network. cURL retries once with the IP address
# when the device-bound transfer fails.
# default: none
# option bind_network "wan7"