通过 OPENWRT 的 HOTPLUG 功能实现 DDNS (动态DNS)

通过 OpenWRT 的 HotPlug 功能配合 DNSPOD 实现 DDNS

原料

dnspod 域名解析服务

openwrt (不需要安装额外的DDNS软件)

实现原理

OpenWRT 的 hotplug 顾名思义,就是热拔插的意思。当设备的任意硬件出现变更时会引发事件自动执行 sh 脚本。其中 hotplug 的设备分为block、iface、net、switch、tty、usb以及wifi,具体可以SSH到路由器查看/etc/hotplug.d目录。关于 Linux 系统中的热拔插可以参见这篇文章。例如你使用PPPOE上网,当拨号成功之后则会引起ifup事件,属于iface分类下的事件,那么 iface 文件夹内的sh将会按顺序被执行。DDNS的目的就在于动态更新你的IP到对应域名之中。刚好,dnspod提供了API可以修改域名解析的数据,那么当一个WAN或者PPPOE成功获取到IP时,则会执行sh。那么我们通过在iface下编写sh请求dnspod的API即可实现DDNS。

配置DNSPOD API

  1. 登录到你的DNSPOD后台,定位到 用户中心->安全设置,开启 API Token功能并记录好你的 TOKEN。然后设定一个需要实现DDNS的域名。
  2. 请求 API 获取返回值可以使用 curl 或者使用 postman 工具请求,我们只需要获取到需要 DDNS 的域名ID即可。
  3. 首先获取域名列表,POST 请求 https://dnsapi.cn/Domain.List ,参数 login_token=token_id,token ,请求后将会接收到 JSON 数据,找到对应域名的ID,并记录下来,方便请求获取二级域名信息。
  4. 获取二级域名列表,即获取域名的解析记录。POST 请求 https://dnsapi.cn/Record.List,获取该二级域名的所有记录,找到需要DDNS的二级域名,并记录下ID

了解 OpenWRT 的 ubus 命令行工具

ubus 在 OpenWRT 中提供了进程间的通信功能,使得进程之间的通信变得非常简单。配合 call 指令,我们可以把需要调用的指令发送到相应进程中执行。

为了获得WAN的IP地址,我们需要查看 network.interface.wan 的详细信息。

在终端中执行以下指令,我们可以看到WAN口的详细信息

ubus call network.interface.wan status

返回的信息为JSON格式,IP地址就位于 ipv4-address 下 的 address 之中,由此我们可以使用 grep 方便地取出

ubus call network.interface.wan status | grep \"address\" | grep -oE '[0-9]{1,3}\.[0-9]{1

关于 ubus 的更多信息,可以查阅[OpenWRT官方文档]

编写 sh 实现 ddns

有了上面的过程,现在我们已经拿到需要实现DDNS的域名ID,知道如何取出本机IP地址。配合 hotplug,当 WAN 连接上之后,会执行一遍 iface 下的 sh 脚本,那么,我们只要编写一个请求DNSPOD修改记录信息的脚本即可实现DDNS。

#! /bin/sh
ip=$(ubus call network.interface.wan status | grep \"address\" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
curl -k -X POST https://dnsapi.cn/Record.Modify -d "login_token=ID,TOKEN&format=json&domain_id=DOMAIN_ID&record_id=RECORD_ID&sub_domai
echo $ip
exit 0

通过 vim 或者 sftp 在 /etc/hotplug.d/iface 下新建一个 sh 脚本,并拷贝上述脚本到文件中。由于不知道其他脚本的具体作用,所以新建的文件名使用 99- 开头,确保在执行本脚本之前,原先的脚本会被全部先执行一遍。 代码中 ID 就是 TOKEN ID,TOKEN 就是 Token 内容,DOMAIN_ID 为前面获取的域名ID,RECORD_ID即为二级域名的ID,替换好后保存起来。

手动执行该脚本,如果没有什么幺蛾子,就会看到当前 WAN 口的 IP 地址,然后查看 DNSPOD 后台,就可以看到二级域名的 A 记录的 IP 地址同时变更。