生活随笔
收集整理的這篇文章主要介紹了
Python 实现动态解析阿里云DNS记录
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、背景
最近有一個需求,公司內(nèi)網(wǎng)的IP地址會發(fā)生變化,導(dǎo)致阿里云域名不能解析到新的IP地址,此時我們需要對阿里云的域名進(jìn)行更新
二、實現(xiàn)
2.1 獲取本地出口的公網(wǎng)IP
2.1.1 通過命令或網(wǎng)頁 - 獲取本地出口的公網(wǎng)IP**
獲取本地IP的方式有很多,可以通過訪問一些網(wǎng)站來獲取本地的公網(wǎng)IP地址
1. curl ifconfig.me
2. curl -L ip.tool.lu
3. 以及一些在線查詢網(wǎng)頁然后解析內(nèi)容來獲取我們的公網(wǎng)IP地址
2.1.2 通過Nginx 獲取我們的公網(wǎng)IP
我們通過在云端創(chuàng)建一個主機地址,然后通過nginx來獲取訪問者的公網(wǎng)IP,這樣的好處是我們自己搭建的服務(wù)比較穩(wěn)定可靠
-
1. 創(chuàng)建阿里云主機記錄
在域名服務(wù)中通過訪問域名列表點擊解析
-
2. 新增獲取訪問者IP的主機記錄
設(shè)置主機地址,記錄值這里填寫自己阿里云的IP地址,這是為了訪問這個域名地址時,nginx返回訪問者的IP地址。
-
3. 新增測試的主機記錄
我們可以自己在新建一個記錄,主機記錄隨意填寫一個如dev,IP地址也可以隨意填寫一個。
-
4. Nginx 返回對應(yīng)的域名時返回訪問者的IP
新建一個nginx的配置文件,指定域名返回的內(nèi)容
root@rion:/etc/nginx/conf.d# pwd
/etc/nginx/conf.d
root@rion:/etc/nginx/conf.d# ls
remote_ip.conf
root@rion:/etc/nginx/conf.d# cat remote_ip.conf
real_ip_recursive on;
server {listen 80; # 指定訪問端口,如果不想用80端口,需要在阿里云開啟對應(yīng)的端口server_name ip.xxx.xx;# 省略其他配置....# nginx直接返回客戶端IP到bodylocation /ip {default_type text/plain;return 200 "$remote_addr";}
}
root@rion:/etc/nginx/conf.d# nginx -s reload
訪問對應(yīng)的域名查看結(jié)果是否正確,返回的結(jié)果時正確的。
2.2 實現(xiàn)動態(tài)更新阿里云IP地址
2.2.1 獲取AccessKey ID和AccessKey Secret
我們使用SDK時,需要使用到AccessKey ID和AccessKey Secret 。
參考鏈接: https://help.aliyun.com/document_detail/38738.html
2.2.2 代碼實現(xiàn)
-
下載python包
aliyun-python-sdk-core-v3
aliyun-python-sdk-alidns
-
代碼
import requests
import traceback
import time
from datetime
import datetime
import json
import sys
from aliyunsdkcore
.client
import AcsClient
from aliyunsdkalidns
.request
.v20150109
.DescribeDomainRecordsRequest
import DescribeDomainRecordsRequest
from aliyunsdkalidns
.request
.v20150109
.UpdateDomainRecordRequest
import UpdateDomainRecordRequest
class DNSRecord:json_data
= None client
= None public_dic
= {"time":None,"ip":None} dns_record_dic
= {"time":None,"ip":None,"record_id":None}@classmethoddef init(cls
):"""初始化阿里云 client"""try:cls
.client
= AcsClient
(cls
.json_data
['id'], cls
.json_data
['secret'], cls
.json_data
['region'])print("Aliyun key 認(rèn)證成功")return Trueexcept Exception
as e
:print("Aliyun key 認(rèn)證失敗")return False@classmethod def reload_config(cls
):"""加載配置文件"""with open('./config.json',mode
='r',encoding
='utf-8') as fp
:cls
.json_data
= json
.load
(fp
)@classmethoddef get_dns_record(cls
):"""獲取dns記錄"""try:request
= DescribeDomainRecordsRequest
()request
.set_accept_format
('json')request
.set_DomainName
(cls
.json_data
['domain_name'])response
= cls
.client
.do_action_with_exception
(request
)data
= json
.loads
(str(response
, encoding
='utf-8'))for record
in data
['DomainRecords']['Record']:if cls
.json_data
['RR'] == record
['RR']:cls
.dns_record_dic
['time'] = datetime
.now
()cls
.dns_record_dic
['ip'] = record
['Value']cls
.dns_record_dic
['record_id'] = record
['RecordId']return Trueexcept:traceback
.print_exc
()return False@classmethoddef get_public_ip(cls
):"""獲取公網(wǎng)IP"""for url
in cls
.json_data
['public_url']:try:request_obj
= requests
.get
(url
,timeout
=5)if request_obj
.status_code
== 200:cls
.public_dic
['time'] = datetime
.now
()cls
.public_dic
['ip'] = request_obj
.text
return Trueexcept:traceback
.print_exc
()return False@classmethoddef update_dns_record(cls
,public_ip
):update_time
= datetime
.now
()update_time_str
= update_time
.strftime
("%Y-%m-%d %H:%M:%S")try:request
= UpdateDomainRecordRequest
()request
.set_accept_format
('json')request
.set_Value
(public_ip
)request
.set_Type
(cls
.json_data
['type'])request
.set_RR
(cls
.json_data
['RR'])request
.set_RecordId
(cls
.dns_record_dic
['record_id'])response
= cls
.client
.do_action_with_exception
(request
)cls
.public_dic
['time'] = update_timecls
.dns_record_dic
['time'] = update_time
print(f"
[更新成功
{update_time_str
}] 域名
:{cls
.json_data
['domain_name']} + \主機
:{cls
.json_data
['RR']} 記錄類型
:{cls
.json_data
['type']} + \IP地址
:{cls
.dns_record_dic
['ip']}"
)return Trueexcept Exception
as e
:print(f"域名:{cls.json_data['domain_name']} 主機:{cls.json_data['RR']} 解析失敗,錯誤:",e
)return False@classmethoddef main(cls
):cls
.reload_config
()cls
.init
()while True:public_time
= cls
.public_dic
['time']dns_time
= cls
.dns_record_dic
['time']if not dns_time
: ret
= cls
.get_dns_record
() if not ret
:time
.sleep
(10)continuedns_time
= cls
.dns_record_dic
['time']if not public_time
: ret
= cls
.get_public_ip
() if not ret
:time
.sleep
(10)continuepublic_time
= cls
.public_dic
['time']if (public_time
- dns_time
).total_seconds
() < 300: print("本地更新時間與云端更新時間差小于5分鐘")time
.sleep
(10)continueelse:public_ret
= cls
.get_public_ip
() if not public_ret
:time
.sleep
(10)continuedns_ret
= cls
.get_dns_record
() if not dns_ret
:time
.sleep
(10)continuepublic_ip
= cls
.public_dic
['ip']dns_ip
= cls
.dns_record_dic
['ip']if public_ip
!= dns_ip
: ret
= cls
.update_dns_record
(public_ip
)if not ret
:time
.sleep
(10)else:time
.sleep
(10)if __name__
== "__main__":dns_r
= DNSRecorddns_r
.main
()
{"id":"xxxxxxxxxxxxxxxxxx","secret":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx","region":"cn-hangzhou","RR":"dev","type":"A","domain_name":"xxxxx.xx","public_url":["http://ip.xx.xx/ip","http://xx.xxx.xx:8899/ip"]
}
這里獲取本地公網(wǎng)IP的對象為列表,若一個獲取地址的URL掛掉了,我們還可以從另一個地址獲取本地公網(wǎng)的IP,保證了一定的穩(wěn)定性。
參考鏈接: https://help.aliyun.com/document_detail/124923.html
以上是python實現(xiàn)動態(tài)更新阿里云DNS解析記錄的代碼,除了更新記錄之外還可以增加記錄,刪除記錄等。
總結(jié)
以上是生活随笔為你收集整理的Python 实现动态解析阿里云DNS记录的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。