Python教程

【script】python 调用阿里云解析 DNS API 实现 DDNS(动态域名解析)

本文主要是介绍【script】python 调用阿里云解析 DNS API 实现 DDNS(动态域名解析),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、前情提要

​ 由于当前IPv4公网地址匮乏 ,一般来说,即便你是电信或联通的宽带,运营商默认也是不会给你分配公网 IP 的,需要向运营商提出申请,根据地区不同,申请难易程度不同。少数地区可以通过公众号或装维师父直接联系申请,大部分地区需要拨打人工客服(电信 10000,联通 10010)以“家中要安装家庭网络摄像头”为理由申请动态公网 IP(千万不能说是服务器或其他设备),少数地区可能一次无法申请成功(很多客服不清楚动态公网 IP,所以可以尝试多换几个客服),申请成功后重启光猫即可。不过运营商提供的公网IP地址是动态的,一段时间后或光猫/路由器重启,公网IP地址就发生变化。 这就导致我们不能直接把得到的公网IP绑定到自己的域名上,每次IP地址发生变化,域名就无法访问了。于是就需要用到DDNS服务。DDNS(动态域名解析)是把互联网域名指向可变IP地址的系统。DNS只是提供了域名和IP地址之间的静态对应关系,当IP地址发生变化时,DNS无法动态的更新域名和IP地址之间的对应关系,从而导致访问失败。但是DDNS系统是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络时,客户端程序通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,实现动态域名解析。

​ 官方文档可参考 阿里云 DNS API 快速入门 。

注:现在不少路由器都带有DDNS服务,不过提供的服务商有限仅支持花生壳、公云等。要想使用自己手头的阿里域名就需要自己来解决了。

二、准备

1、公网IP(向运营商申请的动态IP)

2、域名(通过阿里云购买的域名)

3、可以运行python程序的服务器(路由器/电脑/树莓派)

4、安装两个Python-SDK库

# 核心库
pip install aliyun-python-sdk-core
# 域名库
pip install aliyun-python-sdk-domain

三、获取 AccessKey

通过阿里云控制台进入RAM访问控制页面新建子用户,获取 AccessKey ID 和 AccessKey Secret

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述

四、实现逻辑

1、获取当前IP

2、存储获取到的IP

3、比对IP(因为阿里云不允许修改相同的解析,所以需要比对IP是否有变化)

4、获取解析记录列表

#!/usr/bin/env python
#coding=utf-8

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest

client = AcsClient('', '', 'cn-hangzhou')

request = DescribeDomainRecordsRequest()
request.set_accept_format('json')

request.set_DomainName("xx.com")

response = client.do_action_with_exception(request)

5、添加解析记录

#!/usr/bin/env python
#coding=utf-8

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest

client = AcsClient('', '', 'cn-hangzhou')

request = AddDomainRecordRequest()
request.set_accept_format('json')

request.set_DomainName("xx.com")
request.set_RR("@")
request.set_Type("A")
request.set_Value("60")

response = client.do_action_with_exception(request)

6、修改解析记录

#!/usr/bin/env python
#coding=utf-8

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest

client = AcsClient('', '', 'cn-hangzhou')

request = UpdateDomainRecordRequest()
request.set_accept_format('json')

request.set_RecordId("xx.com")
request.set_RR("@")
request.set_Type("A")
request.set_Value("60")

response = client.do_action_with_exception(request)

五、源代码

github地址:https://github.com/a-00/AliyunDDNS

DDNS.py

#!/usr/bin/env python
# coding=utf-8

"""
新增域名解析记录,参数说明如下:
:填写自己的accessKey,建议使用RAM角色管理的Key:填写自己的accessSecret,建议使用RAM角色管理的Secret
"""

import os
import time
from aliyunsdkcore.client import AcsClient
from cxxh_function import wirte_to_file
from cxxh_function import add_record
from cxxh_function import update_record
from cxxh_function import Describe_Domain_Records
from cxxh_function import get_internet_ip

while True:
    # 判断存放IP的文件是否存在,不存在则创建
    if os.path.exists("./ip"):
        pass
    else:
        wirte_to_file("./ip", "0.0.0.0")

    client = AcsClient('LTAI4G3PiidWoszTkEpC9DL8', '7Dx8BPqiy0Tyq822mPDMYEKmrT7SOt', 'cn-hangzhou')

    # 通过函数获取外网ip
    ip = get_internet_ip()
    # print(ip)

    # 下面开始对比ip,如果ip与之前记录的ip一致,则不执行任何操作,如果ip有变化,则会更新本地存储文件和更新域名解析
    with open("./ip", 'r') as f:
        old_ip = f.read()
    if ip == old_ip:
        print("本地记录未更新"+"\nnew_ip:"+ip+"\nold_ip:"+old_ip)
    else:
        des_relsult = Describe_Domain_Records(client, "A", "cccc.com")
        # 判断域名解析记录查询结果,TotalCount为0表示不存在这个域名的解析记录,需要新增一个
        if des_relsult["TotalCount"] == 0:
            add_relsult = add_record(client, "5", "600", "A", ip, "@", "cccc.com")
            record_id = add_relsult["RecordId"]
            print("域名解析新增成功!")
            wirte_to_file("./ip", ip)
            print("本地记录已更新"+"\nnew_ip:"+ip+"\nold_ip:"+old_ip)
        # 判断域名解析记录查询结果,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, "@", record_id)
            print("域名解析更新成功!")
            wirte_to_file("./ip", ip)
            print("本地记录已更新"+"\nnew_ip:"+ip+"\nold_ip:"+old_ip)
        else:
            TotalCount = des_relsult["TotalCount"]
            print("存在%d个域名解析记录值,请核查删除后再操作!" % TotalCount)
    time.sleep(120)

cxxh_function.py

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest
from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest
from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest
from aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest import DescribeSubDomainRecordsRequest
import urllib.request
import json

# 写入文件
def wirte_to_file(path, content):
    with open(path, 'w') as f:
        f_name = open(path, 'w')
        f_name.write(content)

# 新增解析记录,返回json格式的数据
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

# 更新解析记录
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

# 获取解析记录列表
def Describe_Domain_Records(client, record_type, domainname):
    request = DescribeDomainRecordsRequest()
    request.set_accept_format('json')

    request.set_Type(record_type)
    request.set_DomainName(domainname)

    response = client.do_action_with_exception(request)
    response = str(response, encoding='utf-8')
    relsult = json.loads(response)
    return relsult

# 获取外网地址
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

# 测试地址
# def get_internet_ip():
#     ip = '1.1.1.1'
#     return ip
这篇关于【script】python 调用阿里云解析 DNS API 实现 DDNS(动态域名解析)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!