前言
最近發現家里的移動寬帶能夠獲取公網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地址了。