I’ve recently updated my router system, and I’ve broken DDNS. The router system is OpenWrt, DDNS service using Cloudflare. last time the configuration is tossed for a long time, I forgot to record. This time again tossed again. Take this opportunity to organize into a text, share it with you.

The first thing we need to do is to create an interface token (token) for calling the Cloudflare API. this step needs to be done in the Cloudflare management backend.

Cloudflare API Token

Click on the user icon in the upper right corner and click on My Profile in the pop-up menu to open a new page. Click on API Tokens in the left column, then click on Create Token on the right, then select Edit zone DNS from API token templates, click on Use Template on the right, then click on Zone Resources in the last drop-down menu, select the domain name you want to personalize. Finally, click Continue To summary and the system will display the corresponding domain name information. Click Create Token to complete the creation. The system will display the newly created token. Note that it will only be displayed once, so please make sure to save it. If you lose it, you can only create a new token.

With the token in place, next we install the required packages.

OpenWrt DDNS Packages

We can install them from the OpenWrt backend System -> Software page, or we can install them directly using opkg. The required packages are.

  • luci-app-ddns
  • ddns-scripts-cloudflare

luci-app-ddns is used to support DDNS configuration in the admin backend interface, and ddns-scripts-cloudflare is used to call the Cloudflare API. ddns functionality also relies on some other toolkits, which OpenWrt will install automatically.

After installation, refresh the page and the Services menu will appear in the top bar with Dynamic DNS service. Click to open the DDNS configuration page.

Configure Cloudflare DDNS

Click on the Add new services… button in the bottom left corner and you need to specify the following fields.

Field Value Description
Name Configuration Name You can fill in whatever you like, for example cf4
IP Address Version IP Address Type You can select IPv4 and IPv6, generally select IPv4
DDNS Service provider DDNS Service Provider This article needs to be selected cloudflare.com-v4

Click Create Service and a new configuration menu will pop up. There are a bit too many fields, and the required fields are as follows.

Field Value Description
Lookup Hostname The domain name used to verify the IP mapping is actually the domain name used by DDNS
Domain Domain names used by DDNS Sub-domains need to be connected using @, e.g. ddns@example.net
Username API authentication username fixed to Bearer
Password API authentication token is the token requested earlier
Use HTTP Secure Use HTTPS to call the interface must be checked
Path to CA… /etc/ssl/certs CA certificate file path

Just leave the other fields as they are. Finally click Save to save.

Troubleshooting

Once you have created the configuration, you also need to click the Save & Apply button at the bottom. Finally, you can click the Reload button on the right side of the configuration.

However, after the actual operation, I found that DDNS did not take effect. I did not find a solution from the Internet, so I had to debug it myself.

First look at the log. Click the Edit button on the configuration, switch to the Log File Viewer tab, and then click Read / Reread log file, and then you can see the logs. The most suspicious line is as follows.

1
WARN : No update_url found/defined or no update_script found/defined! - TERMINATE

It says it didn’t find update_url or update_script, but where to find it? I can’t say, so I have to figure out how to look at the code. But I don’t know which script is outputting this message. So I had to check them one by one.

As we said earlier, DDNS relies on several packages, which OpenWrt installs automatically. The main one is the ddns-scripts package, which can be considered as the base framework of the whole DDNS. Let’s see how many files it has.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
opkg files ddns-scripts
Package ddns-scripts (2.8.2-12) is installed on root and has the following files:
/usr/lib/ddns/dynamic_dns_updater.sh
/usr/bin/ddns
/etc/init.d/ddns
/etc/hotplug.d/iface/95-ddns
/etc/config/ddns
/usr/lib/ddns/dynamic_dns_functions.sh
/usr/share/ddns/version
/usr/lib/ddns/dynamic_dns_lucihelper.sh

A good comparison is dynamic_dns_updater.sh, which searches for script content.

1
2
grep 'No update_url found' /usr/lib/ddns/dynamic_dns_updater.sh
[ -z "$update_url" -a -z "$update_script" ] && write_log 14 "No update_url found/defined or no update_script found/defined!"

I was lucky to find the error code. Open the file and you can see the following code.

1
[ -n "$service_name" ] && get_service_data update_url update_script UPD_ANSWER

The get_service_data function is called here. We need to find the source code of this function. dynamic_dns_functions.sh is more suspicious, search for it.

1
2
3
grep get_service_data /usr/lib/ddns/dynamic_dns_functions.sh
get_service_data() {
    [ $# -ne 3 ] && write_log 12 "Error calling 'get_service_data()' - wrong number of parameters"

Sure enough here, the core code snippet is as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
get_service_data() {
    [ $# -ne 3 ] && write_log 12 "Error calling 'get_service_data()' - wrong number of parameters"
    __FILE="/etc/ddns/services"
    [ $use_ipv6 -ne 0 ] && __FILE="/etc/ddns/services_ipv6"
    mkfifo pipe_$$
    sed '/^#/d; /^[ \t]*$/d; s/\"//g' $__FILE >pipe_$$ &
    while read __SERVICE __DATA __ANSWER; do
        if [ "$__SERVICE" = "$service_name" ]; then
            __URL=$(echo "$__DATA" | grep "^http")
            [ -z "$__URL" ] && __SCRIPT="/usr/lib/ddns/$__DATA"

It reads the contents of /etc/ddns/services line by line and then extracts each field by read __SERVICE __DATA __ANSWER. From the __URL assignment statement, we can determine that the second column in the services file indicates the URL if it starts with http, otherwise it indicates the script path. This path corresponds to the script file in the /usr/lib/ddns/ directory.

1
2
3
4
5
ls -1 /usr/lib/ddns/
dynamic_dns_functions.sh
dynamic_dns_lucihelper.sh
dynamic_dns_updater.sh
update_cloudflare_com_v4.sh

So we need to add a line to /etc/ddns/services.

1
"cloudflare.com-v4"     "update_cloudflare_com_v4.sh"

After saving, reload the DDNS configuration in the OpenWrt backend and click the Reload button to complete the DDNS configuration. At this point, you can see through the logs that the system has invoked the Cloudflare API normally. Wait at most 10 minutes for the DNS update to take effect.

IPv6 Configuration

OpenWrt DDNS supports binding IPv6 addresses. We need to add a separate configuration and select IPv6 for the address type, otherwise the configuration is exactly the same as for IPv4. The only thing to note is that IPv6 requires an additional NIC to be specified. In the Advanced Settings tab, specify Network as wan6, otherwise it will report an error because it cannot get an IPv6 address.

Summary

Although OpenWrt supports DDNS function, but the default configuration for Cloudflare still has many problems. We still need some tossing and turning when using it. But the use of OpenWrt users who are not tossing and turning? With all of you to encourage 😄