⽬录
⼀、前⾔
阅读本⽂前需要先搞懂NAT、PAT、端⼝映射⼏个概念,前⾯我有写了⼀篇关于这⼏个概念的博⽂。根据之前的博⽂我们已经知道,内⽹宽带中的主机可以访问公⽹宽带主机,反之不可以访问;公⽹宽带主机可以和公⽹宽带主机双向访问;内⽹宽带中的主机和内⽹宽带中的主机互相⽆法访问。那么内⽹宽带中的客户机和公⽹宽带中的客户机如何访问另⼀个内⽹宽带中的服务器呢?这⾥就需要⽤到内⽹穿透技术。
⼆、应⽤场景
家⾥或公司是运营商内⽹ipv4宽带或公⽹IP在防⽕墙后,且需要在外访问家⾥或公司的电脑、NAS、树莓派、摄像头等⽹络设备或远程控制等情况下。
三、详细原理
3.1 传统内⽹穿透(服务器中转数据穿透)原理
对于在NAT之后的服务器来说,其不是不能主动访问公⽹端⼝,⽽是不能反过来有效的被公⽹访问。所以可以在中间架设⼀个公⽹服务器,让在NAT之后的服务器持续主动访问这个拥有公⽹IP地址的服务器,,这样内⽹服务器就成功与公⽹中转服务器建⽴了⼀个连接通道。然后当有任何其他NAT后的客户端主动连接公⽹中转服务器时,公⽹服务器接收到连接请求之后马上把这连接请求通过先前建⽴好的隧道转发到内⽹服务器,内⽹服务器将响应数据包再原路转发回去,最终到达公⽹中转服务器,然后返回给其他NAT后的客户端。
3.2 点对点穿透原理
在内⽹穿透传输⼤量数据时如果都经过服务器中转的话,这样会对服务器端带宽压⼒⽐较⼤。只要是数据量很⼤,⽽⼀般利⽤中转服务器⼜需要⼀定规模投⼊的应⽤,我们都可以考虑⽤P2P技术。
1.UDP打洞技术
最为常见的实现P2P的⽅式是采⽤UDP打洞技术,UDP打洞技术是通过中间服务器的协助在各⾃的NAT⽹关上建⽴相关的表项,使P2P连接的双⽅发送的报⽂能够直接穿透对⽅的NAT⽹关,从⽽实现P2P客户端互连。如果两台位于NAT设备后⾯的P2P客户端希望在⾃⼰的NAT⽹关上打个洞,那么他们需要⼀个协助者——集中服务器,并且还需要⼀种⽤于打洞的Session建⽴机制。Session建⽴机制:
假定客户端A要发起对客户端B的直接连接,具体的“打洞”过程如下:
(1)A最初不知道如何向客户端B发起连接,于是A向集中服务器(本质上是⼀台被设置在公⽹上的服务器,建⽴P2P的双⽅都可以直接访问到这台服务器。位于NAT⽹关后⾯的客户端A和B都可以与⼀台已知的集中服务器建⽴连接,并通过这台集中服务器了解对⽅的信息并中转各⾃的信息)发送消息,请求集中服务器帮助建⽴与客户端B的UDP连接。
(2)集中服务器将含有B的外⽹和内⽹的地址⼆元组发给A,同时,集中服务器将包含有A的外⽹和内⽹的地址⼆元组信息的消息也发给B。这样⼀来, A与B就都知道对⽅外⽹和内⽹的地址⼆元组信息了。
(3)当A收到由集中服务器发来的包含B的外⽹和内⽹的地址⼆元组信息后,A开始向B的地址⼆元组发送UDP数据包,并且A会⾃动锁定第⼀个给出响应的B的地址⼆元组。同理,当B收到由集中服务器发来的A的外⽹和内⽹地址⼆元组信息后,也会开始向A的外⽹和内⽹的地址⼆元组发送UDP数据包,并且⾃动锁定第⼀个得到A回应的地址⼆元组。⼀旦A与B都向对⽅的NAT设备在外⽹上的地址⼆元组发送了数据包,就打开了A与B之间的“洞”,A与B向对⽅的外⽹地址发送数据,等效为向对⽅的客户端直接发送UDP数据包了。⼀旦应⽤程序确认已经可以通过往对⽅的外⽹地址发送数据包的⽅式让数据包到达NAT后⾯的⽬的应⽤程序,程序会⾃动停⽌继续发送⽤于“打洞”的数据包,转⽽开始真正的P2P数据传输。
当然,UDP转换协议提供的“洞”不是绝对可靠的,多数NAT设备内部都有⼀个UDP转换的空闲状态计时器,如果在⼀段时间内没有UDP数据通信,NAT设备会关掉由“打洞”过程打出来的“洞”。如果P2P应⽤程序希望“洞”的存活时间不受NAT⽹关的限制,就最好在穿越NAT以后设定⼀个穿越的有效期。2.TCP打洞技术
从现在的主流应⽤的⾓度上来看,基于TCP的P2P应⽤显然不如基于UDP的应⽤那么⼴泛,但是也存在打洞的需求。TCP相对于UDP⽽⾔要复杂的多,TCP连接的建⽴要依赖于三次握⼿的交互,所以NAT⽹关在处理TCP连接的时候,需要更多的开销。但是,由于TCP协议完备的状态机机制,TCP反⽽⽐UDP更能精确的获取某个Session的⽣命期。⼀种新的代理类型 XTCP 能解决这个问题,实现⽅式可以是采⽤搭建FRP服务器的⽅式,在传输数据的两端都部署上FRP客户端⽤于建⽴直接的连接。
3.3 延伸⼀个内⽹渗透知识
为了安全起见,通常会在⽹络中加⼊防⽕墙,防⽕墙有⼊站规则和出站规则。如果不是⾮常严格的安全管控,通常是不会设置出站规则的,但是⼊站规则⼀般都会设置的,⽐如说外部可以通过80端⼝传⼊内⽹的WEB服务器访问⽹页,但是不能通过3389端⼝登陆内⽹的远程桌⾯。⽽在内⽹渗透的过程中碰到这种情况,我们也可以借助上⾯内⽹传统的⽅式实现穿透防⽕墙的⼊站规则。因为防⽕墙通常只拦截了⼊站,没有拦截出站,那么我们可以让内⽹服务器主动出站(主动连接到⿊客的服务器),与⿊客⾃⼰的服务器打通隧道,最终绕过防⽕墙连上3389远程桌⾯。
还有⼀种情况就是我们已经拿下了内⽹其中⼀台并没有做任何防⽕墙规则的⽩名单服务器,但是我们想连上内⽹另⼀台做了⼊站规则的⽬标服务器,那么我们可以让这台⽩名单服务器作为⼀个跳板,让他先监听⾃⾝任意⼀个端⼝,然后在有任何⽤户连上这个端⼝之后,⽩名单服务器就主动连上内⽹的⽬标服务器,然后借助这台⽩名单服务器打通⿊客和⽬标服务器的连接隧道。⽽在⿊客⼯具中⼤名⿍⿍的lcx原理也就是如此,前者的实现是lcx的listen和slave命令,后者的实现是lcx的tran命令。
3.4 穿透原理总结
内⽹穿透传统⽅式会出现服务器和客户机之间的数据传输全部经过中转服务器,传输速度将受制于中转服务器的上下⾏带宽,不过稳定性很好,对于⾃⼰要购置的云主机要求就是⼤带宽,⼀般这种云主机按流量计费,传输的数据量越⼤价格⾃然越贵。所以点对点穿透便能解决流量带来的困扰,点对点可以实现服务器和客户机之间打洞直接进⾏数据通信,这种⽅式⼀般⽤于udp协议的传输,⽐如应⽤于远程NAS看视频听歌,但这种⽅式需要服务器和客户机都安装穿透⼯具,对⽤户访问端来说不够⽅便,⽽且这种⽅式受复杂⽹络环境影响较⼤,不能100%实现,稳定性⽋缺。
四、⽅法实现
4.1 ⼏款主流⼯具实现
1.frp(开源):
FRP使⽤ Go 语⾔开发,可以⽀持 Windows、Linux、macOS、ARM 等多平台部署。frp内⽹穿透⽆需多复杂的配置就可以达到⽐较好的穿透效果,具有较强的扩展性,⽀持tcp, udp, http, https协议,并且 web 服务⽀持根据域名进⾏路由转发。此外,FRP 提供了⼀种新的代理类型 XTCP ,可以在传输⼤量数据时让流量不经过服务器中转,⽤于实现点对点穿透,当然,此功能并不能保证在你的⽹络环境 100% 可⽤,成功率较低,⽽且还要求访问端也得运⾏ FRP 客户端 (⽬前⼿机端ios没有frp客户端软件)。由于实现条件较多,所以有⽂件传输需求的朋友但必须⽤frp的朋友还是建议买带宽稍⼤⼀点的 VPS 会⽐较省⼼。frp适合有linux基础的个⼈,且需要⾃购⼀个云主机做中转,企业追求稳定可以考虑其他⽅式。
2.ngrok(开源):
ngrok是⼀个反向代理,通过在公共的端点和本地运⾏的Web服务器之间建⽴⼀个安全的通道。ngrok可捕获和分析所有通道上的流量,便于后期分析与响应。主要⽤途是给⽹站或者安装开发提供部署环境,但是也同样可以⽤来进⾏端⼝转发。ngrok适合有linux基础的个⼈,和frp类似,但⽐frp配置稍复杂,且需要⾃购⼀个云主机做中转,企业追求稳定可以考虑其他⽅式。
3.zerotier(开源/商业):
ZeroTier官⽅解释为将整个世界转变为单个数据中⼼或云区域,将所有设备,虚拟机和应⽤程序联接起来,就像在同⼀个交换机接⼊所有设备⼀样。zerotier类似VPN,为内⽹服务器所在NAT⽹络和客户机所在NAT⽹络各虚拟出⼀个VLAN,这样俩个VLAN就可以通过ZeroTier建⽴连接,在通过UDP打洞技术就可以实现内⽹服务器和内⽹客户机直接交互数据。⽬前ZeroTier提供的点对点穿透技术成功率还是⽐较⾼的,可以应付⼤多数⽹络,国内长城宽带⽆法点对点穿透。⽽zerotier因为是国外的项⽬,官⽅提供的中转服务器在国外,国内连接延迟⾼甚⾄连不上,所以官⽅给出了moons概念,可以⾃⼰搭建中转服务器。另外ZeroTier ⽀持 Windows、macOS、Linux 三⼤主流平台,iOS、Android 两⼤移动平台,以及 QNAP(威连通)、Synology(群晖)、WesternDigital MyCloud NAS(西部数据)三个 NAS 平台,还⽀持 LEDE 开源路由器项⽬,⽀持客户端真的很多。zerotier适合有linux基础的个⼈,⼀般⽤于NAS,为了稳定性需要⾃购⼀个云主机做中转,服务器和客户机都需要安装zerotier,企业追求稳定可以考虑其他⽅式。
4.花⽣壳(商业):
花⽣壳既是内⽹穿透软件、端⼝映射软件。功能⽐较齐全,⽐较简单,也是⼤家⽐较⽿熟了,⽀持tcp,udp.https.http,socket5应⽤。流量还是得⾛传说中的rootnode,所以是限流1G,分的等级⽐较多商业版、旗舰版、铂⾦版,需要根据不同需求付费开通相关功能。安装使⽤门槛低,⽆需⾃购云主机做中转,企业商⽤追求稳定可以选择花⽣壳付费版本。
5.Nat123(商业):
nat123是内⽹端⼝映射与动态域名解析(DDNS)软件,在内⽹启动映射后,可在外⽹访问连接内⽹⽹站等应⽤。安装使⽤门槛低,⽆需⾃购云主机做中转,企业商⽤追求稳定可以选择此⽅式付费版。
6.NATAPP(商业):
natapp是基于ngrok的国内收费内⽹穿透⼯具,类似花⽣壳,有免费版本,⽐花⽣壳好。免费版本:提供http,https,tcp全隧道穿透,随机域名/TCP端⼝,不定时强制更换域名/端⼝,⾃定义本地端⼝。安装使⽤门槛低,⽆需⾃购云主机做中转,企业商⽤追求稳定可以选择此⽅式付费版。
7.向⽇葵、teamviewer、anydesk(远程桌⾯):
这三款⽐较特殊,都是⽤来远程桌⾯使⽤,原理就是基于点对点穿透+传统穿透,三款软件都有免费版本,经本⼈长期⼯作使⽤发现,teamviewer免费版稳定性和连通性可以说是最好的,但“怀疑商业⽤途”不时弹出加上近年来爆出的漏洞,⽽anydesk使⽤过程中会经常断连,所以现在很多国内⽤户都转⽤了免费版的向⽇葵,本⼈使⽤中发现移动⽹络环境下使⽤向⽇葵很卡。
8.VPN(加密穿透):
原理类似zerotier,利⽤组建虚拟⽹络,局域⽹VLAN通信的⽅式,不同的是不打洞,流量均⾛中间服务器,内⽹服务端和客户端均需要安装vpn软件,但是它⼤量使⽤了OpenSSL加密库中的
SSLv3/TLSv1协议函数库,数据通信全程加密,⾮常适⽤于企业内⽹资料供员⼯在外⽹访问,⼀般使⽤开源的openvpn,因相关规定这⾥就不做过多描述和搭建介绍了。对了,VPN还有个作⽤就是⽤来正向代理,游戏加速器就是基于VPN正向代理原理,有兴趣的童鞋可以⾃⾏查找相关资料,⽽正向代理典型的⼯具是S..,不能说了,再说下去这篇博⽂就要被删了...
4.2 ⽅法实现总结
商业付费版暂不具体阐述,只能说花钱的就是好,有专业团队维护,且使⽤简单⽅便,但要注意由于数据包会流经第三⽅,因此对数据安全也是⼀⼤隐患。那么对于个⼈有动⼿能⼒的⽤户或者中⼩型企业⼩规模使⽤可以选择开源⽅式,综合软件配置复杂度、穿透能⼒等因素,个⼈觉得⽬前最好的选择就是frp⽤于对流量转发不⼤的场景,⽽需要⼤量udp传输的场景选择zerotier。
五、案例配置
经过前⾯的介绍,相信⼤家对内⽹穿透的⼏个实现⽅法有了⼤概的了解,那么接下来就针对frp和zerotier分别做下安装配置的讲解。
5.1 frp安装配置
1)中转服务器frps安装配置:
FRP 安装⾮常容易,只需下载对应系统平台的软件包并解压就可⽤了。这⾥以centos7系统为例:安装脚本:
#!/bin/bash
#0.33.0是frp的版本号 (截稿为⽌最新版本)export FRP_VERSION=0.33.0sudo mkdir -p /etc/frpcd /etc/frp
sudo wget \"https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_amd64.tar.gz\"sudo tar xzvf frp_${FRP_VERSION}_linux_amd64.tar.gzsudo mv frp_${FRP_VERSION}_linux_amd64/* /etc/frp
如上在/etc/frp⽬录下关注4个⽂件,分别是frpc、frpc.ini和frps、frps.ini,前者两个⽂件是客户端所关注⽂件,后者两个⽂件是服务端所关注两个⽂件。这⾥配置服务端(公⽹服务器),⾸先删掉frpc、frpc.ini两个⽂件,然后再进⾏配置,vi ./frps.ini,FRP 默认提供了2个服务端配置⽂件,⼀个是简化版的frps.ini,包含了基础配置,另⼀个是完整版的frps_full.ini,包含了frp其他功能配置,这⾥不做详细介绍,感兴趣的⼩伙伴可以⾃⾏去查看,初学者只需⽤简版配置即可,在简版 frps.ini 配置⽂件⾥,默认设置了监听端⼝为 7000,你可以按需修改它。来看看简化版的:
> $ vi frps.ini[common]
bind_port = 7000 #隧道端⼝,默认配置中监听的是 7000 端⼝,可根据⾃⼰实际情况修改。subdomain_host = frp.abc.top #配置中转服务器域名绑定,可选配置,如果域名多可以设置⼀个authentication_method = token #启⽤token验证,frpc也需要加此参数token = changeit #token密码
vhost_http_port = 80 #内⽹服务器http映射的端⼝,内⽹可以有多个⽹站使⽤这个端⼝vhost_https_port = 443 #内⽹服务器https映射的端⼝,内⽹可以有多个⽹站使⽤这个端⼝
dashboard_port = 7500 #配置Dashboard监控frp状态的端⼝,后⾯可以直接访问http://frp.abc.top:7500/或http://中转服务器公⽹IP:7500/dashboard_user = admin #监控访问账户dashboard_pwd = admin #监控访问密码
前台启动frps
./frps -c ./frps.ini
配置⾃动启动:⾸先
sudo vi /lib/systemd/system/frps.service
在frps.service⾥写⼊以下内容
[Unit]
Description=fraps service
After=network.target network-online.target syslog.targetWants=network.target network-online.target[Service]Type=simple
#启动服务的命令(此处写你的frps的实际安装⽬录)ExecStart=/etc/frp/frps -c /etc/frp/frps.ini[Install]
WantedBy=multi-user.target
这时候就可以⽤centos7的systemctl命令了,设置开机启动
sudo systemctl enable frps
请⼀定要记住,你需要将服务器的系统防⽕⼟啬,以及阿⾥云、腾讯云后台⾥找到“安全组策略”的相关配置,设置 7000 7500或你修改过的对应端⼝的「允许⼊站和出站」,否则会⼀直连接不上的哦这个切记!!
如服务器使⽤ Win 系统,假设解压到 c:\\frp ⽂件夹,那么只需这样启动:
c:\\frp\\frps.exe -c c:\\frp\\frps.ini
这⾥可以为frp添加进程守护,防⽌访问因意外导致frp进程终⽌,我们写个脚本来监控frp运⾏
#!/bin/bash
#添加本地执⾏路径
export LD_LIBRARY_PATH=/etc/frp/while true; do
server=`ps aux | grep frpc | grep -v grep` if [ ! \"$server\" ]; then
nohup ./frpc -c ./frpc.ini & fi
sleep 60done
2)内⽹服务器frpc安装配置:
设置好中转服务器上 Frp 服务端后,我们就需要在内⽹服务器上安装 Frp 的客户端了。 这⾥安装⽅式和中转服务器⼀样,此处省略。当然内⽹服务器可以是 Windows 电脑、Linux 设备 (⽐如树莓派) 或者 NAS,甚⾄部分路由器等设备上。Linux 客户端的安装和启动与服务器端没有太多区别,只是对应运⾏程序是 frpc ⽽不是 frps。前⾯介绍了Linux安装,这⾥就以内⽹服务器为
Windows 电脑来安装 Frp 客户端,因为 Frp 是绿⾊程序,下载软件包回来解压后,启动 frpc.exe 即可。但在启动前,我们需要先修改配置⽂件,⾸先删掉frps、frps.ini、frps_full.ini⼏个⽂件。假设你的 FRP 中转服务端所在的 VPS 公⽹ IP 为 1.2.3.4或为域名 frp.abc.top, ⽽客户端是 Win 电脑,我们来修改 frpc.ini 配置⽂件:
[common]
server_addr = 1.2.3.4或者frp.abc.top #公⽹服务器ip或域名server_port = 7000 #隧道端⼝,与服务端bind_port⼀致
authentication_method = token #启⽤token验证,frps也需要加此参数token = changeit #token密码
[ssh] #公⽹通过ssh访问内部服务器(这⼀种ssh是最简单暴露公⽹不太安全的映射,如果需要安全的ssh,可以看后⾯的配置[secret_ssh])type = tcp #连接协议tcp
local_ip = 192.168.1.30 #内⽹服务器在局域⽹中的 IP (如是本机,也可使⽤ 127.0.0.1)local_port = 22 #内⽹服务器ssh端⼝号
remote_port = 6000 #⾃定义的访问中转服务器映射的ssh端⼝号,客户机访问中转服务器IP:6000即可到达本机ssh[secret_ssh] #公⽹通过ssh加密访问内部服务器,注意这种⽅式还需要在客户机 [secret_ssh_visitor] #上安装配置frpc.ini(客户机配置请看右边[secret_ssh_visitor]) type = stcptype = stcp #连接协议stcp role = visitor
sk = abcdefg #客户端连接ssh的秘钥 server_name = secret_sshlocal_ip = 127.0.0.1 sk = abcdefg
local_port = 22 bind_addr = 127.0.0.1remote_port = 6000 bind_port = 6000
[web] #公⽹访问内部web服务器以http⽅式type = http #访问协议
local_port = 80 #内⽹web服务的端⼝号
custom_domains = repo.iwi.com #所绑定的中转服务器IP的域名,⼀级、⼆级域名都可以,此域名会映射给中转服务端,客户机访问http://repo.iwi.com:8000即可到达本机web
remote_port = 8000 #⾃定义的访问中转服务器映射的web端⼝号,客户机访问中转服务器IP:8000或域名:8000即可到达本机web。如果中转服务器配置了vhost_http_port = 80和vhost_https_port = 443,这⾥可以省略,不省略则访问端⼝以这⾥配置为准。
[RDP] #Windows 远程桌⾯控制type = tcp
local_ip = 192.168.1.30 #内⽹服务器在局域⽹中的 IP (如是本机,也可使⽤ 127.0.0.1)local_port = 3389remote_port = 7002
# 如果内⽹服务器是https,还需要做以下配置(frp对于https的映射代理原理在后⾯会有⼯作流程图介绍)[web_https] #Https服务,映射的是服务端https443端⼝type = https #服务⽅式
local_ip = 127.0.0.1 #内⽹服务器在局域⽹中的 IP (如是本机,也可使⽤ 127.0.0.1)local_port = 443 #内⽹web服务的端⼝号
custom_domains = test.test.com #所绑定的中转服务器IP的域名,⼀级、⼆级域名都可以,此域名会映射给中转服务端,客户机访问https://test.test.com:443即可到达本机web
#配置https插件部分(这⾥都配置在了内⽹服务器端,即frp客户端,实际是有缺陷的,后⾯https⼯作原理介绍会提到,还可以在中转服务器,即frp服务端结合nginx配置,我个⼈推荐选择中转服务器端结合nginx做配置,后⾯会有详细配置介绍)plugin = https2http #配置插件,将https请求转换成http请求后再发送给本地服务
plugin_local_addr = 127.0.0.1:80 #转换http后的端⼝,这⾥端⼝号为前⾯设置[web]的local_port,即内⽹服务器http的web服务的端⼝号remote_port = 8001 #同http配置,这⼀句可选加
#内⽹服务器证书相关配置
plugin_crt_path = C:\\Users\\Administrator\\Desktop\est.test.com\\fullchain1.crt #linux下⽣成的证书为fullchain.pem格式,复制到Windows上改成.crt后缀即可plugin_key_path = C:\\Users\\Administrator\\Desktop\est.test.com\\privkey1.key #linux下⽣成的证书为privkey.pem格式,复制到Windows上改成.key后缀即可plugin_host_header_rewrite = 127.0.0.1 #这⾥必须写成 127.0.0.1 plugin_header_X-From-Where = frp #指定代理⽅式为 frp
这样就在本地上新增了“ssh”和“web”以及“RDP”“https”⼏个可供公⽹访问的服务了 (它们名称可以⾃⼰取)。如果你需要添加更多的设备和服务供外⽹访问,那么只需要照葫芦画瓢,指定正确的 IP地址和端⼝号即可。
注意放⾏端⼝:每个服务的 remote_port 是远程访问时要⽤到的端⼝号,注意这些端⼝号也要在服务器的防⽕⼟啬和安全组⾥放⾏才能顺利访问的,如上⾯的 6000、7002、8000。
server {
listen 443 ssl; # https对应端⼝,注意因为有nginx也有frps,以nginx这⾥的端⼝为准,frps中的vhost_http**s**_port不⽤配置 ssl_certificate /etc/letsencrypt/live/test.test.com/fullchain.pem; # 证书存放位置 ssl_certificate_key /etc/letsencrypt/live/test.test.com/privkey.pem; # 证书存放位置
server_name *.test.test.com; # ip,域名,我这⾥以泛域名举例,毕竟是做反向代理,http就不⽤配置了 rewrite ^(.*) https://$server_name$1 permanent; # 可以做个http强制转换为https # https还可以做其他安全配置,需要的去看其他⽂章 location / {
proxy_pass http://127.0.0.1:12369; # 映射的frp服务端frps.ini的 vhost_http_port端⼝ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection \"upgrade\"; proxy_max_temp_file_size 0; proxy_redirect off;
proxy_read_timeout 240s; }
error_page 500 502 503 504 /50x.html; location = /50x.html {
root /usr/share/nginx/html; }}
修改完nginx配置后重启nginx
sudo nginx -s reload
修改中转服务器frps.ini配置
[common]
................. #其他配置省略..................
vhost_http_port = 12369 #客户端http映射的端⼝,就是上⾯Nginx的proxy_pass对应端⼝..................................
配置完之后还是运⾏服务端测试⼀下Linux :
/etc/frp/frps -c /etc/frp/frps.ini
内⽹服务器,即frp客户端frpc.ini配置:
..............................
[test_http] #Http服务,映射的是服务端http80端⼝type = http #服务⽅式
local_ip = 127.0.0.1 #服务端ip,可写本地,局域⽹等做反向代理的iplocal_port = 80 #服务端端⼝
#custom_domains = test.test.com #需要反向代理的域名,就是服务端要代理的域名,因为我们只需要https穿透,在nginx中已经做了https的域名配置,这⼀句可以不⽤添加
配置完之后运⾏,Linux :
/etc/frp/frps -c /etc/frp/frps.ini
启动frpc,windows:
c:\\frp\\frpc.exe -c c:\\frp\\frpc.ini
3)进⾏远程访问:
按照上⾯的配置,我们想要远程桌⾯连接到家⾥的 Windows 电脑,那么打开“微软远程桌⾯客户端”后,在地址栏⾥填⼊中转服务器公⽹IP:7002 即可连接。同理其他连接根据中转服务器IP:设置的端⼝号来访问就可以了。由此,借助 Frp,你就能轻松地为本地局域⽹内⽹的设备提供公⽹直接访问的能⼒了,你可以⽤ Frp 来转发包括但不限于 ssh、http、https、转发 Unix 域套接字等服务。上⾯只是最基础的教程,Frp 还有很多很多⾼级功能,⽐如给 Web 增加密码保护、点对点内⽹穿透、设置端⼝⽩名单等等,Frp 官⽹上也提供了很详细的⽂档,感兴趣的朋友可以去研究⼀下。
5.2 zerotier安装配置
免费版⽀持客户端多。连⼊同⼀个⽹络的客户端不超过100个就都免费。所以我们⾃⽤NAS远程访问完全够了,这⾥以安装配置免费版为例:
ZeroTier相当于软交换机,需要在内⽹服务器和客户机上安装ZeroTier one软件,然后在官⽅给的中转服务端或者⾃⼰搭建的云主机中转服务器(moon)中配置VLAN和路由,这样就把俩个VLAN连在了⼀起,⾥⾯的设备便可以互相访问。
正是因为如此,zerotier不⽀持域名和ddns,也就是说必须以虚拟IP互相访问,moon节点仅⽀持固定公⽹IP,且未来2.0版本依然维持此设定,如果需要⽤域名访问内⽹web服务器,此⽅法不可⽤,这也是⽬前我想到的这个⽅法唯⼀⼀个不满⾜的场景。官⽅中转服务端或moon配置:1.ZeroTier账号并登陆(此处省略)
2.登录后配置⽹络(这⾥默认是官⽅免费中转服务器,可以免费创建多个network,每个network实现⼀个局域⽹)
这样就进⼊了⽹络设置界⾯,⽹络设置界⾯可以配置很多东西,但是这⾥只介绍需要⽤到的部分,就是 NetworkID 和下⾯的 Members。NetworkID 是在连⼊新设备时需要⽤到的标识符,每个设备连接这个虚拟的局域⽹时都要输⼊这个ID。Members 则是连⼊⽹络的设备列表,按照默认的设定,当有⼀个新设备接⼊⽹络时,⽤户需要在这个页⾯进⾏授权。这⾥其实可以不⽤⾃⼰做额外配置,默认就好,下⾯还是把其中⼀些重要参数截图说明下:
下⾯插⼊ ⼀个概念:moon。
先简单提⼀下 UDP 打洞的原理,UDP 打洞的本质是让 NAT 后⾯的机器 A 和 B 先连接⼀个有公⽹ IP 的中间服务器,然后中间服务器经过⼀番操作之后让 A 和 B 直接互联,这样之后的数据传输就是 A 和 B 之间直接传输,不再通过中间服务器。但是出于节省资源和增强健壮性的⾓度,A 和 B 服务器直接打出来的「洞」并不是永久的,⽽是维持⼀段时间后释放,下次连接时重新打洞。这样就带来⼀个问题,Zerotier 是⼀款国外的项⽬,他提供的中间服务器到⼤陆的⽹络状况并不好,有很⾼的延迟,并且很可能丢包,这就导致我们每次「打洞」都有很⾼的延迟。为了解决这个问题,Zerotier 提供了⼀个 moons 的概念,中提供了详细的解释和配置⽅法。
如果需要moon,则要做另外配置,这⾥再说明下如何搭建配置中转机器(moon)centos为例:给⾃⼰的中转主机安装 zerotier-one 这个软件包:
curl -s https://install.zerotier.com/ | sudo bash
之后就完成了安装,然后我们要启动zerotier,并且让他开机⾃启动,运⾏:
sudo systemctl start zerotier-one.servicesudo systemctl enable zerotier-one.service
进官⽅⽹络设置页⾯,复制这个Network ID然后在⾃⼰的moon中转机器上执⾏:
sudo zerotier-cli join 83048a0632246d2c
加⼊之后就启动了,但是还连不进我们创建的⽹络,因为我们选择了 Private(私有⽹络) ,还需要到官⽅⽹络设置页⾯对接⼊的机器打勾,拉到 Members 这⼀节,把前⾯的勾勾选上。这个时候执⾏⼀下 ip a 你会发现多了⼀个叫做 ztuzethlza 或者类似名字的设备,还有IP地址,这就是zerotier组建的局域⽹的IP地址。此时⾃⼰的中转服务器已经被加⼊到了zerotier虚拟的局域⽹下。接下来就是对我们⾃⼰的中转服务器进⾏配置moon。执⾏:
cd /var/lib/zerotier-one/
sudo zerotier-idtool initmoon identity.public > moon.json
此命令会在当前⽬录下⽣成⼀个⽂件 moon.json,⽂件内容如下:
{
\"id\": \"deadbeef00\ \"objtype\": \"world\ \"roots\": [ {
\"identity\": \"deadbeef00:0:34031483094...\ \"stableEndpoints\": [] } ],
\"signingKey\": \"b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0\
\"signingKey_SECRET\": \"ffc5dd0b2baf1c9b220d1c9cb39633f9e2151cf350a6d0e67c913f8952bafaf3671d2226388e1406e7670dc645851bf7d3643da701fd4599fedb9914c3918db3\
\"updatesMustBeSignedBy\": \"b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0\ \"worldType\": \"moon\"}
其中 id 为我们⾃⼰中转服务器在 ZeroTier 中的 id,本⽂为 deadbeef00。接下来编辑moon.json,把 \"stableEndpoints\": [] 这⼀节⾥加⼊我们⾃⼰的中转机器的公⽹IP,例如 \"stableEndpoints\":[\"1.2.3.4/9993\"],其中 9993是默认监听的端⼝,接下来要把9993端⼝的防⽕墙放开(注意是UDP),如果你的机器外边还有防⽕墙的话,也要⼀起放开,例如阿⾥云的机器就有防⽕墙规则,要⼀起把对应端⼝的UDP流量放⾏,如:
\"stableEndpoints\": [ \"1.2.3.4/9993\
若公⽹机器没有 IPv6 地址,则将其修改为
\"stableEndpoints\": [ \"1.2.3.4/9993\" ]
此后,我们要⽣成moon的签名⽂件:
sudo zerotier-idtool genmoon moon.json
此命令会⽣成⼀个签名⽂件在当前⽬录下,⽂件名如 000000deadbeef00.moon (我们⾃⼰的中转服务器 id 为 deadbeef00)接下来将 moon 节点加⼊⽹络
在我们⾃⼰的中转服务器中的 ZeroTier ⽬录中建⽴⼦⽂件夹 moons.d不同系统下的 ZeroTier ⽬录位置:
Windows: C:\\ProgramData\\ZeroTier\\One
Macintosh: /Library/Application Support/ZeroTier/One (在 Terminal 中应为 /Library/Application\\ Support/ZeroTier/One)Linux: /var/lib/zerotier-one
FreeBSD/OpenBSD: /var/db/zerotier-one
将前⾯⽣成的 000000deadbeef00.moon 拷贝进 moons.d ⽂件夹中,并重启 ZeroTier(此步好像有些许 bug,重启电脑为佳)
注意: windows需要重启服务,⽽不是重启程序,按住windows键+r,在弹出的对话框中输⼊services.msc并回车,找到ZeroTier One,右键选择重新启动即可
sudo systemctl restart zerotier-onesync && sync && reboot
这样我们⾃⼰的中转服务器moon配置就完成了,下⾯还要将内⽹服务器和内⽹客户端加⼊moon,这⾥我⾃⼰的内⽹服务器⽤的centos7,需要先安装好zerotier-one并加⼊⽹络,和我们⾃⼰中转服务端安装⽅式⼀样,我的客户机是ios,ios需要⽤国外的apple账号在applestore下载zerotier one,国内商城这个app被下架了。这⾥先查看前⾯moon.json中的id是多少,下⾯这个命令可查看并返回结果为“ \"id\": \"xxxxxxxxxx\:
grep id /var/lib/zerotier-one/moon.json | head -n 1
接着先说下我的内⽹centos7服务器如何加⼊moon节点:复制前⾯查到的id,然后在内⽹centos7机器执⾏:
sudo zerotier-cli orbit xxxxxxxxxx xxxxxxxxxx
注意,xxxxxxxxxx 要两遍。此后重启 zerotier one,完毕。等⼀会⼉之后,zerotier局域⽹内的机器就可以互相访问了,延时⾮常低:
sudo systemctl restart zerotier-one
要验证是否moon⽣效,只需要在客户端zerotier程序⽬录下,执⾏以下命令即可:
zerotier-cli listpeers
若有类似地址,即可证明moon连接成功
200 listpeers abcdefgh00 1.1.1.1/9994;4242;4038 224 1.2.12 MOON接下来再说下内⽹客户端ios如何加⼊moon节点:
其实这⾥是个⼤问题,移动端如何加⼊moon节点,⽬前还没研究出来...内⽹服务器端和客户端安装配置:
前⾯介绍moon安装配置的时候已经描述了centos整个安装过程,参考我们⾃⼰的中转服务器安装配置过程即可,这⾥针对Windows做个简短的安装介绍。进官⽹下载Windows的msi安装包后直接安装;
安装完后打开,在桌⾯下⽅可以看到黄⾊的图标,⿏标右击选择\"join Network\"
弹出⼀个⼩的会话框,三个选项全部勾选上并在上⾯填⼊中转服务器的Network ID后,点击 “join”稍等⽚刻,会弹出此窗⼝,选择“是”即可
最后刷新官⽹中Network配置页⾯,在下⽅的“member”区域中勾选将其注册到⽹络中
好了,到这⾥关于zerotier的服务端和客户端安装配置都做完了,zerotier⽹络组建成功后,相当于⾥⾯的设备在同⼀局域⽹下或俩个不同VLAN下,所以也就意味着⾥⾯的所有设备只要开放了端⼝互相就能访问,⽽不需要像frp那样对单独的某个端⼝最设置,这⼀点也说明zerotier和vpn相似。
最后针对zerotier,有⽹友对它点对点穿透模式做过穿透效果测试,这⾥引⽤了过来,供参考:
\"事实上 Zerotier 的打洞效果好的令我惊讶,我的⽹络环境 A 是上⾏ 20M 下⾏ 100M 的电信⽹络,B 则是移动赠送的 50M 上下⾏对等移动⽹络。晚⾼峰时段,在两边都开启 bbr 的情况下,互相下载⽂件可以跑到⽹络峰值的 60%~70%。电信拖移动能跑3MB/s,反过来则是 1.4MB/s 左右。延迟的话「打洞」完成之后稳定在 90ms,丢包率在 8% 左右。顺便吐槽⼀下,⼀开始看到 90ms的延迟我还以为打洞出了问题,结果直接从移动 ping 了⼀下电信的公⽹ IP(我的电信⽹络环境是有公⽹ IP 的,但是我并没有在路由器设置端⼝转发,因此测试效果仍然是打洞的效果),发现延迟也在 90ms 上下,通过 traceroute 命令追踪路由发现数据包先从隔壁的 H 省进⼊移动⾻⼲⽹,然后进⼊电信⾻⼲,再从另⼀个⽅向隔壁的 S 省回到本地电信,难怪会有这么⾼的延迟。同样,8% 也是晚⾼峰电信和移动互联本⾝的延迟。换⽽⾔之,Zerotier 的打洞⾮常成功,延迟和丢包率基本都和公⽹差距不⼤,但是由于本⾝移动和电信晚⾼峰时段的互联效果较差,因此效果并没有想象中完美。从延迟的⾓度,本地电信到⾹港阿⾥云服务器的延迟尚在 50ms 以下,到洛杉矶的 CN2 服务器也不过 150ms,然⽽与本地移动互联延迟竟然⾼达 90ms,国内 ISP 互联还是任重道远啊。\"
六、总结
以上基本把内⽹穿透原理和实现⽅法很详细的介绍了⼀遍,还是针对不同实现⽅法做个总结吧。1.如果是企业内⽹资料需要员⼯远程访问就⽤VPN。
2.⾃⼰家⾥NAS或远程桌⾯直接⽤zerotier,我⾃⼰没有额外搭建moon,有点延迟但可以接收,还有远程桌⾯也优先⽤zerotier。3.⼀些页⾯访问⽤frp,⽐如测试⽤的web服务、路由器管理界⾯、NAS管理界⾯等等。4.最后如果觉得⿇烦,资⾦允许可以直接花⽣壳之类的收费穿透。
因篇幅问题不能全部显示,请点此查看更多更全内容