利用OpenWrt的Hotplug与DNSPOD的API实现DDNS
2017/11/8 计算机 次 0 条
既然标题叫“利用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>"