使用Python实现动态公网IP和域名动态解析(DDNS)
前言
通过和电信客服沟通了解到,办理“家庭有线宽带公网双栈”业务即可得到一个动态的公网IP地址,不过需要花费20元/月。
缴纳20元/月后,公网IP就顺利拿到了。由于这个公网IP是动态的,如果直接解析到域名的话,每次IP地址更新,都需要重新解析一次,很麻烦也很不方便。
因此萌生了一个想法,希望公网IP地址变更的时候,解析可以自动更新,这其实就是著名的DDNS技术。
DDNS(Dynamic Domain Name System,动态域名系统)是一种网络服务,它实现了将动态变化的IP地址映射到一个固定的域名上。
当然要实现这个功能,可以使用成熟的服务提供商的方法,比如:花生壳(oray.com
)、公云(3322.org
)、Dyndns.com、No-ip.com等平台。
但是这些服务提供商的服务不是价格不菲,就是只能支持固定的域名,无法使用自定义的域名,于是决定自己动手解决。
实现思路
我的域名注册在阿里云,使用的是阿里云的DNS解析服务,因此使用阿里云提供的SDK,就可以解决问题。我熟悉的编程语言是Python,这里就选用了Python来实现。
具体实施
需要安装的模块
提前安装好需要的SDK依赖模块。
pip install aliyun-python-sdk-core-v3
pip install aliyun-python-sdk-domain
pip install aliyun-python-sdk-alidns
pip install requests
编写实现脚本
导入需要使用的模块。
import json
import requests
from urllib.request import urlopen
from aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest import DescribeSubDomainRecordsRequest
from aliyunsdkcore.client import AcsClient
域名配置信息。
# 公有云配置信息
accessKeyId = "XXXXXXXX" # 域名解析服务器 accessKeyId
accessSecret = "XXXXXXXX" # 域名解析服务器 accessSecret
az = "cn-hangzhou" # AZ
domain = "ictstu.com" # 二级域
name_ipv4 = "test1" # 子域
# 初始化阿里云SDK客户端
client = AcsClient(accessKeyId, accessSecret, az)
功能实现主体代码。
def update(RecordId, RR, Type, Value): # 更新域名记录
from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest
request = UpdateDomainRecordRequest()
request.set_accept_format('json')
request.set_RecordId(RecordId)
request.set_RR(RR)
request.set_Type(Type)
request.set_Value(Value)
response = client.do_action_with_exception(request)
def add(DomainName, RR, Type, Value): # 新增域名记录
from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest
request = AddDomainRecordRequest()
request.set_accept_format('json')
request.set_DomainName(DomainName)
request.set_RR(RR)
request.set_Type(Type)
request.set_Value(Value)
response = client.do_action_with_exception(request)
获取当前的公网IP地址。
ipv4 = urlopen('http://ip.ictstu.com').read()
ipv4 = str(ipv4, encoding='ascii')
ipv4 = ipv4.replace('\n', '').replace('\r', '')
获取域名已有的解析配置。
# 获取域名解析记录
request = DescribeSubDomainRecordsRequest()
request.set_accept_format('json')
request.set_DomainName(domain)
request.set_SubDomain(name_ipv4 + '.' + domain)
request.set_Type("A")
response = client.do_action_with_exception(request)
domain_list = json.loads(response)
检查返回结果并决定操作。
if domain_list['TotalCount'] == 0:
add(domain, name_ipv4, "A", ipv4)
print("新建域名解析成功")
elif domain_list['TotalCount'] == 1:
if domain_list['DomainRecords']['Record'][0]['Value'].strip() != ipv4.strip():
update(domain_list['DomainRecords']['Record'][0]['RecordId'], name_ipv4, "A", ipv4)
print("修改域名解析成功")
else:
print("IPv4地址没变")
elif domain_list['TotalCount'] > 1:
from aliyunsdkalidns.request.v20150109.DeleteSubDomainRecordsRequest import DeleteSubDomainRecordsRequest
request = DeleteSubDomainRecordsRequest()
request.set_accept_format('json')
request.set_DomainName(domain)
request.set_RR(name_ipv4)
request.set_Type("A")
response = client.do_action_with_exception(request)
add(domain, name_ipv4, "A", ipv4)
print("修改域名解析成功")
新增企业微信通知
编写发送消息的函数模块,我这里使用的是企业微信的webhook机器人,也可以使用钉钉、邮箱、短信等方式发送消息。
webhook = "webhook地址链接"
#webhook发送消息
def send_text(webhook, content):
header = {
"Content-Type": "application/json",
"Charset": "UTF-8"
}
data ={
"msgtype": "text",
"text": {
"content": content
}
}
data = json.dumps(data)
info = requests.post(url=webhook, data=data, headers=header)
消息获取。
# webhook文本内容
content = "出口公网IP地址更新为:%s" % ipv4
代码使用。
send_text(webhook, content)
代码持续运行
使用Linux系统的crontab服务实现代码持续运行。
每分钟运行一次代码,这样虽然有1分钟的时间差,但是家用足够了,如果要缩小差距可以用代码循环来实现。
*/1 * * * * /usr/bin/python3 /opt/aliyunddns.py
效果
总结
通过该方案可以简单的实现动态公网IP和域名之间的解析,虽有瑕疵但家用足够了。
© 版权声明
文章:使用Python实现动态公网IP和域名动态解析(DDNS)
作者:Guangran
链接:https://www.grbj.cn/1029.html
声明:如无特别说明本文即为原创文章仅代表个人观点,版权归《广然笔记》所有,未经授权、请勿转载。
文章:使用Python实现动态公网IP和域名动态解析(DDNS)
作者:Guangran
链接:https://www.grbj.cn/1029.html
声明:如无特别说明本文即为原创文章仅代表个人观点,版权归《广然笔记》所有,未经授权、请勿转载。
THE END