动态公网ip配合阿里云的ddns

引缀

前不久,我把自己家用电脑穿透出nat让我能在公司进行远程控制。

从映射到DDNS

可是用作穿透的中转服务器是一台共享百兆带宽的服务器,再考虑网络折损什么的,感觉不划算。于是就想着怎么去搞一个公网ip映射好了。可是想了下,映射也仅仅是单机,而我还想做一台家用的linux服务器,该怎么办呢。所以映射是行不通的,而且我家用的是移动宽带。人家也不是自己的技术构建的带宽,而是购买的,所以想给一个ipv4的公网Ip可谓是难如登天吧。

先说回映射,前面说映射单机,而我想多机,该怎么办呢。这样就引申到以前的一个技术--DDNS

DDNS是什么技术呢

DDNS全称Dynamic Domain Name Server,寓意即是动态域名服务。 作用是将用户的动态IP地址映射到一个固定的域名解析服务上,这样我们即可以使用域名去访问不停变换的公网ip地址了。至于为什么要动态,而不是静态,咱也不知道,咱也不敢问啊(ps:据传是因为商业服务原因)

好了,现在我们知道可以用这个技术映射多个地址了。因为一个顶级域名可以分出无数的次级域名。

但问题也来了,我们说到移动公司是不会给你ipv4的公网ip的。

从ipv4到ipv6

首先,大家都注意到了,我这里用了ipv4来形容公网ip。那大家说既然有ipv4是不是还有ipv5,ipv6,ipv7啊。

哎嘿,大家还真的猜对了,其实我们常用ipv4的下一代IP协议就是ipv6。(至于为啥没5,大家可以自行去了解,不是什么秘闻)

为什么ipv4不能,ipv6就能给一个公网地址呢。这就要讲到ipv6的由来了

IPv4迄今为止已经使用了30多年。最早期的时候,互联网只是设计给美国军方用的,根本没有考虑到它会变得如此庞大,成为全球网络。 尤其是进入21世纪后,随着计算机和智能手机的迅速普及,互联网开始指数爆发性发展,越来越多的上网设备出现,越来越多的人开始连接互联网。这就意味着,需要越来越多的IP地址。 根据互联网数据研究机构的统计,全世界 76 亿人口,网民总数已经超过了 40 亿(2018年1月)。而IPv4池一共才2的32次方,也就是约42.9亿个IP地址。早在前几年就宣告ipv4的地址池枯竭。 其实地址不够的问题,并不是这几年才发现的。早在1990年,IETF(互联网工程任务小组,成立于1985年底,是全球互联网最具权威的技术标准化组织)就开始规划IPv4的下一代协议。他们还建立了IPng(下一代IP),拉了一帮人,专门推进相关工作。 1994年,各IPng的代表们于多伦多举办的IETF会议中,正式提议IPv6发展计划。 该提议直到同年的11月17日才被认可,并于1996年8月10日成为IETF的草案标准。 1998年12月,IPv6被IETF正式推出,也就是互联网标准规范RFC2460。

只是升级能有什么提升呢,可能大家都会这么说。诚然就如前面所说的IPv4的地址池是约42.9亿,IPv6能达到多少呢? 340282366920938463463374607431768211456个 简单说,是2的128次方。是的ipv4仅仅只有2的32次方。毫不夸张的说就算一个人百台千台设备也足够使用

因为刚巧发现我公司是有ipv6的,我家的宽带也是被我打开了ipv6的。于是乎计上心头我就打算用ipv6做ddns映射。

window

但是我这个人是比较懒的,所以我就先上各大git平台找有没有这样的工具

还真让我找到一个,在window上运行的。

gitee地址

下载下来按照教程配置好并且install就可以使用了

Linux/Unix

而我找了许久,都没有一个合我心意的在linux/unix平台使用的工具

于是我在看了上面gitee的代码后,自己用Python写了个供linux/unix平台使用的ddns工具,搭配linux/unix的cron使用相得益彰。

gitee地址

使用前先看清楚readme的教程哦!!哦macos也能使用哦,毕竟macos也是基于unix的嘛。啾咪

代码如下:

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest import DescribeSubDomainRecordsRequest
from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest
import requests
import json
import configparser
import os

'''配置文件'''
conf = configparser.ConfigParser()
root_path = os.path.dirname(os.path.abspath(__file__))

'''读取配置文件'''
def readConf(group,key):
    #配置文件路徑
    conf.read(root_path + '/app.conf')
    # print(conf)
    data = conf.get(group, key)
    if(key == 'SLD'):
        #SLD是數組配置
        data = eval(data)

    return data

'''連接阿里雲'''
client = AcsClient(readConf('aliyun','accessKeyId'), readConf('aliyun','accessSecret'), 'cn-hangzhou')

'''獲取當前ip地址'''
def getIp(type):
    session = requests.Session()
    session.trust_env = False
    if (type == 'v4'):
        response = session.get('https://v4.ident.me/').text
    else:
        response = session.get('https://v6.ident.me/').text
    print("获取到IP地址:%s" % response)
    return response

'''修改域名ddns的方法'''
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)

'''添加新的ddns的方法'''
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)

'''獲取域名ddns的記錄'''
def getList(DomainName,RR):
    request = DescribeSubDomainRecordsRequest()
    request.set_accept_format('json')
    request.set_DomainName(DomainName)
    request.set_SubDomain(RR + '.' + DomainName)
    response = client.do_action_with_exception(request)
    # domain_list = json.loads(response)
    return response;

'''ipv4-ddns的主函數'''
def ipv4Main():
    DomainName = readConf('aliyun', 'domain')
    SLD = readConf('ipv4','SLD')
    ipv4 = getIp('v4')
    for once in SLD:
        domain_list = json.loads(getList(DomainName,once))
        if domain_list['TotalCount'] == 0:
            add(DomainName, once, "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'], once, "A", ipv4)
                print("修改域名解析成功")
            else:
                print("IPv4地址沒有改變")
        else:
            print('IPv4未知錯誤')

'''ipv6-ddns的主函數'''
def ipv6Main():
    DomainName = readConf('aliyun', 'domain')
    SLD = readConf('ipv6', 'SLD')
    ipv6 = getIp('v6')
    for once in SLD:
        domain_list = json.loads(getList(DomainName, once))
        if domain_list['TotalCount'] == 0:
            add(DomainName, once, "AAAA", ipv6)
            print("新建域名解析成功")
        elif domain_list['TotalCount'] == 1:
            if domain_list['DomainRecords']['Record'][0]['Value'].strip() != ipv6.strip():
                update(domain_list['DomainRecords']['Record'][0]['RecordId'], once, "AAAA", ipv6)
                print("修改域名解析成功")
            else:
                print("IPv6地址沒有改變")
        else:
            print('IPv6未知錯誤')

if __name__ == '__main__':
    ipv6Flag = readConf('ipv6','flag')
    ipv4Flag = readConf('ipv4','flag')

    try:
        if (ipv4Flag == 'true'):
            ipv4Main()

        if (ipv6Flag == 'true'):
            ipv6Main()
    except Exception as r:
        print('獲取IP未知错误 %s' % (r))
        os._exit(0)

----------end

本文为ctexthuang原创文章,转载请注明来自ctexthuang_blog

Edit with Markdown
召唤看板娘