动态公网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地址][1]
下载下来按照教程配置好并且install就可以使用了
Linux/Unix
而我找了许久,都没有一个合我心意的在linux/unix平台使用的工具
于是我在看了上面gitee的代码后,自己用Python写了个供linux/unix平台使用的ddns工具,搭配linux/unix的cron使用相得益彰。
[gitee地址][2]
使用前先看清楚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)