愚蠢的地球人

利用OpenWrt的Hotplug与DNSPOD的API实现DDNS

既然标题叫“利用OpenWrt的Hotplug与DNSPOD的API实现DDNS”,那么首先你得有一个openwrt的路由器,其次你需要有一个在dnspod.cn解析的域名,最后你家的宽带得要是公网IP。除此之外,既然你需要把域名解析到你家宽带的IP,那么你家里肯定有一台需要从外网访问的Server。


如果这些你都有,那就跟着我一起动手来折腾吧。


Hotplug,直译就是热插拔。在OpenWrt中,无论何时一个设备从系统中增删,都产生一个“热插拔事件”。每次网络接口启动(up)或者关闭(down)的时候,所有在/etc/hotplug.d/iface/目录中的脚本都会以字母顺序执行。所以每个脚本的前面加上一个数字前缀来设置正确的运行顺序。这就是为什么脚本名称都像:/etc/hotplug.d/iface/<nn>-<scriptname>的原因。

在iface hotplug脚本中有三个主要的环境变量:

ACTION:"ifup"或"ifdown",表示网络接口打开或者关闭

INTERFACE:网络接口的名称,如"wan"

DEVICE:物理设备的名称,如"br-lan"


利用这个Hotplug的功能,我们可以在wan口的状态发生变化时执行一个自定义的脚本来更新我们的DDNS。


我们先来看一下DNSPOD关于DDNS的API文档:https://www.dnspod.cn/docs/records.html#dns

接口地址:https://dnsapi.cn/Record.Ddns

HTTP请求方式:POST

请求参数:

domain_id 或 domain, 分别对应域名ID和域名, 提交其中一个即可

record_id 记录ID,必选

sub_domain 主机记录,如 www

record_line 记录线路,通过API记录线路获得,中文,比如:默认,必选

record_line_id 线路的ID,通过API记录线路获得,英文字符串,比如:‘10=1’ 【record_line 和 record_line_id 二者传其一即可,系统优先取 record_line_id】

value IP地址,例如:6.6.6.6,可选


示例:

curl -X POST https://dnsapi.cn/Record.Ddns -d 'login_token=LOGIN_TOKEN&format=json&domain_id=2317346&record_id=16894439&record_line_id=10%3D3&sub_domain=www'


其中LOGIN_TOKEN是DNSPOD新采用的一种鉴权方式,旧的 “用户名 + 密码” 的鉴权方式仍能继续使用,推荐开发者优先使用 login_token 来鉴权。

LOGIN_TOKEN生成方法详见:https://support.dnspod.cn/Kb/showarticle/tsid/227/


有了LOGIN_TOKEN,下一步我们还需要获取domain_id和record_id,这里我们需要用到curl指令,这个指令在windows里面需要安装第三方软件才能实现,不过既然你有openwrt的路由器,那么最简单的方法就是直接在openwrt的WebShell里面执行,不过这里需要注意的是由于你的openwrt里面可能没有安装证书,所以在使用curl指令的时候可以加上-k的参数来忽略证书的问题。


获取 domain_id

curl -k 'https://dnsapi.cn/Domain.List' -d 'login_token=<your_login_token>&format=json'

根据响应中的 domains 得到域名对应的 domain_id


获取 record_id

curl -k 'https://dnsapi.cn/Record.List' -d 'login_token=<your_login_token>&format=json&domain_id=<your_domain_id>'

根据响应中的 records 得到子域名记录对应的 record_id


有了这几样东西,我们就可以准备正式动手编写脚本了。

在编写脚本之前我们先在路由器的WebShell里面输入以下指令来测试一下解析记录是否能更新成功:

curl -s -k -X POST "https://dnsapi.cn/Record.Ddns" -d "login_token=<your_login_token>&format=json&domain_id=<your_domain_id>&record_id=<your_record_id>&record_line=%e9%bb%98%e8%ae%a4&sub_domain=<your_sub_domain>"

如果网站返回内容有"message":"Action completed successful"的字段,那么恭喜你,成功了。


现在,我们新建一个名叫99-dnspod的文件,文件格式一定要使用UTF-8,输入以下内容保存:

#!/bin/sh
# wan ifup
[ "$ACTION" = ifup ] || exit 0
[ "$INTERFACE" = "wan" ] || exit 0
curl -s -k -X POST "https://dnsapi.cn/Record.Ddns" -d "login_token=<your_login_token>&format=json&domain_id=<your_domain_id>&record_id=<your_record_id>&record_line=%e9%bb%98%e8%ae%a4&sub_domain=<your_sub_domain>"


然后用WinSCP登录你的路由器,将99-dnspod这个文件上传到/etc/hotplug.d/iface/目录,修改权限0755,完工。


当然,你也可以把curl指令换成wget,指令如下:

wget --post-data="login_token=<your_login_token>&format=json&domain_id=<your_domain_id>&record_id=<your_record_id>&record_line=%e9%bb%98%e8%ae%a4&sub_domain=<your_sub_domain>"  https://dnsapi.cn/Record.Ddns --no-check-certificate --output-document=/dev/null

你也可以使用https://dnsapi.cn/Record.Modify这个接口来实现更多功能。这个接口需要人工发送解析记录的IP地址,获取wan口IP地址的指令我搜集了一下,可以用以下几种方式:

wanip=$(ifconfig pppoe-wan | awk '/inet addr/{print substr($2,6)}')
wanip=$(ifconfig pppoe-wan | grep inet | awk '{print $2}' | cut -c 6-)

【2017年12月10日更新】

刚发现OpenWrt最新的DDNS Client已经可以使用自定义脚本来更新了,这样的话就更加简单了,我们不需要把99-dnspod脚本放在/etc/hotplug.d/iface/下面了(实际上DDNS Client已经在这里已经建立了一个脚本,一旦IP发生变化就会通知DDNS Client的进程执行更新。另外,DDNS Client会在后台每隔一段时间自动解析你预设的域名,然后跟WAN口IP进行对比,如果不一致也会执行你设置好的脚本)。我们只需要把下面的脚本放在任何位置,然后在DDNS LUCI配置界面里选择自定义脚本,填上脚本路径就OK了。

curl -s -k -X POST "https://dnsapi.cn/Record.Ddns" -d "login_token=<your_login_token>&format=json&domain_id=<your_domain_id>&record_id=<your_record_id>&record_line=%e9%bb%98%e8%ae%a4&sub_domain=<your_sub_domain>"


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

相关推荐

友情链接

网站分类

最新留言

最近发表