情景说明
前段时间应公司需求, 需要将内网的服务映射到公网. 由于公司使用的是类似家庭宽带的线路, 没有固定的公网 IP 地址, 所以决定使用域名来完成.
当时有几种方案:
1, 花生壳: 但是目前需要乱七八糟的认证备案, 舍弃!
2,NAT123: 花里胡哨的, 感觉像垃圾软件, 也舍弃!
3,holer:GITHUB 上面的一个项目, 但是我们只能安装 Client 端, Server 端在别人手里, 不安全, 舍弃!
...
还有其它的乱七八糟的很多, 但是都觉得要么是 C/S 架构, 麻烦. 要么就是使用别人的, 定制要么收费, 要么不安全, 也都放弃了, 最后决定参考网上的 Python 调用阿里云 API 通过 Linux 定时任务来更新解析!
网络拓扑
简单的网络拓扑如下图:
说明:
1, 电信 ASDL 拨号, 会有一个会变化的公网 IP 地址, 我们的域名就是要解析到最新的该 IP 地址上面
2, 公司内网是一个路由器接交换机的方式, 路由器比较 Low,H3C 的, 简单的进行一个端口转发到指定的服务器 192.168.1.100
3,192.168.1.100 上面安装 Nginx, 做反向代理, 同时也作为统一的管理入口, 方便管理, 同时也做定时更新 DNS 解析的任务
准备工作
首先, 我们需要去阿里云创建一个 Accesskey , 这个东西将作为我们登录阿里云更新解析的用户, 具体创建方法可以参考百度, 创建完成后记得保留好生成的 Key 和 Secret:
注意: 创建的 AccessKey 用户一定要记得授权 DNS 管理 的权限, 否则无法更新!
其次, 我们需要有一个已经备案完成的域名, 如 abc.com!
最后, 有一台内网的 Linux 机器, 个人推荐 CentOS, 几年运维下来, 几乎用的都是这个, 不为别的, 就为了比较好管理.
服务配置
[1] CentOS 服务器安装 Python: 默认情况下, CentOS 是拥有 Python 的, 一般都是 2.6 或者 2.7, 但是不一定有 pip, 我们需要安装 pip, 这里采用的 epel 源:
- yum -y install epel-release
- yum -y install python-pip
[2] 安装依赖的阿里云 Python 包: 前者是阿里云需要的包, 后者是模拟请求需要的包
- pip install aliyun-python-sdk-alidns
- pip install requests
[3] 编辑更新脚本 ddns_update.py, 内容如下:
备注: 脚本参考网上的老哥的分享, 然后自己做了一些修改
注意: 这里解析有一个前提条件, 就是你需要修改的那条解析规则必须已经存在, 该脚本不能新增, 只能修改旧的
- #coding:utf-8
- from aliyunsdkcore import client
- from aliyunsdkalidns.request.v20150109 import DescribeDomainsRequest,DescribeDomainRecordsRequest,UpdateDomainRecordRequest
- import json,urllib,re
- ######################################################################################
- # 个人配置区域
- #####################################################################################
- # 创建的 AccessKey
- ID="xxxxx"
- Secret="xxxxx"
- # 默认
- RegionId="cn-hangzhou"
- # 你的域名
- DomainName="abc.com"
- # 你想解析的二级域名, 是一个列表, 可以写多个
- HostNameList = ['test','hello', 'world']
- # 默认
- Types = "A"
- clt = client.AcsClient(ID,Secret,RegionId)
- ######################################################################################
- # 动态获取当前公司对外的公网 IP
- def GetLocalIP():
- IPInfo = urllib.urlopen("http://ip.chinaz.com/getip.aspx").read()
- IP = re.findall(r"ip:'(.*?)',", IPInfo)[0]
- return IP
- # 更新域名 IP
- def EditDomainRecord(HostName, RecordId, Types, IP):
- UpdateDomainRecord = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
- UpdateDomainRecord.set_accept_format('json')
- UpdateDomainRecord.set_RecordId(RecordId)
- UpdateDomainRecord.set_RR(HostName)
- UpdateDomainRecord.set_Type(Types)
- UpdateDomainRecord.set_TTL('600')
- UpdateDomainRecord.set_Value(IP)
- UpdateDomainRecordJson = json.loads(clt.do_action_with_exception(UpdateDomainRecord))
- print UpdateDomainRecordJson
- # 获取域名信息
- def GetAllDomainRecords(DomainName, Types, IP):
- DomainRecords = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest()
- DomainRecords.set_accept_format('json')
- DomainRecords.set_DomainName(DomainName)
- DomainRecordsJson = json.loads(clt.do_action_with_exception(DomainRecords))
- print DomainRecordsJson['DomainRecords']['Record']
- for HostName in HostNameList:
- for x in DomainRecordsJson['DomainRecords']['Record']:
- RR = x['RR']
- Type = x['Type']
- if RR == HostName and Type == Types:
- RecordId = x['RecordId']
- print RecordId
- EditDomainRecord(HostName, RecordId, Types, IP)
- IP = GetLocalIP()
- GetAllDomainRecords(DomainName, Types, IP)
[4] 添加定时任务: 每两小时更新一次
- # 授执行权限
- chmod 755 /scripts/ddns_update.py
- # 添加定时任务
- echo "* */2 * * */usr/bin/python /scripts/ddns_update.py">> /var/spool/cron/root
[5] 配置完成, 此时你可以手动执行检验该脚本是否能够正常的修改域名解析! 至于后面的 Nginx 反向代理, 网上的方法很多, 这里就不一一缀诉!
其它
这里感谢提供这个脚本的大神, 但是我写这个的时候已经离找到这个脚本有一段时间了, 所以就无法具体到哪位, 有些遗憾!
来源: https://www.cnblogs.com/Dy1an/p/9229074.html