跳到主要内容

结合阿里云DNS实现动态DNS

· 阅读需 3 分钟

动态DNS 实现

项目已放Github,欢迎Star。 https://github.com/MasonSRE/ddns

编写脚本获取公网IP地址,实时更新DNS记录

编写 get_ip_dns.py

import time
import logging
import requests
import json
from aliyunsdkcore.client import AcsClient
from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkalidns.request.v20150109 import DescribeDomainRecordsRequest, DescribeDomainRecordInfoRequest


# 阿里云API凭证
access_key_id = 'your_access_key_id'
access_key_secret = 'your_access_key_secret'
region_id = 'cn-hangzhou' # 你的阿里云区域ID (可以不做修改)

# 域名和记录信息
domain_name = 'example.com' # 你的域名
sub_domain = 'www' # 子域名,例如www

# 设置日志记录
logging.basicConfig(level=logging.INFO)

def get_public_ip():
try:
response = requests.get('https://api.ipify.org?format=json')
response.raise_for_status() # 抛出HTTP错误
ip = response.json()['ip']
logging.info(f'Public IP retrieved: {ip}')
return ip
except requests.exceptions.RequestException as e:
logging.error(f'Failed to retrieve public IP: {e}')
return None

def get_current_dns_record(client, domain_name, sub_domain):
request = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest()
request.set_DomainName(domain_name)
try:
response = client.do_action_with_exception(request)
records = json.loads(response)['DomainRecords']['Record']
for record in records:
if record['RR'] == sub_domain and record['Type'] == 'A':
return record['RecordId'], record['Value']
return None, None
except ServerException as e:
logging.error(f'Failed to get the current DNS record: {e}')
return None, None

def update_dns_record(client, record_id, sub_domain, ip):
request = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
request.set_RecordId(record_id)
request.set_RR(sub_domain)
request.set_Type('A')
request.set_Value(ip)
try:
client.do_action_with_exception(request)
logging.info(f'Updated DNS record to {ip}')
except ServerException as e:
logging.error(f'Failed to update DNS record: {e}')

def add_dns_record(client, domain_name, sub_domain, ip):
request = AddDomainRecordRequest.AddDomainRecordRequest()
request.set_DomainName(domain_name)
request.set_RR(sub_domain)
request.set_Type('A')
request.set_Value(ip)
try:
client.do_action_with_exception(request)
logging.info(f'Added DNS record: {sub_domain}.{domain_name} -> {ip}')
except ServerException as e:
logging.error(f'Failed to add DNS record: {e}')

def update_dns_record_if_needed(client, domain_name, sub_domain, new_ip):
record_id, current_ip = get_current_dns_record(client, domain_name, sub_domain)
if record_id is None:
logging.warning(f'No existing DNS record found for {sub_domain}.{domain_name}, adding a new record.')
add_dns_record(client, domain_name, sub_domain, new_ip)
return
if current_ip != new_ip:
update_dns_record(client, record_id, sub_domain, new_ip)

def main():
client = AcsClient(access_key_id, access_key_secret, region_id)

while True:
new_ip = get_public_ip()
if new_ip is not None:
update_dns_record_if_needed(client, domain_name, sub_domain, new_ip)
time.sleep(10) # 等待10秒再检查

if __name__ == '__main__':
main()

检查公网IP并更新 DNS 纪录

此脚本将获取该服务器的公网IP,并且修改阿里云对应的DNS解析的A纪录。

  • 非常适用于家用网络,公网IP改变时也会同步修改至Aliyun dns解析
  • 手动误修改此DNS解析时,也会进行操作IP对比,同时进行修改 dns 解析

1、下载依赖包

pip3 install requests
pip3 install aliyun-python-sdk-core
pip3 install aliyun-python-sdk-alidns

2、修改配置

# 阿里云API凭证
access_key_id = 'your_access_key_id'
access_key_secret = 'your_access_key_secret'
region_id = 'cn-hangzhou' # 你的阿里云区域ID(可以不做修改)

# 域名和记录信息
domain_name = 'example.com' # 你的域名
sub_domain = 'www' # 子域名,例如www

3、运行脚本

python3 get_ip_dns.py