|
正文开始
1.准备物理设备
可以是机架式服务器,塔式服务器,工程机,tb的centos小主机甚至你家的电脑等等,如果是搭网站,24小时开机的觉悟一定要有,噪音,电费等事宜自己要解决,不行的话可以去买云服务器了,没必要这么折腾
各位可以看看我的,花了很多钱,(其实还不如去腾讯云秒杀一台服务器)
数数装了几根内存,就装内存的的钱也够买一年服务器了(⊙o⊙) 2.自行申请公网ip
3.安装系统,配置环境
我是觉得,高端的服务器要配置最好用的面板-宝塔(不打广告啊)
4.DDNS配置(请根据自身服务器环境进行配置)
我的服务器使用宝塔面板
首先访问内网宝塔面板,因为现在没有配置公网ip,所以是访问不了的
DDNS服务即为动态解析,在监测到服务器ip变动后能够自动修改域名解析值,保证域名正常访问,免除许多麻烦。
因为我的域名是在阿里云注册的,所以我通过阿里云DNS的API实现自动DDNS
在DNSpod也有类似功能,这里不再过多赘述
(1)阿里云设置域名解析
直接去阿里云的云解析控制台,添加一个域名解析记录,值随便写,便于到时候判断ddns服务是否生效
(2)安装阿里云SDK(Python环境,阿里云也提供了其他语言,可以自行查看官方文档)
回到宝塔,连接ssh,输入以下命令检查系统是否安装了python [root@localhost ~# python#若提示未找到命令,请执行下面这条[root@localhost ~# python3
从这张图可以看到,我的服务器安装了python3.6.8,所以我不用另外安装了
要是两个命令都是报错的话,请自行安装python(可以在宝塔应用商店找到Python项目管理器,里面一键安装)
没有报错的话,我们直接安装阿里的SDK了,依次执行以下命令: - #Python3.0以下版本或pip3.0以下版本请使用以下命令:
- #安装阿里云核心SDK库
- pip install aliyun-python-sdk-core
- #安装阿里云域名SDK库
- pip install aliyun-python-sdk-domain
- #安装阿里云DNS-SDK库
- pip install aliyun-python-sdk-alidns
- #Python3.0及以上版本请使用以下命令:
- #安装阿里云核心SDK库
- pip3 install aliyun-python-sdk-core
- #安装阿里云域名SDK库
- pip3 install aliyun-python-sdk-domain
- #安装阿里云DNS-SDK库
- pip3 install aliyun-python-sdk-alidns
- #没碰过python或者够懒的兄弟直接把上面的都复制下来执行一遍就行了,反正注释会省略的
复制代码
没有报错就差不多了
若是出现以下报错: - =============================DEBUG ASSISTANCE=============================
- If you are seeing a compilation error please try the following steps to
- successfully install cryptography:
- 1) Upgrade to the latest pip and try again. This will fix errors for most
- users. See: https://pip.pypa.io/en/stable/installing/#upgrading-pip
- =============================DEBUG ASSISTANCE=============================
复制代码
请升级pip版本,执行命令:
pip3 install --upgrade pip (3)代码实现与配置
好,这下基本安装完python环境了,来,开始写(抄)DDNS代码:
新建一个空白文件,命名为ddns.py,代码复制起来:
- #!/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 = '你的AccessKey'
- SECRET = '你的Secret'
- # 地区节点 可选地区取决于你的阿里云帐号等级,普通用户只有四个,分别是杭州、上海、深圳、河北,具体参考官网API
- regionId = 'cn-hangzhou'
- # 配置认证信息
- client = AcsClient(ID, SECRET, regionId)
- # 设置主域名
- DomainName = '你的根域名'
- # 子域名列表 列表参数可根据实际需求增加或减少值
- SubDomainList = ['二级域名']
- # 获取外网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('60') # 可选值的范围取决于你的阿里云账户等级,免费版为 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('60')
- 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() + ')')
复制代码
太长了看不过来的话,这里针对个人情况指出需要修改文件几个地方: # AccessKey 和 Secret 建议使用 RAM 子账户的 KEY 和 SECRET 增加安全性 ID = '你的AccessKey' SECRET = '你的Secret' 这些AccessKey和Secret想必各位都能找到ヾ(≧▽≦*)o
为了保证信息安全,建议使用子账户的AccessKey和Secret,并且手动修改子账户的权限
# 设置主域名 DomainName = '你的根域名' # 子域名列表 列表参数可根据实际需求增加或减少值 SubDomainList = ['二级域名'] 那么这个也是需要注意的, DomainName要填你的根域名,例如123.com
那如果我要填a.123.com怎么办? SubDomainList就填你的二级域名,但不要带上你的根域名!譬如a.123.com,你只需要填a就可以了
注意,这个动态DDNS,并不局限于一个子域名,如果你有多个子域名需要使用动态DDNS,例如a.123.com和b.123.com,可以在 SubDomainList 里直接填写a和b,二级域名之间使用逗号隔开
例: # 设置主域名 DomainName = '123.com' # 子域名列表 列表参数可根据实际需求增加或减少值 SubDomainList = ['a,b'] # 这样就是配置了a.123.com和b.123.com使用动态DDNS 还有一个: request.set_TTL('60') # 可选值的范围取决于你的阿里云账户等级,免费版为 600 - 86400 单位为秒 这个就是TTL,开了企业版解析套餐的土豪可以调整一下这个,不用白不用,记录生效也快嘛,60就是一分钟,600就是十分钟,自己调就行了
编辑完之后保存文件,转到ssh,先测试一下api能否正常调用,输入命令: #python3.0(含)以上版本用下面这个 python3 /文件具体路径/ddns.py #python3.0以下版本用下面这个 python /文件具体路径/ddns.py #例 #python3 /www/ddns.py 返回信息若为以下提示,说明配置成功
我们去到阿里云云解析页面,若看到域名记录值发生变化,说明api修改成功,DDNS基本配置完成!
(4)添加定时任务,自动监测公网ip变化
转到宝塔面板-计划任务,添加shell脚本任务:
脚本内容就是刚刚ddns.py的执行命令,例:python3 /www/ddns.py
执行周期按需填写,建议两分钟执行一次,我选择一分钟的监测频率,这样当公网ip变动后,可以缩短宕机恢复时间;
我们也可以同时创建多个计划任务,最大程度监测公网ip变化,保证网站正常运行
任务创建好后要手动执行一下,检查日志,没有报错就可以了
恭喜,你现在完成了万里长征第一步,喜提动态DDNS服务一个!
5.端口转发实现真正意义上的外网访问
单是有公网ip还是不行的,不信?你可以试试用公网ip访问宝塔面板,我敢肯定绝对是访问超时,更别说搭建网站了。
这是因为我们路由器的设置还是对外封锁端口,导致无法访问到我们的服务器。要解决这个问题,我们需要登录路由器管理页面配置端口转发,将外网用户对服务器的请求转发到内网所对应的服务器,这样就可以从外网正常访问我们的服务器了。
废话不多说,先访问服务器的管理页面,大部分的路由器管理页面地址是192.168.0.1或192.168.1.1
输入管理员密码即可成功进入后台,忘记密码请reset路由器配置
(该设置的位置及名称因路由器品牌和型号而异,请加以分辨)
找到转发规则,虚拟服务器,添加端口转发规则
我们直接添加新条目,先尝试转发宝塔面板的入口
注意:服务端口号是可以随意填的,路由器会将服务端口的请求转发到内部端口,外网用户通过公网ip+服务端口即可访问到内部端口,但是像80,443,8080这类端口就没辙
举个例子:宝塔面板默认端口为8888,如果你的服务端口号和内部端口号都是填写8888,那么你直接输入公网ip+8888就能访问宝塔面板。
如果你的服务端口填了1234,那么你输入公网ip+8888会访问超时,只有输入公网ip+1234才会访问到宝塔面板~
(相当于一个奇怪的内网穿透)
ip地址填写宝塔面板内网ip,保存
现在尝试通过公网ip+服务端口访问宝塔面板入口,若能够成功访问,说明配置成功
若是上面的宝塔面板端口转发配置成功,接下来便需要转发网站的端口,让我们搭建的网站可以通过指定的端口被外网访问
登录宝塔面板,创建一个网站,网址最好已经配置DDNS,便于检验端口转发是否成功
创建完成后,点击站点设置,手动添加域名
因为80端口和443端口已经被运营商封锁,我们需要为网站分配其他的端口。如上图,我给我的网站分配了5555端口
实现:添加域名<127.0.0.1:自定义端口>,端口你随便填可以了,11451也可以,就是臭了点
添加完成后,注意要去防火墙放行
然后呢,就去路由器管理页面配置端口转发:
ip地址还是填宝塔面板内网地址即可
然后,我们需要验证一下端口转发是否正常工作:
(1)公网ip+服务端口
(2)已配置DDNS的网址+服务端口(优先验证这个)
像我刚刚使用了5555端口创建网站,我就访问< 公网ip:5555 >或< 已配置DDNS的网址:5555 >检查能否正常从外网访问,用多几个设备检查( •̀ ω •́ )✧
如下图,访问不超时就是成功
至此,端口转发已经配置完成
P.S.我在撰写这篇文章的时候,有一个想法,是否可以将非80和443的服务端口转发到内网的80端口呢?例如,外网访问1111端口,就能直接转发到内网80端口。虽然运营商封了外网的80和443,但是内网没有啊!这样就可以省掉更改网站运行端口这一步骤。但是似乎也有一个bug:如果我运行多个网站呢?全都转发到80端口吗?有待验证,有兴趣的大佬可以尝试一下
6.解决访问网站时域名后面要加端口号的问题
(去掉难看的端口号,艸,这破端口看得人烦)
运营商封掉了美妙的80和443端口,只留下一堆奇奇怪怪的端口,让我们在访问域名的时候都要带上个小尾巴,非常恶心,如果是自己用的网站可以理解,但是,爷靠着他赚钱呢!搜索引擎看见这么奇怪的域名,都懒得来爬,这不玩完了吗?用户本来输了个域名就可以访问的网站,现在偏偏要加个端口,你说烦不烦?再说,中文的:和英文的:(冒号)超级难分,用户手骉怎么办?不用玩了呐!所以,一个合格的站长,不能忍受这种问题的存在,既然已经走到这一步,那就让暴风雨来的更猛烈些吧~
注意:本篇文章将针对已备案的域名,提供解决访问网站时域名后面要加端口号的步骤,若你的域名未备案,请拉到本文末尾,查看另外那篇针对未备案域名提供解决方案的文章,感谢您的支持~
由于我们的域名备案了,此时我们有两个选择:第一个是使用第三方CDN帮助我们实现去掉端口的问题,;第二个就是使用隐性url解析帮我们隐藏掉原来带端口的访问域名
不过在我们开始操作之前,还有一个步骤不能忽略:我们要一个中转的域名
解释一下:由于我们的ip是动态的,同域名解析一样,cdn的回源配置也不可能要我们手动去改回源ip,既然我们有DDNS,那么cdn有没有这样的功能呢?监测ip变动,自动修改回源ip?大厂有没有我不知道,小厂绝对没有。那么这就麻烦了?NONONO,别忘了有些CDN也支持域名回源的!在源服务器和 a.com 之间,我们给他加多一个 b.com ,这个 b.com 的作用就是配合DDNS,如同上面所讲,b.com 只需加一个端口号也能正常访问到网站,不过我们现在的任务是需要去掉域名端口也能正常访问,那么 b.com 承担的就是<工具人>的角色。假设 b.com:1234 能够正常返回原站,那么我们给 a.com 套上cdn,回源目标为 b.com:1234 ,那么只要我们访问a.com,不就能直接访问源服务器嘛?再也不用加端口了!!!
举例来了:我想通过 123.com 访问源站,我们加一个中转域名,假设为 redirect.123.com ,配置好DDNS后, redirect.123.com 加上一个服务端口就能访问源站,然后 123.com 套上cdn,回源为 redirect.123.com:服务端口,这样通过 123.com 就能访问源站了~~~
所以呢,不要用正式域名来配置DDNS,如果你这样做了,换一个域名~~~ 只要原理理解了,配置并不难
腾讯云配置实例
阿里云配置实例
另外说一句,我们可以DDNS和第三方内网穿透共用,使用腾讯云的热备原站回源方法,当一个源站回源失败,就可以通过另外一个源站回源,有备无患。假设DDNS废了,还有第三方的内网穿透撑腰,就没事了
找到合适你CDN,按图配置就行了,然后去云解析DNS解析CDN提供的cname,完美访问!去掉端口这个小尾巴了,看起来真舒服!要是已备案的域名,还可以使用大陆CDN,速度一点也不会差
第二个,就是不推荐使用的隐性url解析方法了:
正如前文所讲:
隐性url的缺点(流量站大忌!) 隐性url有一个很大很大,甚至是致命的问题,首先,隐性url解析是基于iframe实现的,这对搜索引擎的蜘蛛非常不友好,注重seo的兄弟千万不能使用,第二,在浏览器中显示的域名永远都是隐性url记录的解析值,无论你怎么点内部链接,浏览器永远就显示那个域名,用户看了会摸不着头脑。可以这样理解:我建个博客,域名为123.com,使用了隐性url解析,我打开一篇文章,发现url还是原来的123.com,大受震撼。我登陆wordpress后台,url输入123.com/wp-admin,(刻进DNA的链接),发现页面正常跳转,但是浏览器显示的url还是原来的123.com???有用户看到的话,绝对以为闹鬼了。那么蜘蛛要来爬你的站,发现一个域名指向了一堆不同的页面,你让他怎么想?它还会来爬吗?
但是,如果网站是自己用,或者是静态网页,没有那么多子链接,隐性url是非常可取的。我们也不要忘记他的优点:可以直接回源!无需经过第三方CDN分发 我没钱,所以就用阿里云作例子吧:
也是非常简单的,只是域名一定要备案!不然就会这样:
当然你也可以用显性url,你可以理解为301重定向,只不过重定向是在DNS服务器完成的~当然域名会变化~
访问一下我们的网站,完美回源,没有端口!哦耶!家建服务器正式运行!
还是要提醒一下,因为公网ip会变动,例如ssh或者宝塔面板登录需要用到ip,所以就可能要依赖内网穿透实现这些服务了!当然,宝塔面板也可以绑定域名访问的~自己琢磨吧!内网穿透教程拖到下面看~
教程到此结束!感谢你能看到这里,希望本文能够对您有所启发!本来我也想过何必费那么大周折就搞这,还不如买台云服务器省心,应该就是纯粹享受折腾的过程罢了!ヾ(≧▽≦*)o
|