0x01 前言

我本来是使用DNSPod的DDNS服务,但自从我撤走极路由后就再也用不了了。同时DNSPod免费用户最低的TTL仅能设为600(10分钟),不足以满足DDNS的需求。我试过很多次重启服务器或者重新拨号后都无法在短时间内更新DNS的A记录。

其实DNSPod也有简单易用的API可供我编写python脚本,相对于阿里云年付的40.8元,DNSPod的年付360确实有点贵,同时DNSPod个人专业版的TTL最低也就300(5分钟),但阿里云最低却能设为1(1秒)。

如果你需要阿里云的付费服务,以下是一个9折优惠码:

DNSPod DNS费用详情
DNSPod DNS费用详情

阿里云DNS费用详情
阿里云DNS费用详情

0x02 准备

因为受限于阿里云python SDK,这里使用python2.7进行编写。运行时请使用python2.x版本运行,而使用python3.x将会出现错误。

首先要在系统上安装阿里云的python SDK:

还需要准备以下账号内容:

  1. Access Key ID
  2. Access Key Secret
  3. 账号ID

准备好上面的内容后,将你的域名添加到阿里云解析DNS中:

WechatIMG23

完成后再在这个域名下添加一个主机A记录:

WechatIMG24

至此,准备工作已经完成。下面来获取域名的关键信息。

0x03 关键信息

通过脚本更新DNS记录需要几个关键的信息,如下:

  1. 一级域名(你的域名)
  2. 主机记录(你的二级域名)
  3. 记录类型(你的本地IP地址)
  4. 记录ID(这个解析记录的ID)
  5. 记录TTL(记录有效生存时间)

0x03.1 记录ID

其中1,2,3,5是可以确定的,而4则需要通过阿里云API获取:

返还的内容如下:

0x03.2 本机IP

而获取本机IP,我选用ip.cn这个网站。当使用curl访问这个网站时,它会返还IP归属地和IP地址。使用脚本获取:

WechatIMG25

可能因为ip.cn这个站点受到攻击,他们的服务目前不太稳定,请使用my_ip_method_2或my_ip_method_3这两种本地IP的获取方式。

0x04 对比 | 更新

怎样才能知道IP地址是否有改变?

在获取本地IP后,再通过阿里云DNS API获取上一次的记录,两者相对比,如果不一致则更新DNS记录。

0x04.1 上一次的记录

0x04.2 更新记录

0x04.3 对比

0x05 记录

我不但想要更新DDNS记录,我还想记录下每一次重新拨号后获取的IP,说不定日后能做个分析什么的。那么将记录写入文件:

0x06 完整脚本

最新完整脚本请移步至GitHub:阿里云DDNS python脚本

可能因为ip.cn这个站点收到攻击,他们的服务目前不太稳定,请使用my_ip_method_2或my_ip_method_3这两种本地IP的获取方式。

修改第117行即可修改本地IP的获取方式。

0x07 运行

将程序通过crontab每分钟运行一次,请将脚本路径修改为你的实际路径:

0x08 结语

其实这个脚本也可以更新其他类型的DNS记录,例如:CNAME,TXT等,只要知道解析记录ID即可。

经过近3天的运行,一切正常。

12 条评论 / comments

  1. File “aliyun_ddns.py”, line 9, in
    from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest, DescribeDomainRecordsRequest, \
    ImportError: No module named aliyunsdkalidns.request.v20150109
    我现在也遇到了楼上的问题,是接口更新了?

  2. 不支持,这个脚本需要运行在一台主机上,只能获取一个公网地址和更新一个域名。但你可以将它运行在多个不同公网IP的主机上,然后独立配置或使用同一个私钥,但这样会有安全问题。

  3. 你好,我脚本的以下两行所处的位置有误,我修改了脚本,请再次检查相关内容:

    rc_value = my_ip()
    rc_value_old = old_ip()

    account_id:可以在你账户的 账号管理 >> 安全设置 中找到;
    rc_record_id:你需要先将 i_dont_know_record_id = ‘no’ 设为yes,然后运行脚本,在返还的内容中找到RecordId,这个就是了。详情请再次阅读文中 0x03.1 记录ID 章节。获取到RecordId后还需要把i_dont_know_record_id设为no!

    如果你的域名有多个记录,建议将返还回来的json先格式化,然后再查找。可以尝试使用以下工具:

    http://tool.oschina.net/codeformat/json

    如果需要进一步的协助,可以给我发送邮件:contact\@enginx\.net

  4. 您好,我这边新手遇到了一些困难,能帮我看一下,万分感激。
    我执行会出如下错误
    [[email protected] data]# python aliyun_ddns.py
    Traceback (most recent call last):
    File “aliyun_ddns.py”, line 87, in
    rc_value_old = old_ip()
    File “aliyun_ddns.py”, line 68, in old_ip
    result = json.JSONDecoder().decode(result1)
    NameError: global name ‘result1’ is not define

    然后我想问一下:这两个地方是填什么的。
    #请填写你的账号ID
    account_id = “0000”
    #请填写解析记录ID
    rc_record_id = ‘0000’

    再次万分敢接,谢谢

Comments are closed.