前言
前置條件
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