大家好,又见面了,我是你们的朋友全栈君。
目录
什么时候使用DDNS?
一句话:只有在你的服务器被分配动态ipv4公网或私网ip的时候才考虑使用DDNS。
为什么会是动态?怎么出现这种情况的?
据估算,大陆一共有2-4亿个公网ip1,显然不够用,其中中国电信的公网ip最多2。
很显然ip不够用,于是运营商采取NAT技术,打个比方,一个小区或者一个信号塔使用公网ip,小区内或信号塔范围内的设备在局域网中上网的方式。这样就大大节约公网ip资源。
但是你在家里搭建的网址、NAS等服务别人访问不到的。电信和联通有时在ip宽裕的情况下会就近给一些宽带用户账号分配公网ipv4,且每天变化一次。所以北上广深的宽带用户大概率是有动态ip的,没有就打电话。
免费获得动态公网ip的唯一方式:
- 购买电信或联通宽带,价格在1000元以上/年的百兆以上宽带,因为高速宽带为了保证稳定性,运营商会给你的宽带直接使用动态公网ip,这样省去你做第2步。
- 拨打电信10000或联通10010客服,让客服和技术师傅给你的宽带转成动态公网ip,这个请求合理合法,如果对方拒绝,可向工信部投诉。此时你的光猫分配了公网ip,但是这个ip每天一变。(固定的公网ip只有企业和政府单位才能申请,且价格至少25000元一年,根据网速上不封顶。)
- 再次拨打10000或10010,询问自己宽带的账号和密码。
- 登录到光猫后台网址,一般是192.168.1.1 ,将网络连接方式从路由模式改成桥接模式。这样做是让光猫的动态公网ipv4直接交给路由器。设置完后你的光猫就不负责宽带账号登录了,它只负责网络传输。(踩坑:刚开始电信给我装的光猫是SDN,这种光猫是进不了后台的,家里是这种光猫的赶快淘宝上买了一个华为的光猫换上,这样就能进后台改桥接了。)
- 用网线将路由器接到光猫上,此时路由器将获得动态公网ip(因为桥接),进入路由器后台网站,将你的宽带账号和密码填进去,并登录。即采用路由器拨号上网。
- 服务器连接路由器,将你的服务器内网ip填写在路由器的DMZ主机上,这样服务器就暴露到公网,别人通过你的公网ip能访问到服务器。
以上步骤完成后,你的服务器可以直接通过公网ip访问了,但是ip每天变化。为了解决这个问题,请跟我一起做DDNS。
DDNS其实是服务器上跑一个脚本,这个脚本时时获取当前服务器的公网ip地址,然后自动登录DNS服务商并将当前ip解析到你的域名上。这样无论何时何地,通过访问域名就能访问服务器,时刻保持域名=ip。本次教程采用阿里云域名和DNS域名解析。其他厂商例如腾讯云、百度云、花生壳等自行摸索吧。
阿里云官网购买域名
注册阿里云账号,登录,进入控制台,点击域名进行购买,购买时会提示你登记身份信息。我的5年129元,不贵吧。不要买.com,.cn等等重要域名,因为非常贵。
服务器pip安装阿里云python-ddns库
因为有的人机器上同时有python 2 和python 3 ,如果用pip安装就不起作用,所以以下六条命令都要执行一下,以防万一。
pip install aliyun-python-sdk-core
pip install aliyun-python-sdk-domain
pip install aliyun-python-sdk-alidns
pip3 install aliyun-python-sdk-core
pip3 install aliyun-python-sdk-domain
pip3 install aliyun-python-sdk-alidns
获取AccessKey
鼠标移到阿里云账号头像上,点击AccessKey,点击获取即可,最好下载csv保存,防止忘了。csv文件是可以用office或wps打开的。
复制DDNS代码
在自己的用户家目录下创建一个DDNS.py的文件,将下方代码粘贴到空文件中。最好将文件设置777权限。
cd ~
touch DDNS.py
chmod 777 DDNS.py
你需要配置ID、SECRET、regionID、DomainName、SubDomainList五个变量。
ID、SECRET就是你刚生成的AccessKey 的ID 和 Secret。
regionID默认就行了,可以不改
DomainName写入你的二级域名。比如我购买了8zi.site,这就是二级域名,在代码里写 “8zi.site” 。
SubDomainList子域名就是的网址的前缀,一般是www,你也可以写成任意你喜欢的。
下方的脚本是使用python3执行的,如果你的服务器上python命令能启动python3,那么请将第一行的python3改成python
#!/usr/bin/env python3
#coding=utf-8
# 加载核心SDK
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
# 加载获取 、 新增、 更新、 删除接口
from aliyunsdkalidns.request.v20150109 import DescribeSubDomainRecordsRequest, AddDomainRecordRequest, UpdateDomainRecordRequest, DeleteDomainRecordRequest
# 加载内置模块
import json,urllib
# AccessKey 和 Secret 建议使用 RAM 子账户的 KEY 和 SECRET 增加安全性
ID = 'xxxxxxx'
SECRET = 'xxxxxx'
# 地区节点 可选地区取决于你的阿里云帐号等级,普通用户只有四个,分别是杭州、上海、深圳、河北,具体参考官网API
regionId = 'cn-hangzhou'
# 配置认证信息
client = AcsClient(ID, SECRET, regionId)
# 设置主域名
DomainName = 'example.com'
# 子域名列表 列表参数可根据实际需求增加或减少值
SubDomainList = ['www','a']
# 获取外网IP 三个地址返回的ip地址格式各不相同,3322 的是最纯净的格式, 备选1为 json格式 备选2 为curl方式获取 两个备选地址都需要对获取值作进一步处理才能使用
def getIp():
# 备选地址: 1, http://pv.sohu.com/cityjson?ie=utf-8 2,curl -L tool.lu/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 getDomainInfo(SubDomain):
request = DescribeSubDomainRecordsRequest.DescribeSubDomainRecordsRequest()
request.set_accept_format('json')
# 设置要查询的记录类型为 A记录 官网支持A / CNAME / MX / AAAA / TXT / NS / SRV / CAA / URL隐性(显性)转发 如果有需要可将该值配置为参数传入
request.set_Type("A")
# 指定查记的域名 格式为 'test.example.com'
request.set_SubDomain(SubDomain)
response = client.do_action_with_exception(request)
response = str(response, encoding='utf-8')
# 将获取到的记录转换成json对象并返回
return json.loads(response)
# 新增记录 (默认都设置为A记录,通过配置set_Type可设置为其他记录)
def addDomainRecord(client,value,rr,domainname):
request = AddDomainRecordRequest.AddDomainRecordRequest()
request.set_accept_format('json')
# request.set_Priority('1') # MX 记录时的必选参数
request.set_TTL('600') # 可选值的范围取决于你的阿里云账户等级,免费版为 600 - 86400 单位为秒
request.set_Value(value) # 新增的 ip 地址
request.set_Type('A') # 记录类型
request.set_RR(rr) # 子域名名称
request.set_DomainName(domainname) #主域名
# 获取记录信息,返回信息中包含 TotalCount 字段,表示获取到的记录条数 0 表示没有记录, 其他数字为多少表示有多少条相同记录,正常有记录的值应该为1,如果值大于1则应该检查是不是重复添加了相同的记录
response = client.do_action_with_exception(request)
response = str(response, encoding='utf-8')
relsult = json.loads(response)
return relsult
# 更新记录
def updateDomainRecord(client,value,rr,record_id):
request = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
request.set_accept_format('json')
# request.set_Priority('1')
request.set_TTL('600')
request.set_Value(value) # 新的ip地址
request.set_Type('A')
request.set_RR(rr)
request.set_RecordId(record_id) # 更新记录需要指定 record_id ,该字段为记录的唯一标识,可以在获取方法的返回信息中得到该字段的值
response = client.do_action_with_exception(request)
response = str(response, encoding='utf-8')
return response
# 删除记录
def delDomainRecord(client,subdomain):
info = getDomainInfo(subdomain)
if info['TotalCount'] == 0:
print('没有相关的记录信息,删除失败!')
elif info["TotalCount"] == 1:
print('准备删除记录')
request = DeleteDomainRecordRequest.DeleteDomainRecordRequest()
request.set_accept_format('json')
record_id = info["DomainRecords"]["Record"][0]["RecordId"]
request.set_RecordId(record_id) # 删除记录需要指定 record_id ,该字段为记录的唯一标识,可以在获取方法的返回信息中得到该字段的值
result = client.do_action_with_exception(request)
print('删除成功,返回信息:')
print(result)
else:
# 正常不应该有多条相同的记录,如果存在这种情况,应该手动去网站检查核实是否有操作失误
print("存在多个相同子域名解析记录值,请核查后再操作!")
# 有记录则更新,没有记录则新增
def setDomainRecord(client,value,rr,domainname):
info = getDomainInfo(rr + '.' + domainname)
if info['TotalCount'] == 0:
print('准备添加新记录')
add_result = addDomainRecord(client,value,rr,domainname)
print(add_result)
elif info["TotalCount"] == 1:
print('准备更新已有记录')
record_id = info["DomainRecords"]["Record"][0]["RecordId"]
cur_ip = getIp()
old_ip = info["DomainRecords"]["Record"][0]["Value"]
if cur_ip == old_ip:
print ("新ip与原ip相同,无法更新!")
else:
update_result = updateDomainRecord(client,value,rr,record_id)
print('更新成功,返回信息:')
print(update_result)
else:
# 正常不应该有多条相同的记录,如果存在这种情况,应该手动去网站检查核实是否有操作失误
print("存在多个相同子域名解析记录值,请核查删除后再操作!")
IP = getIp()
# 循环子域名列表进行批量操作
for x in SubDomainList:
setDomainRecord(client,IP,x,DomainName)
# 删除记录测试
# delDomainRecord(client,'b.jsoner.com')
# 新增或更新记录测试
# setDomainRecord(client,'192.168.3.222','a',DomainName)
# 获取记录测试
# print (getDomainInfo(DomainName, 'y'))
# 批量获取记录测试
# for x in SubDomainList:
# print (getDomainInfo(DomainName, x))
# 获取外网ip地址测试
# print ('(' + getIp() + ')')
创建定时任务
创建定时任务前先试运行你的脚本。只要不报错,说明能运行。
chmod 777 DDNS.py
/home/Andy/DDNS.py # 这里写你自己的脚本绝对路径试试
因为代码里子域名我放了一个www一个a,因此在阿里云官网上域名——解析中能看到两条记录。子域名想要多少自己在代码列表里加就行了,要多少有多少。
你的DDNS脚本好了,但是需要定时执行
执行下方crontab命令,注意脚本路径必须写成绝对路径。
crontab -e
# 按一下i进入编辑模式
*/10 * * * * /home/Andy/DDNS.py
# 上面的意思是分,时,日,月,星期 脚本路径,这里设置每隔10分钟更新ip
# 按esc退回命令行模式,再:wq末行模式保存退出
验证DDNS是否成功
比如我的域名是www.8zi.site,试试能不能ping通
ping www.8zi.site
试着用ssh工具登录服务器,能显示解析结果:
当然了当前这个180的公网ip是电信动态分给我的,过了一天就变成其他的了,所以这才需要DDNS。
成功啦,哈哈哈哈,觉得有帮助记得点赞。
想要每秒30M网速的500G网盘的小伙伴加我qq : 2290906844 。 免费体验7天哈,发个福利。 我的私人网盘什么都能放哦,某mp4也行哦。
附录1:如何解析固定公网ip
百度搜索ip,得到你的机器的公网ip
阿里云网址上解析域名,添加记录值,修改主机记录和记录值。
记录类型就是你想怎么解析,点击下拉框查看,不做解释,选择A。
主机记录是一级域名,你可以写任意字符串,比如www ,hello等等。
记录值就是你的ipv4。
其他默认。
附录2:路由器DDNS
有的路由器自带DDNS功能,比如我用的华为路由器,DDNS服务商是Oray,就是花生壳的公司(贝锐科技),在花生壳上5块钱买个域名,把域名用户名密码填进去,再做好DMZ就可以了,方便快捷。
附录3:目前公网ip情况
当你部署服务器搭建网站或者在家建NAS,要能让别人访问你的服务,就必须拥有公网ip。全球的任意一台设备都能访问公网ip上的任意服务,你的公网ip服务器也能访问世界上的任何服务,除非服务方设置了防火墙,这就是优势。
举个例子,在中国你是访问不了谷歌的,因为早年谷歌地图事件,中国设立了墙,屏蔽了谷歌的所有服务,你试试你能登上谷歌搜索官网吗??但是你可以购买一台美国的AWS云服务器轻松解决。
你的电脑—-连接美国的一台公网ipv4的windows系统—-访问谷歌。而且美国人有30亿个ip,价格也便宜。国内有很多人在香港部署服务器做这种跳墙服务,并且这种服务不违法。
公网ip分ipv4和ipv6两种。公网ipv4的格式是类似39.103.144.114这样的四段数字,每段从0到255,所以公网ip的ipv4全球一共只有256的4次方,即4,294,967,297个。显然全球七十亿人口加上企业政府等单位需要,不能人手一个。并且42亿个公网ip中,有超过16亿个在美国人手中。
ipv6的地址虽然有很多,甚至是“地球上每一粒沙子都能分配到一个ipv6”,但是ipv6在国内普及率超过10%3,现有的设备、技术还是依据ipv4研发的,更新换代困难,时间长,并且耗资巨大。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/139633.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...