python+阿里云实现动态域名解析(DDNS)

前言

最近发现家里的移动宽带能够获取公网ipv6地址了,刚好前段时间配了台win10的机子做家用NAS(只能局域网进行文件共享),现在就想利用这个公网ipv6地址实现外网访问,但是电脑每次重启获取的ipv6地址都是变化的,所以需要实现动态域名解析(DDNS)功能。

具体情况

1、可以获取公网ipv6地址,但是ipv4的地址是内网的;

2、在阿里云买了一个1块钱1年的域名,刚可以利用起来;

3、电脑获取的ipv6地址在每次重启后都会自动变化,直接通过域名解析每次重启后域名访问就不行了。

前期准备

1、一个域名(我直接买的阿里的域名,1块钱1年,需要备案)
2、给域名添加解析记录

3、安装阿里云pythonSDK:

阿里云核心SDK库:pip install aliyun-python-sdk-core

阿里云域名SDK库:pip install aliyun-python-sdk-domain(我在看其他博客的时候有写到这个,但是我没找到怎么使用,所以没有用这个),用的下面这个

阿里云域名库:aliyunsdkalidns.zip(直接pip我没有安装成功,需要的可以百度云下载:https://pan.baidu.com/s/1i9-7xpNzFQGdXiTtjqCXLQ,提取码:pr76)

实现思路

1、获取阿里云的accessKeyId和accessSecret
2、获取当前电脑的公网ipv6地址和域名解析的ipv6地址
3、判断当前点奥的公网ipv6地址和域名解析的ipv6地址是否一直
4、ip不一致时,更新域名解析记录

5、添加win10系统的定时任务执行

实现步骤

获取accessKeyId和accessSecret

这个可以直接在阿里云控制台的个人中心获取,不清楚的可以直接百度

获取本机ipv6地址

1 # 获取本机临时IPv6地址
2 def get_local_ip():
3     child = subprocess.Popen("ipconfig", shell=True, stdout=subprocess.PIPE)
4     out = child.communicate()  # 保存ipconfig中的所有信息
5     ipv6_pattern = '(([a-f0-9]{1,4}:){7}[a-f0-9]{1,4})'
6     m = re.findall(ipv6_pattern, str(out))
7     address = m[1][0]
8     return address

获取域名当前解析ip(利用"nslookup+域名"的方式)

1 # 获取当前域名对应的ip地址
2 def get_internet_ip():
3     child = subprocess.Popen("nslookup nideyuming", shell=True, stdout=subprocess.PIPE)
4     out = child.communicate()  # 保存nslookup获取的所有信息
5     ipv6_pattern = '(([a-f0-9]{1,4}:){7}[a-f0-9]{1,4})'
6     m = re.findall(ipv6_pattern, str(out))
7     address = m[0][0]  # 拿到ipv6地址
8     return address

利用UpdateDomainRecordRequest这个action执行域名解析更新操作,但是在执行这个action的时候需要传RecordId参数,需要先通过DescribeDomainRecordsRequest这个action获得RecordId。

获取RecordId

 1 # 获取recordid
 2 def get_recordid(client):
 3     request = DescribeDomainRecordsRequest()
 4     request.set_accept_format('json')
 5     request.set_DomainName("nideyuming")#这个地方传你的域名信息
 6     response = client.do_action_with_exception(request)
 7     response = str(response, encoding='utf-8')
 8     result = json.loads(response)
 9     recordid = result["DomainRecords"]["Record"][0]["RecordId"]
10     return recordid

更新域名解析

 1 # 更新域名解析
 2 def update_record(client, priority, ttl, record_type, value, rr, record_id):
 3     request = UpdateDomainRecordRequest()
 4     request.set_accept_format('json')
 5     request.set_Priority(priority)
 6     request.set_TTL(ttl)
 7     request.set_Value(value)
 8     request.set_Type(record_type)
 9     request.set_RR(rr)
10     request.set_RecordId(record_id)
11     response = client.do_action_with_exception(request)
12     response = str(response, encoding='utf-8')
13     return response

判断上面2步获取的ip是否相同,如果相同就不需要更新域名解析ip了,如果不同就执行更新操作

执行

 1 # 函数调用
 2 def run_result(client, priority, ttl, record_type, value, rr, record_id):
 3     if get_local_ip() == get_internet_ip():
 4         print("解析地址未发生变化,不修改!")
 5         pass
 6     else:
 7         result = update_record(client, priority, ttl, record_type, value, rr, record_id)
 8         result = json.loads(result)
 9         print("新的RecordId是:%s" % result["RecordId"])
10 
11 
12 if __name__ == '__main__':
13     client = AcsClient('youraccessKeyId', 'youraccessSecret', 'cn-chengdu')
14     record_id = get_recordid(client)
15     ip = get_local_ip()
16     run_result(client, "5", "600", "AAAA", ip, "@", record_id)

为了简单,我把所有代码放到一个.py文件里了,整体代码如下:

完整代码

 1 #!/usr/bin/env python
 2 # coding=utf-8
 3 
 4 from aliyunsdkcore.client import AcsClient
 5 from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest
 6 from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest
 7 import json
 8 import subprocess
 9 import re
10 
11 
12 # 获取当前域名对应的ip地址
13 def get_internet_ip():
14     child = subprocess.Popen("nslookup nideyuming", shell=True, stdout=subprocess.PIPE)
15     out = child.communicate()  # 保存nslookup获取的所有信息
16     ipv6_pattern = '(([a-f0-9]{1,4}:){7}[a-f0-9]{1,4})'
17     m = re.findall(ipv6_pattern, str(out))
18     address = m[0][0]  # 拿到ipv6地址
19     return address
20 
21 
22 # 获取本机临时IPv6地址
23 def get_local_ip():
24     child = subprocess.Popen("ipconfig", shell=True, stdout=subprocess.PIPE)
25     out = child.communicate()  # 保存ipconfig中的所有信息
26     ipv6_pattern = '(([a-f0-9]{1,4}:){7}[a-f0-9]{1,4})'
27     m = re.findall(ipv6_pattern, str(out))
28     address = m[1][0]
29     return address
30 
31 
32 # 获取recordid
33 def get_recordid(client):
34     request = DescribeDomainRecordsRequest()
35     request.set_accept_format('json')
36     request.set_DomainName("nideyuming")#传你的域名
37     response = client.do_action_with_exception(request)
38     response = str(response, encoding='utf-8')
39     result = json.loads(response)
40     recordid = result["DomainRecords"]["Record"][0]["RecordId"]
41     return recordid
42 
43 
44 # 更新域名解析
45 def update_record(client, priority, ttl, record_type, value, rr, record_id):
46     request = UpdateDomainRecordRequest()
47     request.set_accept_format('json')
48     request.set_Priority(priority)
49     request.set_TTL(ttl)
50     request.set_Value(value)
51     request.set_Type(record_type)
52     request.set_RR(rr)
53     request.set_RecordId(record_id)
54     response = client.do_action_with_exception(request)
55     response = str(response, encoding='utf-8')
56     return response
57 
58 
59 # 函数调用
60 def run_result(client, priority, ttl, record_type, value, rr, record_id):
61     if get_local_ip() == get_internet_ip():
62         print("解析地址未发生变化,不修改!")
63         pass
64     else:
65         result = update_record(client, priority, ttl, record_type, value, rr, record_id)
66         result = json.loads(result)
67         print("已更新解析地址,新的RecordId是:%s" % result["RecordId"])
68 
69 
70 if __name__ == '__main__':
71     client = AcsClient('youraccessKeyId', 'youraccessSecret', 'cn-chengdu')#这儿传你的accessKeyId、accessSecret和区域ID(region_id)
72     record_id = get_recordid(client)
73     ip = get_local_ip()
74     run_result(client, "5", "600", "AAAA", ip, "@", record_id)

以上,执行该.py文件,就会自动更新当前电脑的公网ipv6地址到域名解析

电脑执行.py脚本

我配置了1个开机执行的任务,一个每天早上9点执行的定时任务。这块儿的资料网上很多,这儿写下2个要注意的点。

1、创建了一个开机自动执行的任务,这儿我最开始选择的只在用户登录是运行,重启电脑后发行没有自动执行,改成不管用户是否登录都有运行就ok了

1、原来的方法有点问题,重启确实会自动执行,但是如果是关机再开机就没有执行了,我最后的处理方式是在该定时任务上新加了一个用户登录时执行的触发器,并设置win10开机自动登录。具体方法是在运行框输入netplwiz,在弹窗窗口中取消勾选“要使用本计算机,用户必须输入用户名和密码”项并保存,保存的时候会让输入账号的用户名和密码。之后开机就会自动登录并触发该任务了。

 

 2、操作里面直接填写python.exe和要执行的.py脚本的据对路径就ok了

 

 以上,重启下电脑,自动执行脚本成功,登录阿里云查看域名解析ip也已经变成本机最新获取的ipv6地址了。

 

 

 

 

 

 

 



 

posted on 2020-06-07 20:53  菜鸡快学  阅读(3018)  评论(0编辑  收藏  举报

导航