前言
最近发现家里的移动宽带能够获取公网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了
2、操作里面直接填写python.exe和要执行的.py脚本的据对路径就ok了
以上,重启下电脑,自动执行脚本成功,登录阿里云查看域名解析ip也已经变成本机最新获取的ipv6地址了。