本文源自 CNSS 工作室招新题目。项目完成于 2020.10.10

DDNS 是运维中经常遇到的技术,其核心在于定时获取主机 IP 地址和自动更新域名记录。本文主要回顾了我使用 Python 独立开发 DDNS for Dnspod 脚本的过程,并介绍了这个脚本的使用方法。

需要注意的是,这个脚本的开发意义并不大,因为网上已经有大量的成熟可靠现成项目可供调用。对于我个人而言,虽然难度不高,但这是我第一次开发此类脚本,可谓是一次有益的尝试(实际上就是为了完成招新题目)

项目地址:https://github.com/Nativu5/dnspod-ddns-python

特性

  • 便捷的安装卸载,方便部署;
  • 支持 2/3 级域名和同时多个域名的管理;
  • 支持定时检测和更新解析记录。

使用的库

除了 Python 内建的库之外,使用了 Requests 和 Crontab 库。

前者用于与 api 进行交互,获取公网 IP 和操作解析记录;

后者用于管理系统 Crontable,实现程序的定时启动。

获取公网 IP

这里我使用了 http://myip.ipip.net/ 提供的接口,直接用 Request 获取网页内容然后匹配得到 IP 地址即可。

操作解析记录

DNSPod API 文档:https://docs.dnspod.cn/api/

约定

调用 DNSPod 提供的 API,当然需要遵守约定。

需要注意的几点:

1. 关于滥用:
包括但不限于以下情形都被视为滥用:

  • 短时间内大量添加、删除、修改、刷新域名或者记录,或者设置记录状态。
  • 记录内容没有任何改变的刷新,比如动态 DNS 中 IP 没变也请求修改记录。
  • 程序逻辑不严谨、程序死循环等等,可能造成大量无效、重复的请求。
  • 其它没有提到的,但会给系统带来压力的请求行为。

在对接口进行操作前必须确保使用者提供的信息正确,如果不正确就需要立刻终止操作并提醒用户,否则可能因为频繁操作被封禁。同时由于我们的程序定时检测并更新记录,必须确保在 IP 发生变化后才尝试更新,否则大量请求修改 IP 但实际又不修改的操作将被视为非法操作。

4. 关于请求:

  • 请求的地址为 https://dnsapi.cn/ 开头的地址,基于 SSL 安全传输。为了安全必须用 https 开头的地址,否则将有可能被封禁。
  • 只支持 POST 方法请求数据,用其它方法会提示错误。
  • 请用 UTF-8 编码进行数据传输,返回的数据也是 UTF-8 编码的。

5. 关于UserAgent:
请求的时候必须设置 UserAgent ,如果不设置或者设置为不合法的(比如设置为浏览器的)也会导致帐号被封禁 API 。
UserAgent 的格式必须为:程序英文名称/版本(联系邮箱),比如:MJJ DDNS Client/1.0.0 (dnspod@dnspod.cn)

第 4、5 条说的都很清楚了。

另外还有一点,文档中可能还没有更新。DNSPod 原本是使用用户邮箱 + 密码进行鉴权的,但是现在已经弃用了这种方式,换成 ID + Token 的鉴权方式(相对安全一点)。

我们的程序在运行时会生成 config.json 用来保存用户的信息,其中就包括 ID、Token 和用户要操作的域名。

传递参数

传递的参数主要有两部分:公共请求参数和具体某个 API 的参数。

每个请求都需要公共参数,因为公共参数主要涉及的是用户鉴权和传递数据的一些约定,所以在本程序中公共参数基本上是一样的。

某个 API 的参数由于 API 功能不同,所以需要自己阅读文档修改程序。

接收返回值

返回的数据类型是在传递参数时确定的。根据官方文档,有 xml 和 json 可以选择,这里官方推荐 json,我自然也选择 json。

关于对 json 数据的操作,Python 自带的 json 库很是强大,和 Python 内置 Dict 类型配合很好,基本上边写边学就可以了。(Python 大法好)

定时任务

这里通过 Crontab 库实现定时操作。

参考:

语法非常简单!这里主要多说两句软件维护对应 Crontab 任务的方法:

  • 程序操作 Crontab 时 务必添加注释!因为只有通过注释才能知道这条记录属于谁。例如本项目在 Crontab 中的注释如下:

    comment='DDNS for DNSPOD'
  • 安装时最好扫描 Crontab,将含有上述注释的记录先删掉,防止数据混乱。
  • 卸载时自然可以通过安装时添加的注释找到并清理所有软件添加的记录。

代码

略。直接去 Github 查看吧。

使用说明

略。直接去 Github 查看吧。