序
为什么需要通过外网访问
- 异地联调时接口的实时更新,双方远程联调时不需要再将服务部署到服务器上更新
- 减少域名认证、IP认证、回调地址问题,如使用企业微信、微信支付的接口时,需要填写回调地址,传统开发模式限定了开发只能部署到线上测试,而拥有外网服务后,可以在本地实时调试更改接口
- 本地服务器的实现,不再需要高昂的成本购买云服务器搭建建设性服务(如GIT、SonarQube等),只要本地运行任意一台,就是一台完整的服务器
实现外网访问有哪几种方式?
- 公网IP + DDNS
- FRP等内网穿透转发服务
公网IP
预备知识点
公网IP知识点
- 互联网是一个联通全球各地的广域网,而这里的广域网也是我们所称的公网
- 只有有了公网的接入我们才能访问互联网,也就是我们俗称的接入宽带
- 每一条公网接入必定伴随着一个公网IP
- 拨号的主体一般是公网IP的承接点,以前是电脑拨号,几年前是路由器拨号,现在由光猫拨号
- 光猫分为拨号模式和桥接模式,拨号模式下,光猫拨号完成后实现主路由功能,桥接模式下,光猫只负责转发不负责拨号,由下级路由器拨号
- 光猫除了有很多运营商的配置和光纤信号的转码功能外,也拥有路由器的功能
- 由于公网IP的稀缺,移动服务商的网络一般是一个大的局域网,多个用户共用一个公网IP;电信和联通一般默认一户一公网IP
- 除了专线外,个人和企业的的公网IP并不是一成不变的,一般是拨号时随机分配
- 除了专线外,个人和企业的的公网IP不开放80端口
公网IP的限制
通过以上内容可以简单得到公网IP的几项限制
- 公网IP的承接点是拨号端,而现在默认由光猫拨号,光猫的管理端普通用户无法登录
- 公网IP的承接点是拨号端,我们怎么让我们局域网内的服务运行在拨号端
- 移动宽带是没有公网IP的
- 公网IP会随着拨号,或网络的波动而变化
- 公网IP无法访问80端口
需要公网IP访问的前提
- 不能是移动宽带
- 必须让宽带安装人员设置光猫为桥接模式,由路由器拨号
- 需要解决IP变动问题
- 需要解决如何将路由器端口转发到局域网主机端口问题
解决方案
解决IP变化问题:DDNS
何为DDNS
DDNS是指动态域名服务,DDNS负责实时更新DNS服务器上域名和用户IP的对应关系。
DDNS会每隔几分钟检查主机的IP地址,若IP变更则向DNS服务器发送更新IP地址请求。
DDNS如何实现
以阿里云为例,需要开通阿里云的AccessKey,以调用阿里云的API实时更新DNS
代码如下:
#!/bin/sh
aliddns_name="nas"
aliddns_domain="51zidan.com"
aliddns_ak="LTAI**********RQ4DGdP"
aliddns_sk="4N1A**********3Gl3hA"
aliddns_curl="curl -s whatismyip.akamai.com"
aliddns_dns="8.8.8.8"
aliddns_ttl="600"
ip=`$aliddns_curl 2>&1`
current_ip=`nslookup $aliddns_name.$aliddns_domain $aliddns_dns 2>&1`
if [ "$?" -eq "0" ]
then
current_ip=`echo "$current_ip" | grep 'Address 1' | tail -n1 | awk '{print $NF}'`
if [ "$ip" = "$current_ip" ]
then
exit 0
fi
fi
timestamp=`date -u "+%Y-%m-%dT%H%%3A%M%%3A%SZ"`
urlencode() {
# urlencode <string>
out=""
while read -n1 c
do
case $c in
[a-zA-Z0-9._-]) out="$out$c" ;;
*) out="$out`printf '%%%02X' "'$c"`" ;;
esac
done
echo -n $out
}
enc() {
echo -n "$1" | urlencode
}
send_request() {
local args="AccessKeyId=$aliddns_ak&Action=$1&Format=json&$2&Version=2015-01-09"
local hash=$(echo -n "GET&%2F&$(enc "$args")" | openssl dgst -sha1 -hmac "$aliddns_sk&" -binary | openssl base64)
curl -s "http://alidns.aliyuncs.com/?$args&Signature=$(enc "$hash")"
}
get_recordid() {
grep -Eo '"RecordId":"[0-9]+"' | cut -d':' -f2 | tr -d '"'
}
query_recordid() {
send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$aliddns_name.$aliddns_domain&Timestamp=$timestamp"
}
update_record() {
send_request "UpdateDomainRecord" "RR=$aliddns_name&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$aliddns_ttl&Timestamp=$timestamp&Type=A&Value=$ip"
}
add_record() {
send_request "AddDomainRecord&DomainName=$aliddns_domain" "RR=$aliddns_name&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$aliddns_ttl&Timestamp=$timestamp&Type=A&Value=$ip"
}
if [ "$aliddns_record_id" = "" ]
then
aliddns_record_id=`query_recordid | get_recordid`
fi
if [ "$aliddns_record_id" = "" ]
then
aliddns_record_id=`add_record | get_recordid`
echo "added record $aliddns_record_id"
else
update_record $aliddns_record_id
echo "updated record $aliddns_record_id"
fi
主要包含几点
- 通过
<code>curl -s whatismyip.akamai.com
获取当前主机的公网ip - 与当前DNS的IP比对,若改变则请求阿里云服务更新
- 设置脚本定时运行
解决端口访问问题:端口转发
需要在路由器配置 打开UPNP或者手动配置端口转发
UPNP是被动式端口转发服务,需要端口服务的提供者主动向UPNP服务请求
手动配置端口转发,只需要更新IP和端口号就行
FRP等内网穿透转发服务(以FRP为例)
与公网IP对比优点
- 对公网IP无要求,移动宽带也能用,不需要端口转发更不用DDNS
- 支持80端口
- 搭建简单,没有弯弯绕绕的网络只是,只需要远程转发浏览即可
与公网IP对比缺点
- 需要一台拥有公网IP的服务器做转发(任意一台服务器,如阿里云VPS)
- 访问速度不仅受限于当前网络的速度,也要受限于服务器的速度。(一般家庭500M的宽带有50M的下载、5M的下载上传,但若服务器只有2M,那么速度将仅限于2M)
- 中间的转发让延迟更高,速度更慢
frp服务搭建
http://blog.mokevip.top/2020/06/29/1minute-frp/
其他的内网穿透方法
- 向日葵服务,优点是不需要太多专业知识,不需要服务器做转发,缺点是只能用向日葵的域名,带宽贵、自定义域名贵
- nps服务,更稳定,支持多用户,但缺少强制https功能(可以自己实现
结语
以上内容都是凭本人的知识点和平时的使用总结而来,若有不对的地方,敬请更正。
原创不易,感谢支持。