前言
前置條件
1、域名是在阿里雲購買的
2、地址必須是公網地址,不然加了解析也沒有用
簡介
通過阿里雲提供的SDK,然後自己編寫程序新增或者修改域名的解析,達到動態解析域名的目的;主要應用於pppoe撥號的環境,比如家裏設置了服務器,但是外網地址經常變化的場景;再比如公司的pppoe網關,需要建立vpn的場景。
安裝阿里雲SDK
需要安裝兩個SDK庫,一個是阿里雲核心SDK庫,一個是阿里雲域名SDK庫;
阿里雲核心SDK庫:pip install aliyun-python-sdk-core
阿里雲域名SDK庫:pip install aliyun-python-sdk-domain
阿里雲SDK幫助
關於調試
阿里雲提供一個在線調試,支持在線調試好之後,再複製回來本地即可。使用調試平臺需要先登錄。在線調試平臺
API的模塊名稱都可以通過幫助文檔查詢
設計思路
一、獲取阿里雲的accessKeyId和accessSecret
二、獲取外網ip
三、判斷外網ip是否與之前一致
四、外網ip不一致時,新增或者更新域名解析記錄
詳細步驟
獲取accessKeyId和accessSecret
可以在阿里雲控制檯個人中心直接獲取,但是一般建議使用RAM角色來進行權限控制,這樣這個accessKey和accessSecret就只能操作域名,不能操作其他的資源,相對會比較安全。關於RAM快速入門,請點擊鏈接
獲取到accessKeyId和accessSecret之後,填入相對應的函數中即可:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from hwx_function import *
import os
import time
client = AcsClient('<accessKeyId>', '<accessSecret>', 'cn-hangzhou')
獲取外網IP
通過網絡上面的外網ip的API獲取,可以使用多個,我這裏只是列舉了一個,具體代碼如下:
def get_internet_ip():
with urllib.request.urlopen('http://www.3322.org/dyndns/getip') as response:
html = response.read()
ip = str(html, encoding='utf-8').replace("\n", "")
return ip
判斷IP是否一致
因爲阿里雲不允許修改相同的解析,所以需要比對IP是否一致;因爲把上一次解析的IP寫入文件,所以只需要讀取出來,跟本次得到的外網IP相比較,一致則不修改解析記錄,不一致則修改解析記錄。關於域名解析操作的代碼,下面會有解釋。
with open("./ip", 'r') as f:
old_ip = f.read()
if ip == old_ip:
print("noupdate"+"\nnew_ip:"+ip+"\nold_ip:"+old_ip)
else:
#print("update"+"\nnew_ip:"+ip+"\nold_ip:"+old_ip)
wirte_to_file("./ip",ip)
des_relsult = Describe_SubDomain_Records(client,"A","sz.huangwx.cn")
#判斷子域名解析記錄查詢結果,TotalCount爲0表示不存在這個子域名的解析記錄,需要新增一個
if des_relsult["TotalCount"] == 0:
add_relsult = add_record(client,"5","600","A",ip,"sz","huangwx.cn")
record_id = add_relsult["RecordId"]
print("域名解析新增成功!")
#判斷子域名解析記錄查詢結果,TotalCount爲1表示存在這個子域名的解析記錄,需要更新解析記錄,更新記錄需要用到RecordId,這個在查詢函數中有返回des_relsult["DomainRecords"]["Record"][0]["RecordId"]
elif des_relsult["TotalCount"] == 1:
record_id = des_relsult["DomainRecords"]["Record"][0]["RecordId"]
update_record(client,"5","600","A",ip,"sz",record_id)
print("域名解析更新成功!")
else:
record_id = 0
print("存在兩個子域名解析記錄值,請覈查刪除後再操作!")
path = './RecordId'
wirte_to_file(path,record_id)
域名解析記錄操作
域名解析記錄不存在時,就新增解析記錄,如果已經存在,則修改解析記錄;所以這裏還需要用到查詢子域名解析記錄的API;
子域名解析記錄查詢
Describe_SubDomain_Records(client,"A","sz.huangwx.cn")
這個函數會返回一大堆東西,但是目前我們需要使用的就兩個,一個是解析記錄的數量,一個就是RecordId,RecordId修改域名解析時需要用到;
#這個是函數
def Describe_SubDomain_Records(client,record_type,subdomain):
request = DescribeSubDomainRecordsRequest()
request.set_accept_format('json')
request.set_Type(record_type)
request.set_SubDomain(subdomain)
response = client.do_action_with_exception(request)
response = str(response, encoding='utf-8')
relsult = json.loads(response)
return relsult
#以下是函數調用以及說明
des_relsult = Describe_SubDomain_Records(client,"A","sz.huangwx.cn")
des_relsult["TotalCount"]:解析記錄的數量,0表示解析記錄不存在,1表示有一條解析記錄
des_relsult["DomainRecords"]["Record"][0]["RecordId"]:當des_relsult["TotalCount"]爲1時,會返回這個RecordId,後續的修改域名解析記錄中需要用到
新增域名解析記錄
如果域名解析記錄不存在時,就需要新增域名解析記錄,新增域名解析記錄比較簡單,直接填寫參數即可
def add_record(client,priority,ttl,record_type,value,rr,domainname):
request = AddDomainRecordRequest()
request.set_accept_format('json')
request.set_Priority(priority)
request.set_TTL(ttl)
request.set_Value(value)
request.set_Type(record_type)
request.set_RR(rr)
request.set_DomainName(domainname)
response = client.do_action_with_exception(request)
response = str(response, encoding='utf-8')
relsult = json.loads(response)
return relsult
#函數調用
add_relsult = add_record(client,"5","600","A",ip,"sz","huangwx.cn")
record_id = add_relsult["RecordId"]#同樣會返回一個RecordId,修改的時候也可以直接調用
更新域名解析記錄
如果域名解析記錄已存在,則不能使用新增,而是更新域名解析記錄。更新的時候需要用到RecordId,這個一般查詢的時候就會有返回,直接使用即可
def update_record(client,priority,ttl,record_type,value,rr,record_id):
request = UpdateDomainRecordRequest()
request.set_accept_format('json')
request.set_Priority(priority)
request.set_TTL(ttl)
request.set_Value(value)
request.set_Type(record_type)
request.set_RR(rr)
request.set_RecordId(record_id)
response = client.do_action_with_exception(request)
response = str(response, encoding='utf-8')
return response
#函數調用
record_id = des_relsult["DomainRecords"]["Record"][0]["RecordId"]
update_record(client,"5","600","A",ip,"sz",record_id)
再加個循環或者定時任務即可定時更新域名解析記錄了
總結
1、阿里雲函數的使用依賴於阿里雲的SDK庫,所以這個一定要安裝好
2、新增解析記錄的時候,可以把RecordId存儲在本地文件,下次直接判斷文件是否存在即可,不用每次都調用查詢API