基于阿里云API实现DDNS内网穿透功能
硬件拓扑场景
实现前提
- 具备阿里云注册的域名
- 内网运营商给你的对外IP是公网(动态的)
网络结构调整
获取超级管理账户
由于光猫本身的路由功能有限,建议使用路由器的拨号上网功能,光猫使用桥接模式。
在修改光猫的WAN模式前,需要获取光猫的超级管理员账号,可以咨询客服获取,或者参考如下方法自行获取(适用于天翼2.0的网关猫 型号是烽火HG2201T):
假设管理地址是 192.168.1.1 (光猫铭牌上有)
- 普通用户登录后台 光猫铭牌上有普通用户账号信息
- 登录后访问 http://192.168.1.1:8080/cgi-bin/baseinfoSet.cgi
获取如下信息:
超密一般就是telecomadmin+八位数字,所以后面8组数字就代表8为数字 从48到57就是0到9。因此只需要解析后面八组数字就可以拿到管理密码
修改光猫的宽带设置
超级管理账户登录光猫后台,选择网络宽带配置,修改前确保你已截图备份路由模式下的配置,并知晓宽带账号级密码
备份工作后,修改连接模式为桥接,保存即可
为防止与之前的配置冲突,建议修改DHCP配置,选择用户侧管理-IPv4设置,将IP地址修改为与之前不一样的,注意同步修改DHCP网段
使用路由器进行拨号上网
确保路由器已经连接光猫,连接路由器的无线,登录后台,此处使用的路由器为华为AX3
如下图配置即可,宽带账号修改为自己的
配置后保存,正常即可连上网络
配置DMZ主机暴露自己的内网服务器
也可以使用NAT服务配置端口映射实现单端口的外网访问
至此你可以使用你的动态公网IP访问到你的内网服务器了
内网服务器配置(树莓派4B为例)
配置服务器静态IP
vi /etc/dhcpcd.conf
# 使用 vi 编辑文件,增加下列配置项
# 指定接口 eth0 (无线连接则是wlan0)
interface eth0
# 指定静态IP,/24表示子网掩码为 255.255.255.0
static ip_address=192.168.3.11/24
# 路由器/网关IP地址
static routers=192.168.3.1
# 手动自定义DNS服务器
static domain_name_servers=114.114.114.114 8.8.8.8 223.5.5.5 223.6.6.6 192.168.3.1
# 修改完成后,按esc键后输入 :wq 保存。重启树莓派就生效了
sudo reboot
配置阿里云域名解析记录
Python调用阿里云SDK更新解析记录
首先,要确定一个准备用于外网访问的域名,并将此域名转入到阿里云的云解析服务来解析。如图所示,添加需要管理的域名。
转入后,在解析设置中,设置一下A记录解析,解析的IP地址可以填当前的公网IP。如果不知道自己的公网IP,在CentOS系统下,可以输入使用以下命令获取当前的公网IP。
脚本原理
- 获取主机的外网IP
- 调用接口获取域名解析配置并比对当前外网IP与域名解析配置中的IP是否一致
- IP不一致则调用域名解析配置更新接口更新为当前的公网IP,否则不操作
- 使用Linux定时任务每天执行一次(可根据实际情况调整频率)
安装依赖
sudo apt-get install python3-pip
sudo apt-get install build-essential libssl-dev libffi-dev python3-dev
pip3 install aliyun-python-sdk-core -i http://mirrors.aliyun.com/pypi/simple
pip3 install aliyun-python-sdk-alidns -i http://mirrors.aliyun.com/pypi/simple
脚本
/root/ddns/aliyunApiForDDNS.py 内容如下:
#!/usr/bin/env python3
# coding=utf-8
import json
from urllib.request import urlopen
from aliyunsdkalidns.request.v20150109 import DescribeDomainRecordsRequest
from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest
from aliyunsdkcore.client import AcsClient
class DnsHandler:
# 从阿里云开发者后台获取Access_Key_Id和Access_Key_Secret
access_key_id = '你自己的key'
access_key_secret = '你自己的secret'
region_id = 'cn-hangzhou'
# 域名
domain_name = "mikuai.tech"
# 填入二级域名的RR值
rr_keyword = "www"
# 解析记录类型,一般为A记录
record_type = "A"
# 用于储存解析记录的文件名
file_name = ".ip_addr"
client = None
record = None
current_ip = '117.83.29.186'
# 初始化,获取client实例
def __init__(self):
self.client = AcsClient(
self.access_key_id,
self.access_key_secret,
self.region_id
)
self.record = self.get_record()
self.current_ip = self.get_current_ip()
# 如果公网IP发生变化,则自动修改阿里云解析记录
def reset(self):
if self.current_ip != self.get_record_value():
print(self.update_record(self.current_ip))
self.get_record()
# 获取阿里云域名解析完整记录
def get_record(self):
"""
未做记录为空判断,要求阿里云域名对应记录存在
:return: 域名记录字典
"""
request = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest()
request.set_PageSize(10)
request.set_action_name("DescribeDomainRecords")
request.set_DomainName(self.domain_name)
request.set_RRKeyWord(self.rr_keyword)
request.set_TypeKeyWord(self.record_type)
r = self.client.do_action_with_exception(request)
return json.loads(r)
# 获取阿里云域名解析记录ID
def get_record_id(self):
return self.record["DomainRecords"]["Record"][0]["RecordId"]
# 获取当前域名解析记录
def get_record_value(self):
return self.record["DomainRecords"]["Record"][0]["Value"]
# 修改阿里云解析记录
def update_record(self, value):
request = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
request.set_action_name("UpdateDomainRecord")
request.set_RecordId(self.get_record_id())
request.set_Type(self.record_type)
request.set_RR(self.rr_keyword)
request.set_Value(value)
return self.client.do_action_with_exception(request)
# 获取当前公网IP
def get_current_ip(self):
return json.load(urlopen('https://ipv4.jsonip.com/'))['ip']
# 实例化类并启动更新程序
dns = DnsHandler()
dns.reset()
设置定时任务
sudo -s
crontab -e
# 添加如下配置
00 03 * * * /usr/bin/python3 /root/ddns/aliyunApiForDDNS.py
# 重启服务
systemctl restart cron
测试
# 树莓派安装nginx
sudo apt-get install nginx
# 启动nginx
systemctl start nginx
# 修改默认访问端口为8888
sudo nano /etc/nginx/sites-available/default
# 重启nginx
systemctl restart nginx
访问你的域名+端口8888
结果如下即成功: