记录一次家庭内网使用DDNS让外网访问, 同时动态更新域名
相信很多同学在自己家里学习啥的搞些小网站小程序, 比如部署一些 个人多媒体
、 个人网盘
、 个人博客
等的网站, 但是在公司时想访问记录或查询一些资料, 但是又因为访问不了家庭网络而烦躁...
在此分享能使用任意外网访问家庭内网, 同时动态更新域名的方法.
当然在此之前我使用过花生壳、公云等一些软件, 他也可以让你从外网访问家庭内网, 但是别的不说, 他限速而且收费呀... 自己搭建可以全速使用家里的带宽
步骤如下:
一. 外网访问
1. 申请公网IP
想访问家庭网络必定需要找家里开网络的运营商, 让他们给开公网IP
, 我家里使用的是电信宽带,电话直接打 10000 号人工服务让他们帮忙开通
, 理由嘛很简单( 找个借口说家里安装监控就给你开了 ) , 电信现在默认都是给的私网IP.
2. 光猫改为桥接模式
申请完公网IP先别急着挂, 还需要让他们把宽带网络改成桥接模式
, 后面我们路由器使用拨号上网
3. 查询宽带账号和密码
由于路由器现在是使用拨号上网, 所以还需要找他运营商拿到宽带的账户和密码
, 这些都是必要条件
4. 设备网线连接
我们使用网线连接 光猫的网口 和 路由器WAN口, 电脑主机的网线则联通路由器的LAN口, ( WAN口是连接外部网络, LAN口是连接内部网络, 家里的电脑网线都可以用LAN接口连接, 并且此时我们电脑是没有网络的 )
光猫网口 --> 路由器WAN口
路由器LAN口 --> 电脑网口
5. 设置路由器
此时已经具备的条件:
公网ip, 宽带改为桥接模式, 宽带账号和密码, 设备网线正确连接
- 开始设置路由器:
我的路由器设备使用的小米路由器, 暂以小米路由器为例
, 路由器网关是 192.168.31.1 , 自己的路由器网关自己搜一下, 然后输入路由器用户名密码- 上网设置
如图, 上网方式选择PPPOE手动拨号
, 然后输入宽带的账号和密码即可
拨号成功应该就可以上网了~~~
6. 检查IP地址
百度查询自己本机的IP是否与路由器拨号成功获得的IP地址相同.如果不同, 那一般都是私网ip 没有申请公网ip的.
7. 路由转发
一般路由器都拥有路由转发功能, 可以自己配置转发规则.
- 端口转发: 映射端口, 访问外网 ip:端口, 会直接映射到内网的ip:端口
如: 访问外网地址 22.135.173.55:8848, 会被转发到内网 192.168.31.26:8000
8. 测试
- 我本地电脑随便开启一个服务
部署成功, 内网ip:port 192.168.31.26:8401- 接着使用外网ip访问, 注意自己映射的端口哦
访问成功~~
二. 设置动态更新域名
由于电信给的公网IP是动态IP, 每次关闭重启光猫都会更换公网IP地址, 所以这也是个很头疼的事情...
小编提供个人解决方案:
1. 准备域名 ( 本方案只支持腾讯云域名, 对接腾讯云API )
我使用的方法, 使用Python写了一个脚本, 动态去更新域名, 需要准备一个腾讯云的域名。
提供购买链接https://buy.cloud.tencent.com/domain?from=console
2. 开通腾讯云 API 密钥
API 密钥代表你的账号身份和所拥有的权限,使用腾讯云 API 可以操作您名下的所有腾讯云资源。给上链接 https://console.cloud.tencent.com/cam/capi
- 开通完后新建密钥( 单机即可, 自动创建 ):
3. 安装Python3
由于使用的 Python 写的脚本, 需要环境拥有Python, 版本 3 及以上.
安装方法参考 https://www.cnblogs.com/weven/p/7252917.html
安装完成后查看Python版本:
4. 献上脚本
- 复制以下代码 保存为 xxx.py 格式就行
VERSION = 1
from hashlib import sha1
import json
import time
import base64
import hmac
class DDnsHelper():
def __init__(self, mid=0, params={}):
pass
def excute(self):
import requests
SecretId = '*需要填写*'
SecretKey = '*需要填写*'
runningPause = 20
domainName = 'xxxx.com' # *需要填写你自己的域名*
ddnsDomains = [
{
# *需要填写你自己的域名*
'name': '@.xxxx.com',
'value': '', #
'always': False,
# DNS生存时间
'ttl': 600,
# 主机记录, 即域名前缀
'subDomain': '@',
'recordId': '',
# 记录类型
'recordType': 'A',
# 线路类型, 指定细分解析线路
'recordLine': '默认',
'description': '本地提供api服务的地址',
# 查看本地IP地址的接口, 这是自己写的接口, 仅仅返回一个纯粹的本地外网IP地址
'localDomain': 'https://www.hosix.cn/ip',
'localValue': ''
}
]
class tenXunDDNS_Helper():
def __init__(self):
self.running = True
self.action = ""
self.secretId = SecretId
self.nonce = 38651
self.region = 'ap-guangzhou'
self.secretKey = SecretKey
self.version = '2017-03-12'
self.domain = domainName
self.url = 'cns.api.qcloud.com/v2/index.php'
self.httpType = 'https://'
self.endpoint = self.httpType + self.url
self.ddnsDomain = ddnsDomains
self.runningPause = runningPause
self.remoteRecords = []
def getServerIp(self):
timeStamp = int(time.time())
params = {}
params['Action'] = 'RecordList'
params['domain'] = self.domain
params['Nonce'] = self.nonce
params['SecretId'] = self.secretId
params['Timestamp'] = timeStamp
s = self.get_string_to_sign("GET", self.url, params)
Signature = self.sign_str(self.secretKey, s, sha1)
params['Signature'] = Signature
response = requests.get(self.endpoint, params=params)
result = json.loads(response.text)
if int(result['code']) != 0:
raise Exception('获取域名失败' + ':' + str(result['code']) + ':' + result['message'])
data = result['data']
self.remoteRecords = data['records']
# print(self.remoteRecords)
def postServerIp(self, domain):
timeStamp = int(time.time())
params = {}
params['Action'] = 'RecordCreate'
params['domain'] = self.domain
params['Nonce'] = self.nonce
params['SecretId'] = self.secretId
params['Timestamp'] = timeStamp
params['subDomain'] = domain['subDomain']
params['recordType'] = domain['recordType']
params['recordLine'] = domain['recordLine']
params['value'] = domain['value']
params['ttl'] = domain['ttl']
s = self.get_string_to_sign("GET", self.url, params)
Signature = self.sign_str(self.secretKey, s, sha1)
params['Signature'] = Signature
response = requests.get(self.endpoint, params=params)
result = json.loads(response.text)
if int(result['code']) != 0:
raise Exception('添加域名失败' + ':' + str(result['code']) + ':' + result['message'])
data = result['data']
print('添加域名成功ip:%s,本地ip:%s,域名:%s' % (domain['value'], domain['localValue'], domain['name']))
def updateServerIp(self, domain):
timeStamp = int(time.time())
params = {}
params['Action'] = 'RecordModify'
params['domain'] = self.domain
params['Nonce'] = self.nonce
params['SecretId'] = self.secretId
params['Timestamp'] = timeStamp
params['subDomain'] = domain['subDomain']
params['recordId'] = domain['recordId']
params['recordType'] = domain['recordType']
params['recordLine'] = domain['recordLine']
params['value'] = domain['localValue']
params['ttl'] = domain['ttl']
s = self.get_string_to_sign("GET", self.url, params)
Signature = self.sign_str(self.secretKey, s, sha1)
params['Signature'] = Signature
response = requests.get(self.endpoint, params=params)
result = json.loads(response.text)
if int(result['code']) != 0:
raise Exception('更新域名失败' + ':' + str(result['code']) + ':' + result['message'])
data = result['data']
print('更新域名成功源ip:%s,本地ip:%s,域名:%s' % (domain['value'], domain['localValue'], domain['name']))
def deleteServerIp(self):
pass
def getLocalDomain(self, domain):
res = requests.get(domain['localDomain'])
ip = res.content.decode("utf-8").strip()
return ip
def clearDnsRecord(self):
for domain in self.ddnsDomain:
if not domain['always']:
domain['value'] = ''
domain['localValue'] = ''
def run(self):
self.getServerIp()
for domain in self.ddnsDomain:
if (not domain['always']):
# 获取本地ip
try:
domain['localValue'] = self.getLocalDomain(domain)
except Exception as e:
print("获取本地ip失败 不更新:%s,本地ip:%s,域名:%s" % (
domain['value'], domain['localValue'], domain['name']))
else:
continue
flag = False
for remoteDomain in self.remoteRecords:
if (domain['subDomain'] == remoteDomain['name']):
domain['recordId'] = remoteDomain['id']
domain['value'] = remoteDomain['value']
flag = True
break
if flag:
if (domain['value'] == domain['localValue']):
pass
# print("无需更新ip:%s,本地ip:%s,域名:%s" % (domain['value'],domain['localValue'],domain['name']))
else:
self.updateServerIp(domain)
continue
else:
domain['value'] = domain['localValue']
self.postServerIp(domain)
self.clearDnsRecord()
def start(self):
start_time = int(time.time())
while self.running:
next_time = int(time.time()) + self.runningPause
if (next_time - start_time) > self.runningPause:
try:
self.run()
except Exception as e:
print(e.__str__())
start_time = start_time + self.runningPause
else:
time.sleep(self.runningPause / 10)
def get_string_to_sign(self, method, endpoint, params):
s = method + endpoint + "?"
query_str = "&".join("%s=%s" % (k, params[k]) for k in sorted(params))
# print(s + query_str)
return s + query_str
def sign_str(self, key, s, method):
hmac_str = hmac.new(key.encode("utf8"), s.encode("utf8"), method).digest()
return base64.b64encode(hmac_str)
t1 = tenXunDDNS_Helper()
t1.start()
d = DDnsHelper()
d.excute()
- 最后双击运行~ OK
5. 运行原理和注意事项
- -原理:
该脚本是通过定时查询公网IP接口: https://www.hosix.cn/ip , 然后调用腾讯云API去动态更新域名. 非常简单.....
- 注意事项:
1.该脚本需要持续运行
, 如果是Linux系统, 直接挂后台运行即可, 该脚本资源消耗不高
2.如果提示没安装requests
模块, 打开cmd窗口
输入:pip install requests
3.如运行闪退, 请检查域名等是否正确填写
如有问题请评论或留言: 544010165@qq.com
3 条评论
有用, 家里千兆网快的飞起, 赞一个 ::tieba:Y.tb10::
优秀
66666