Openwrt使用DNSPod服务做动态域名解析(ddns)–一些优化


一个基本的使用DNSPOD提供的API来实现ddns的脚本已经能够工作了,这是一个基础的脚本,实现的是最基本也是最直接的工作。
除了基础功能的需求,我的wr720n上运行脚本之后,发现了我还有一些其他的额外的需求,脚本需要针对这些需求j来做一些改进和优化。
这些额外的需求是:

  1. 我的wr720n上安装了多播的软件(我设置的是3播),所以wrt720上会同时获取3个外网地址。由于有负载均衡,每次访问api网页的时候,可能会从3个接口中的任意一个出去,这实际上是没必要的,因为这会导致多次调用脚本的时候,实际上是一直在三个ip中切来切去。我希望每次更新ip的时候,访问api网页都是通过同一个网络接口出去的。
  2. 脚本中使用的验证机制是用户名+密码的机制,这个机制比较的原始。而DNSPOD是支持使用token的机制的。使用token机制看起来会比较的更加安全一点。
  3. 执行脚本的时候,先检查一下当前的ip地址跟DNS解析出来的ip地址是否一致,如果不一致才更新ip地址。
  4. 每次向服务器更新ip的时候,都要通过调用两次api接口分别用于查询domain_id和record_id,而这其实是一个比较费时间的过程。实际上domain_id和record_id对于某个特定的域名来说是固定的,就是说只要查询一次,下次直接使用就可以了。可以做优化缓存domain_id和record_id。

针对第一个需求,其实使用的方法也很简单。因为脚本使用curl命令去访问DNSPOD的API的,而curl命令是支持指定特定的网络接口的,添加一个选项”–interface xxx”就可以了。wr720n上,比如我希望每次访问api去更新ddns的ip的时候使用”pppoe-VWAN1″接口,那么脚本中的dnspod_update_record_ip()函数可以修改为:

dnspod_update_record_ip(){
 options="login_email=${ACCOUNT}&login_password=${PASSWORD}";
 curl -k -s --interface pppoe-VWAN1 https://dnsapi.cn/Record.Ddns -d "${options}&domain_id=${DOMAIN_ID}&record_id=${RECORD_ID}&sub_domain=${RECORD_NAME}&record_line=${RECORD_LINE}";

针对第二个需求,其实解决方法也很简单,参考DNSPOD的API的官方手册就可以了。首先要做的是在DNSPOD的账号里面申请一个token.申请成功之后,在DNSPOD的账户中能够察看到token_id和token.然后在脚本中将所有的使用login_email和login_password组合的地方改为下面的格式即可:

login_token=token_id,token

针对第三个需求,

确定DNS解析出来的域名的ip地址的方法,可以使用”nslookup”命令查询,这个命令能够返回查询域名的当前解析出来的ip地址。

而确定当前路由器上的ip地址的方法主要有两种。

一种是网络上有一些提供检测ip地址的网页,只要访问这些网页,就能够返回当前访问者自己的ip地址。

一种是直接使用ifconfig(或者ip命令)命令直接查询openwrt本机上的外网ip地址。

这两种方法各有优势,第一种方法的优点是无论路由器的ip地址是怎么配置的,总能够得到路由器的ip地址,缺点是不能够保证网络上提供ip地址解析服务的网站一直都能提供服务,说不定哪一天就停止服务了。而且是通过网络查询,经过实际测试,速度比较慢。

第二种方法的优点是速度快。但是缺点是,在路由器上,必须配有外网地址。如果openwrt是二级路由器之类的,也就是只配有”192.168.x.x”这样的机器,那就不行了,使用本机的ifconfig命令不能够直接获取到外网的ip地址。

我的wr720n机器是直接通过pppoe连接到外网的,所以是能够通过本机命令获取ip地址的。所以我使用了第二种方法。在脚本中增加下面的一个函数dnspod_is_record_updated():

dnspod_is_record_updated(){                                                                                             
#Format is "Address 1: 117.89.152.129"                                                        
record_ip=`nslookup home.proudj.com |tail -n 1 |cut -d " " -f 3`;                             
                                                                                              
#                                                                                             
#Format is "    inet 117.89.152.129 peer 61.155.116.217/32 scope global pppoe-VWAN1"          
current_ip=`ip addr show pppoe-VWAN3 |grep global|cut -d " " -f 6`;                           
                                                                                              
if [ "$record_ip" = "$current_ip" ]; then                                                     
        echo "[`date`] IP address of VWAN1 did not change in 15 minutes: $record_ip";
        exit 0;                                                                      
fi
}                                                                                   

上面的函数用来判断动态DDNS需要需要更新ip地址。如果不需要更新的话,那脚本就直接退出。

针对第四个需求,其实实现起来也很简单,只要查询一次,然后把domain id 和record id记录下来,存放到一个配置文件中,下次每次运行脚本的时候,不用使用API接口去获取这两个id,只要从配置文件中直接读取就行了。


Leave a Reply

Your email address will not be published. Required fields are marked *