无需花生壳,阿里云解析实现内网穿透

家里闲置着一台老款的Mac mini Server,跑OS X越来越慢,索性装上了Cent OS 7,变成了一台家庭服务器,装上了Plex媒体服务器和Transmission下载服务,同时,也装上了Nginx、Mysql、MongoDB、Redis等,可以调试代码,甚至担当一些小型项目的服务器。

不过,只在家庭内网使用,功能太有限,于是接下来面临的一个问题就是内网穿透。使用过花生壳和花生棒,服务相当不稳定,而且种种受限,每要多加一个端口就要多花钱,安全性也有问题。

其实想想,内网穿透的最大难题无非就是家里是动态公网IP,每变换一次公网IP,需要重新解析一次域名。而阿里云等大型的云服务商,目前都已经实现了域名解析管理的API接口,而且基本都是立即就可生效 。

所以我的思路就是,系统运行一个定期执行的程序,每隔一段时间扫描一下最新的公网IP,如果发现最新的公网IP与域名解析到的IP地址不一致,就通过阿里云API自动更新解析设置即可。这样的花费不过每年一个域名的费用,最贵也就几十块钱。

具体实现步骤如下:

1. 阿里云设置

首先,要确定一个准备用于外网访问的域名,并将此域名转入到阿里云的云解析服务来解析。如图所示,添加需要管理的域名。

无需花生壳,阿里云解析实现内网穿透插图

阿里云云解析服务

转入后,在解析设置中,设置一下A记录解析,解析的IP地址可以填当前的公网IP。如果不知道自己的公网IP,在CentOS系统下,可以输入使用以下命令获取当前的公网IP。

curl ifconfig.me 

获取公网IP后,在阿里云云解析中设置完A记录解析。

无需花生壳,阿里云解析实现内网穿透插图1

设置A记录解析

在阿里云账户管理后台,点击右上角的账户头像,然后点击accesskeys,或者直接登陆https://ak-console.aliyun.com,获取阿里云的AccessKeyIDAccessKeySecret

2. 路由器设置

阿里云的设置完成后,需要对路由器设置端口映射,使外网对公网IP的端口访问能转发到内网服务器的相应端口。绝大部分的路由器都支持端口映射。

常见的服务端口包括,用于WEB访问的80端口、SSH远程管理的22端口、Mysql数据库的3306端口、Transmission下载服务管理的9091端口和Plex媒体服务的32400端口等等。不用花生壳的好处就是没有端口数量限制,想设置多少就可以设置多少。

当然,在设置端口映射之前,应确保服务器的内网IP已经设置为静态IP,而不是DHCP动态获取。

例:对外33898.,映射为本机192.168.0.8的3389端口

无需花生壳,阿里云解析实现内网穿透插图2

3. 服务器设置

服务器端安装好想要使用的各种服务后,别忘了在防火墙中开启相应的端口,在CentOS 7中,防火墙永久开启端口的命令是:

firewall-cmd --add-port=80/tcp --permanent 

开启之后别忘了重新载入防火墙的设置以使其生效,命令如下:

firewall-cmd --reload 

4. 自动更新域名解析程序

准备工作都做好了,接下来就是通过程序检测公网IP,并在公网IP发生变化时,及时更新阿里云的域名解析。

这个程序是用Python写的,先使用Python的包管理工具pip下载安装阿里云的Python SDK。如果没有安装pip,则先安装pip:

yum install pip 

安装好pip后,安装阿里云的Python核心SDK以及云解析SDK:

pip install aliyun-python-sdk-core pip install aliyun-python-sdk-alidns 

导入项目所需要的包,如果缺少则使用pip安装:

import os import json from urllib2 import urlopen from aliyunsdkcore.client import AcsClient from aliyunsdkcore.acs_exception.exceptions import ClientException from aliyunsdkcore.acs_exception.exceptions import ServerException from aliyunsdkalidns.request.v20150109 import DescribeDomainRecordsRequest from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest 

完整代码如下:

#!/usr/bin/env python # coding= utf-8 import os import json from urllib2 import urlopen from aliyunsdkcore.client import AcsClient from aliyunsdkcore.acs_exception.exceptions import ClientException from aliyunsdkcore.acs_exception.exceptions import ServerException from aliyunsdkalidns.request.v20150109 import DescribeDomainRecordsRequest from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest class DnsHandler: # 从阿里云开发者后台获取Access_Key_Id和Access_Key_Secret access_key_id = "" access_key_secret = "" # 填入自己的域名 domain_name = "" # 填入二级域名的RR值 rr_keyword = "" # 解析记录类型,一般为A记录 record_type = "A" # 用于储存解析记录的文件名 file_name = ".ip_addr" client = None record = None current_ip = '' # 初始化,获取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): if os.path.isfile(self.file_name) : file_handler = open(self.file_name, 'r') r = file_handler.read() file_handler.close() else : 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) file_handler = open(self.file_name, 'w') file_handler.write(r) file_handler.close() 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('http://jsonip.com'))['ip'] # 实例化类并启动更新程序 dns = DnsHandler() dns.reset() 

将以上代码保存为dns.py文件,并赋予执行权限:

chmod +x dns.py 

5. 设置定时运行

CentOS内置有强大的计划任务工具Crontab,如果系统里没有则先使用yum安装:

yum install crontabs 

首先,设置执行用户的环境变量,比如,我们使用root用户来执行这一程序,则先在用户目录下建立.profile文件,或者在已有的.profile文件下加入如下一行,以使得可以使用VI来编辑cron文件:

EDITOR=vi; export EDITOR 

建立mycron文件,加入如下内容:

*/10 * * * * /root/ddns/dns.py 

这意味着每10分钟执行一次任务,即扫描公网IP,若与阿里云解析不一致,则修改阿里云解析。

然后,提交crontab任务:

crontab mycron 

好了,大功告成,接下来,程序会每隔10分钟自动扫描公网IP,然后自动更新阿里云的解析,速度、稳定性和安全性都远胜于第三方的DDNS服务。

原文链接

ius 地址: https://www.jianshu.com/p/291a3a5283ac

原文链接:https://blog.csdn.net/qq_20349639/article/details/114113931?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168476299816800180693790%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=168476299816800180693790&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-14-114113931-null-null.blog_rank_default&utm_term=NAS%E3%80%81%E7%BE%A4%E6%99%96%E3%80%81%E9%98%BF%E9%87%8C%E4%BA%91%E3%80%81%E5%9F%9F%E5%90%8D%E8%A7%A3%E6%9E%90%E3%80%81%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F%E3%80%81ipv6%E3%80%81ddns%E3%80%81%E8%BD%BB%E9%87%8F%E7%BA%A7%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E3%80%81%E9%93%81%E5%A8%81%E9%A9%AC%E3%80%81%E5%A8%81%E8%81%94%E9%80%9A%E3%80%81DSM%E3%80%81DSM6.0%E3%80%81%E7%BE%A4%E6%99%96nas%E3%80%81%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E3%80%81%E8%9C%97%E7%89%9B%E6%98%9F%E9%99%85%E3%80%81%E9%BB%91%E7%BE%A4%E6%99%96%E3%80%81docker%E3%80%81%E5%AE%B9%E5%99%A8%E9%95%9C%E5%83%8F%E3%80%81%E5%9F%9F%E5%90%8D%E6%B3%A8%E5%86%8C%E3%80%81%E5%AE%9D%E5%A1%94%E3%80%81%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E3%80%81nginx%E3%80%81frp%E3%80%81%E5%8A%A8%E6%80%81%E5%9F%9F%E5%90%8D%E8%A7%A3%E6%9E%90

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享