美文网首页
使用python实现阿里云动态域名解析DDNS

使用python实现阿里云动态域名解析DDNS

作者: windy1001 | 来源:发表于2019-05-15 19:30 被阅读0次

    前言

    前置条件

    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","www.huangwx.cn")
            #判断子域名解析记录查询结果,TotalCount为0表示不存在这个子域名的解析记录,需要新增一个
            if des_relsult["TotalCount"] == 0:
                add_relsult = add_record(client,"5","600","A",ip,"www","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","www.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,"www","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

    阿里云时间

    1.2000代金券,长期有效:2000
    2.高性能拼着买,2折起:高性能ECS
    3.个人博客:薇小站

    相关文章

      网友评论

          本文标题:使用python实现阿里云动态域名解析DDNS

          本文链接:https://www.haomeiwen.com/subject/ddbmaqtx.html