2023年1月7日星期六

OpenWrt中通过自定义脚本为Cloudflare域名更新DDNS

  在上一篇文章中,威联通NAS上myQNAPcloud DDNS获取外网地址不准确的问题,提到使用myQNAPcloud服务来设置DDNS。这次尝试不依赖QNAP的服务,在OpenWrt里定时运行自定义脚本来直接更新域名的DNS地址。


  我的域名托管在Cloudflare上,所以主要思路是定时在OpenWrt里运行脚本检测公网IP地址是否有变化,如果有就用Cloudflare的token和API来更新相关DNS设置。


  记录具体步骤如下:


1. 获取Cloudflare的API token,稍后脚本中会用到。进入 https://dash.cloudflare.com/profile/api-tokens 页面,Create Token,为了使token权限最小化选择Create Custom Token,设置如下图。Specific zone选项可限制token权限为仅允许更新某一个域名。

    - 


2. 在上面所选域名的DNS设置中,添加一条A记录,设置成DDNS想要绑定的域名。IP地址随意设置比如8.8.8.8(之后脚本会付覆盖),Proxy status设置为DNS only。

3. OpenWrt运行的脚本。参考了一些网上的脚本,发现 https://raw.githubusercontent.com/K0p1-Git/cloudflare-ddns-updater/main/cloudflare-template.sh 这个脚本比较全面,注释也清楚。几点注意事项:

    - 第一行的`#!/bin/bash`需要修改成`#!/bin/sh`,否则OpenWrt中没有bash环境无法运行。

    - 要填写的项目有auth_email,auth_key,zone_identifier,record_name,其余可留空。

    - auth_method="token" 注意保持token方式,对应步骤1中创建的API token。同一页面还可看到Cloudflare的Global API Key,因为它可以操作账户里的所有设置,不建议使用。

    - 如果OpenWrt设置了科学上网/透明代理,`curl -s -4 https://cloudflare.com/cdn-cgi/trace`运行时可能获取到代理服务器的ipv4地址。可以注释掉相关if判断部分,改为用其它API直接获取,即`ip=$(curl -s https://api.ipify.org || curl -s https://ipv4.icanhazip.com)` 。

4. 用scp命令将修改好的脚本上传到/root目录,`chmod +x updateDDNS_cloudflare.sh`赋予执行权限。先手动运行一次观察输出是否正常`/bin/sh -x updateDDNS_cloudflare.sh`。如果脚本运行无误的话,可以在Cloudflare中观察到对应A记录的DNS更新成功。

5. `crontab -e`编辑计划任务,添加一行内容`*/10  *  *  *  *  /root/updateDDNS_cloudflare.sh`,这样此脚本会每10分钟运行一次以按需更新DDNS。此步骤也可在OpenWrt网页端的“系统->计划任务”里完成。


  其实同样的工作也可以在OpenWrt的web管理页面上完成,如果你可以在“服务->动态DNS->DDNS 服务提供商 [IPv4]”的设置中找到Cloudflare选项的话。我用的OpenWrt编译了动态DNS的应用(luci-app-ddns, ddns-scripts),但没有Cloudflare的入口点。尝试安装ddns-scripts-cloudflare或更早的ddns-scripts_cloudflare.com-v4_2.7.8-3_all.zip,不仅依然找不到Cloudflare入口点,还有可能破坏掉OpenWrt:实际后台依然运行,可以上网,但web页面(LuCI web interface)报错`Bad Gateway The process did not produce any response.`,只能借助ESXI里的快照恢复或重新安装OpenWrt。所以才有了这篇博客。