Python 百度域名 DDNS 自动解析工具

本文最后更新于:2022年8月10日 上午

DDNS 动态域名服务中介绍了DDNS的含义,本文记录:使用python语言,基于百度域名解析更新API,封装设计成自动同步本地IP的DDNS工具。

前置条件

  • 具有 DDNS 需求 (IPv4 或 IPv6)
  • 申请了百度云域名 (其他家的域名本文方法不适用)
  • 了解DDNS (DDNS 动态域名服务
  • 可以运行python程序

核心实现

将百度 API 中的 DNS 更新模块 封装成一个工程,简单介绍功能和核心实现

功能

  • 动态获取本机指定 IP
  • 自动对比当前本地 IP 与域名指向的IP
  • 当本地 IP 发生变化时自动向远程同步
  • 可以同步 A 记录(IPv4)和 AAAA 记录(IPv6)
  • 可以配置同步频率,同步IP类型
  • 保留较为完整的日志

获取本机 IP

获取本机IP的核心代码,可以获取 IPv4 或 IPv6 的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def getIP(self, ip_type):#获取本地公网IP
assert ip_type in self.IP_TYPE
if ip_type == 'ipv4':

url="http://pv.sohu.com/cityjson?ie=utf-8"
res=requests.get(url,timeout=5).text
res=res.split("=")[1].split(";")[0] #转换javascript为json格式
res=json.loads(res)
res=res["cip"]

elif ip_type == 'ipv6':
url="https://ipv6.ipw.cn/"
res=requests.get(url,timeout=5).text
else:
raise RuntimeError(f"unknown ip type {ip_type}")
return res.upper()
  • 其中 ip_type 为IP类型,可为 IPv4IPv6

获取当前 DNS 信息

需要获取当前DNS 状态,以判断是否需要更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def get_domain_info(self, domain):
data={
'domain':self.url,
'pageNo':1,
'pageSize':100
}
url="/v1/domain/resolve/list"
res=self.post(url,data)
decoded_res = res.decode()

json_part = decoded_res[decoded_res.find('\r\n{') + 2: decoded_res.find('}\r\n') + 1]
clean_json_part = json_part.replace('\r', '').replace('\n', '')

pattern = r'{"recordId":[^"]+,"domain":"' + domain + r'","view":"[^"]+","rdtype":"[^"]+","ttl":[^"]+,"rdata":"[^"]+","zoneName":"[^"]+","status":"[^"]+"}'
searchObj = re.search(pattern, clean_json_part, flags=0)
assert searchObj is not None, f"get_domain_info failed"

domain_str = clean_json_part[searchObj.span()[0]:searchObj.span()[1]]

domain_info = json.loads(domain_str)

return domain_info
  • 其中 domain 为二级域名名称

更新DNS记录

构造更新DNS所需的报文格式

注意如果地址为 IPv6,地址中的字母需要大写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def SET(self, domain, ip_type, logger):
assert ip_type in self.IP_TYPE
logger("ddns ready to update data. ")

# ip
try:
local_ip = self.getIP(ip_type)
logger(f"get local IP: {local_ip}")
except Exception as e:
logger(f"get local IP failed, exception {e}")
return False

# rdtype
if ip_type == 'ipv4':
rd_type = 'A'
elif ip_type == 'ipv6':
rd_type = 'AAAA'
else:
raise RuntimeError(f"unknown ip_type {ip_type}")
logger(f"ip type {rd_type}")

# record
try:
domain_info=self.get_domain_info(domain)
logger(f"get domain info: {domain_info}")
dns_ip = domain_info['rdata'].upper()
recordId = domain_info['recordId']
except Exception as e:
logger(f"get domain_info failed, exception {e}")
return False

if local_ip!=dns_ip:
logger(f"local IP changed, a update will be launched.")
url="/v1/domain/resolve/edit"
data={
"domain" : domain,
"rdType" : rd_type,
"rdata" : local_ip,
"ttl" : 60,
"zoneName" : self.url,
"recordId" : recordId
}

res=self.post(url, data)
res_str = res.decode()
split_lit = res_str.split(' ')
if int(split_lit[1]) != 200:
logger(f"DDNS update failed, error code {split_lit[1]}")
logger(f"http responce: {res_str}")
else:
logger("DDNS update successfully !!!")
else:
logger("local IP is same as reomte IP, skip updating.")

其中 logger 为日志对象

DDNS 配置使用

下载代码

1
git clone git@git.zhlh6.cn:zywvvd/baidu_ddns.git

更改配置

  • assets/config.json中配置域名Access KeySecret Key
  • main.py 文件中配置检测时间间隔二级域名名称IP类型

运行程序

1
python main.py

示例日志

1
2
3
4
5
6
7
8
9
2022-01-02 00:43:21: ************************************************************
2022-01-02 00:43:21: ****************** Baidu DDNS start !!! ******************
2022-01-02 00:43:22: ************************************************************
2022-01-02 00:43:22: ddns ready to update data.
2022-01-02 00:43:22: get local IP: 2409:8A1E:8FCA:BB20:F87C:DD68:7B9D:D395
2022-01-02 00:43:22: ip type AAAA
2022-01-02 00:43:23: get domain info: {'recordId': 23134869, 'domain': 'itest6', 'view': 'DEFAULT', 'rdtype': 'AAAA', 'ttl': 60, 'rdata': '2409:8A1E:8FCA:BB20:F87C:3568:739D:D395', 'zoneName': 'zywvvd.com', 'status': 'RUNNING'}
2022-01-02 00:43:23: local IP is same as reomte IP, skip updating.

参考资料


Python 百度域名 DDNS 自动解析工具
https://www.zywvvd.com/notes/coding/python/baidu-ddns/baidu-ddns/
作者
Yiwei Zhang
发布于
2022年1月2日
许可协议