To handle ip address changing by ifupdate.
When the ipv6 address is updated for an interface
(some ISP only give dynamic ipv6 address).
The ddns script will go into dead loop,
as the new ipv6 address is not used.
The simple change is restarting ddns when ip address is changed.
Signed-off-by: Jimmy Qin <sunnyqeen@gmail.com>
Gandi has deprecated Api Key for authentication and replaced it with
Personal Access Tokens. This adds a v2 gandi package containing a script
using the new authentication scheme while keeping the old version intact
for any existing API Key users. Additionally, it documents the old
version as deprecated and points users to v2.
Signed-off-by: Keith T. Garner <kgarner@kgarner.com>
The date format read from the UCI option ddns.global.ddns_dateformat was
embedded into a command string that is later executed through "eval", both
for the recurring log timestamps
DATE_PROG="date +'$ddns_dateformat'"
...
write_log 5 "PID '$$' started at $(eval $DATE_PROG)"
and for the "last update" timestamp in the updater
EPOCH_TIME="date -d @$EPOCH_TIME +'$ddns_dateformat'"
write_log 7 "last update: $(eval $EPOCH_TIME)"
The value is only wrapped in single quotes, so a single quote inside it
closes that quote and starts a new shell word. A user who can write the ddns
configuration - a delegated DDNS operator who was never granted shell access
- can set
ddns_dateformat="%F'; touch /tmp/pwned; '"
and have arbitrary commands run as root, because the updater runs as root.
The injection triggers on the next start of the updater, so in practice on
the next reconfiguration or reboot.
Stop building shell code from the option. Provide date_prog() as an ordinary
shell function and pass the format as a single quoted argument in both
places, which leaves no way for its content to be interpreted by the shell.
The remaining use of ddns_dateformat in dynamic_dns_updater.sh, for
NEXT_CHECK_TIME, already substituted it as a quoted argument without eval
and was not affected.
luci-app-ddns consumes the same option and is fixed separately in the LuCI
repository.
Reported-by: Matthew Hickey (Hacker Fantastic, https://hacker.house)
Fixes: 1c20dcb71a ("ddns-scripts: update to 2.7.6-1")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Add the missing spaces around the test bracket in the one.com
pre-removal script and escape IPKG_INSTROOT consistently with the other
subpackages.
Signed-off-by: Jiang Tengfei <admin@shaoxia.xyz>
The /usr/bin/ddns frontend did not support a version option, so
generic package tests treated it as an executable that could not report
the package version.
Read the installed version file and support -V/--version, matching the
version output style used by dynamic_dns_updater.sh.
Signed-off-by: Jiang Tengfei <admin@shaoxia.xyz>
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>
None of the ddns-scripts executables or scripts report the package version when
run, which causes the generic version probe to fail.
Add a test-version.sh to skip the version check for ddns-scripts and all of
its subpackages.
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
In luci, the `interface` value has `o.default = 'wan'` configured.
Due to a behavior fix in 'o.default', values matching the default are
no longer saved. Currently, this is workedaround by disabling
'o.rmempty' in luci, but handling this compatibility fallback on the
backend is a cleaner and superior approach.
Ref: b004197a27
Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
When fetching the IP via a URL with `force_ipversion` enabled,
a `Busybox nslookup - no support to 'force IP Version' (ignored)`
log is generated periodically. This log is redundant, in this scenario
`force_ipversion` only affects the results fetched by wget/uclient-fetch/curl.
It is perfectly fine for nslookup to query both A/AAAA records simultaneously.
Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
Add DDNS update support for blazingfast.io Anycast DNS via their
REST API. Authentication is performed via JWT token obtained from
the login endpoint. Zone records are fetched to verify the record
type before update, ensuring IPv4 services only target A records
and IPv6 services only target AAAA records.
Service, zone and record IDs are passed via param_opt as
space-separated key=value pairs:
service_id=X zone_id=Y record_id=Z
curl --config file approach is used throughout to avoid eval and
shell injection from user-controlled values. Supports both IPv4
and IPv6. For dual-stack, create two separate DDNS service sections
with their respective record IDs.
Tested on GL.iNet MT5000 (Brume 3) running OpenWrt with
ddns-scripts 2.8.2.
Signed-off-by: Fotios Kitsantas <fkitsantas@icloud.com>
Add DDNS update support for blazingfast.io Anycast DNS via their
REST API. Authentication is performed via JWT token obtained from
the login endpoint. Zone records are fetched to verify the record
type before update, ensuring IPv4 services only target A records
and IPv6 services only target AAAA records.
Service, zone and record IDs are passed via param_opt as
space-separated key=value pairs:
service_id=X zone_id=Y record_id=Z
curl --config file approach is used throughout to avoid eval and
shell injection from user-controlled values. Supports both IPv4
and IPv6. For dual-stack, create two separate DDNS service sections
with their respective record IDs.
Tested on GL.iNet MT5000 (Brume 3) running OpenWrt with
ddns-scripts 2.8.2.
Signed-off-by: Fotios Kitsantas <fkitsantas@icloud.com>
On master, updater help and missing-option text still refer to '-N'.
Use '-S' instead so the messages match accepted script options.
Also clarify that SECTION is the UCI section name/id to start.
This is a text-only change; runtime behavior is unchanged.
Bump PKG_RELEASE to 4.
Fixes: #27737
Signed-off-by: Dharmik Parmar <dharmikparmar2004@yahoo.com>
Adjust the update error handling path to avoid hard failures on
recoverable errors. This allows ddns to retry updates after the
configured retry interval and improves reliability.
Signed-off-by: Tim Flubshi <flubshi@gmail.com>
Replace manual file loading via cat with json_load_file for parsing
JSON data. This uses the intended helper function and improves
code clarity and robustness.
Signed-off-by: Tim Flubshi <flubshi@gmail.com>
The netcup ddns update script fails on subsequent runs because a
readonly variable is assigned again. Fix this by removing the readonly
declaration to allow repeated execution.
Signed-off-by: Tim Flubshi <flubshi@gmail.com>
Add a new netcup DDNS provider using the netcup DNS api
(ccp.netcup.net) with API key authentication.
Configuration mapping:
* username = netcup customer number
* password = netcup API password
* param_enc = netcup API key (generated in the CCP)
* domain = fully qualified subdomain to update (e.g. home.example.de)
* param_opt = (optional) root/zone domain override (e.g. example.de)
When omitted the root domain is derived by stripping the
leftmost label from 'domain'. This only works correctly for
a single subdomain level (e.g. "home.example.de").
param_opt MUST be set explicitly in two cases:
1. Deep subdomains: domain=test.internal.example.org
2. ccSLD apex domains: domain=example.co.nz
Signed-off-by: Tim Flubshi <flubshi@gmail.com>
The 'ddns-scripts' packages still uses not the procd service handling.
This commit changes this.
This change also resolves the issue where, if a UCI configuration is
already present, the process is blocked during installation via APK and
does not complete.
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
Tested-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
records
Problem:
When using Cloudflare with proxy enabled (orange cloud), DNS lookups
return Cloudflare's edge IP instead of the actual origin IP registered
in the dashboard. This causes ddns-scripts to incorrectly detect IP
mismatches, triggering unnecessary updates and potential rate limiting.
Solution:
Add an optional 'use_api_check' configuration option that enables
provider scripts to fetch the registered IP directly via their API,
bypassing DNS lookups.
Changes:
- dynamic_dns_functions.sh: Add API check block to get_registered_ip()
(~25 lines). When use_api_check is enabled, sources the provider
script with GET_REGISTERED_IP=1 flag. Falls back to DNS lookup if
API check is disabled, unsupported, or fails.
- update_cloudflare_com_v4.sh: Add handler for GET_REGISTERED_IP mode
(~15 lines). Reuses existing cURL setup and authentication to query
Cloudflare API for actual record content.
- etc/config/ddns: Document use_api_check option
Behavior:
- use_api_check=0 or unset: DNS lookup (existing behavior, no changes)
- use_api_check=1 with API support: API query for registered IP
- use_api_check=1 without API support: Falls back to DNS lookup
- API failure: Gracefully falls back to DNS lookup
Testing:
- Cloudflare (proxied): Correctly retrieves origin IP via API
- Cloudflare (non-proxied): Works correctly
- No-IP: DNS lookup works (no regression)
- IPv4 and IPv6 records tested
- API failure gracefully falls back to DNS
Signed-off-by: Wayne King 244781262+bdk38@users.noreply.github.com
For reasons that have not been investigated in detail, the package blocks
during 'postinst' with the new 'apk' backend when the package is installed
on the target.
After much back and forth, it turned out that the '/etc/init.d/ddns start'
command is responsible for this. The call is blocking.
The command '/etc/init.d/ddns enabled' in the 'postinst' also makes no sense
here, as it only checks whether the ddns service is enabled. The return value
is not checked at all. And the 'prerm' script is also not needed, as the
calls made there are implicitly called during package deinstallation.
Therefore, this commit removes the entire and not needed 'postinst' and
'prerm' script call.
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
This was overlooked. Therefore, the package could not be built.
Fixes: e9fe0249f6 ("ddns-scripts: Fix Hetzner Cloud naming")
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
In the original commit I used the wrong name for the package in the
Makefile and various other files which caused the package to not build.
Unify the naming to "cloud" to fix the package build.
Fixes: 5ee205bd31 ("ddns-scripts: add Hetzner Cloud support")
Signed-off-by: Christopher Obbard <obbardc@gmail.com>
Add a new Hetzner DDNS provider using the Hetzner Cloud API
(api.hetzner.cloud) with Bearer token authentication.
Configuration guide:
* set [domain] to domain
* set [username] to subdomain (without domain)
* set [password] to Bearer API key
Signed-off-by: Christopher Obbard <obbardc@gmail.com>
new service provider namesilo.com
config guide:
* set [domain] to apex domain
* set [username] to subdomain (without apex domain)
* set [password] to api key
Signed-off-by: Lin Fan <im.linfan@gmail.com>
Redirect stdout and stderr to /dev/null when starting/restarting the ddns
service in the background. Without this redirection, file descriptors are
inherited by the child process, preventing proper process detachment and
causing luci's XHR requests to timeout.
Added logic to extract and match DNS record ID from parameters,
with fallback to default selection if no match is found.
Signed-off-by: QiLei Niu <qilei.niu@gmail.com>
Add missing provider entry for apertodns.com-token.
The service configuration (apertodns.com-token.json) was already
merged in PR #28160, but the provider list entry was missing.
Signed-off-by: Andrea Ferro <support@apertodns.com>
Add support for ApertoDNS dynamic DNS service with two configuration
options:
- apertodns.com: Standard DynDNS2 compatible authentication (user/pass)
- apertodns.com-token: Token-based authentication for DDNS clients
Both configurations support IPv4 and IPv6 updates via the standard
/nic/update endpoint.
Signed-off-by: Andrea Ferro <support@apertodns.com>
To check if the update was successful.
Not all DDNS implementations have such huge latencies updating their services.
nsupdate for example, updates immediately and the update is immediately checkable.
Add new check_interval_min value to be able to set a check interval lower than the
previously hard-coded 5 minutes.
Fixes: #20564
Signed-off-by: Brian J. Murrell <brian@interlinx.bc.ca>
According to [1] Basic Auth seems to be broken since a while for he.net.
The documentation [2] is outdated, and still mentions Basic Auth, but
switching to parameter-based authentication seems to fix the issue.
It also bumps PKG_RELEASE in order to ensure a new version is packaged.
[1]: https://github.com/openwrt/packages/issues/27593
[2]: https://dns.he.net/docs.html
Signed-off-by: Karol Babioch <karol@babioch.de>
OVH changed its API to update DNS records. It now requires HTTP Basic
Authorization header. As such the default ddns-script method to update
the DNS record is failing. The fix is to move DNS record updates into
its own script/package.
Signed-off-by: David Andreoletti <david@andreoletti.net>
adjust comments documenting the already supported API Token auth
adjust comments with URLs that changed in the meantime
adjust comment regarding CF API documentation URL, points to the scripts relevant DNS section
Signed-off-by: Dominic Greenberg <daroel@riseup.net>
This reverts commit 366629b117.
It has been determined that the URL currently in use points to v1. The
previously used URL remains valid and is correct. If someone requires the
v1 URL, a new provider must be created.
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
Calculating the next check time based on the last update time is not
very accurate if the next check is a large multiple forwards from the
last update time because the cumulative sleeps and wake times are not
exact but best effort of the OS. Other factors including clock-drift
give rise to a larger time discrepancy the further the next update is in
the future.
Stash the next check time which should be quite accurate since it's
only one sleep instance away. This is also for use in the GUI.
Tested on 24.10.2
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Add back the regex searching for valid IP address when getting IP
address via web.
Fixes: 9cdd1a1660 ("ddns-scripts: refactor get_current_ip()")
Signed-off-by: Qian Suyao <qiansuyao@gmail.com>
User can (optionally) set zone_id and dns_record_id in param_opt.
This allows round robin DNS setup in Cloudflare.
Signed-off-by: Eric Leung <contact@ericleung.dev>