自建frps+frpc实现内网穿透

在IPv4地址池枯竭的当下,家庭宽带只能拥有NAT后的内网地址已经成了常态。找ISP软磨硬泡讨一个公网IP不失为一种方法,但这样做往往会把战线拉得很长。于是,花生壳/Ngrok/frp等方案便显得十分合适。这些方案有的是开源项目,有的是商业服务。但是,它们的原理基本相——即让一个拥有公网IP的机器,“借”几个端口给没有公网IP的机器,从而让没有公网IP的机器上的服务能够对公网暴露。

frp的原理

常规情况

在常规的情况下,服务器需要拥有公网IP。IP就如同门牌号,有了门牌号,别人才能找到你。客户端即便是处在NAT环境下,也能通过公网IP访问到服务器提供的服务。NAT环境内的客户端发起的连接建立之后,NAT网关便会对外打开一个端口来接收服务器返回的数据,并把接收到的数据转发给客户端。但是这个通讯,必须由NAT环境内的机器来发起。而提供服务的一方总是被动地等待传入连接的,因此NAT环境下的机器是无法对NAT环境外的机器提供服务的(这里暂时不考虑端口映射、DMZ、UDP穿透等因素)。

frp情况

如果用了frp,那么处在NAT环境下的服务器也能对NAT环境外的机器提供服务了。这需要一台有公网IP的机器来做frp服务器。没有公网IP的应用服务器首先要告诉frp服务器:“我有一个服务运行在A端口,我想借你的B端口来对外开放这个服务。”frp服务器答应了。于是应用服务器便和frp服务器建立起了一个长连接,这使得frp服务器可以随时发送数据给应用服务器(NAT环境下,连接的建立只能是单向的;但连接建立后的通讯仍然可以是双向的)。frp服务器还同时开始监听B端口上的传入连接。当有客户端想要访问应用服务器A端口上的服务时,它需要访问frp服务器的B端口。frp服务器接到这个请求后,就通过刚才建立的那个长连接把请求转发给应用服务器,应用服务器处理完这个请求,把响应发送给了frp服务器,frp服务器再次转发给客户端。整个流程就完成了。这就是frp的基本原理。

之前就在家里的路由器上尝试过搭建frps来提供内网穿透服务,但出于路由器系统更新后不再提供frps的软件包、以及家庭宽带连通性欠佳等因素,决定将frps转移到我的阿里云服务器上。那么,开始吧!

服务端(frps)

参考文章:https://www.itgeeker.net/centos-7-x64%E5%A6%82%E4%BD%95%E5%AE%89%E8%A3%85%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F%E5%B7%A5%E5%85%B7frps%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF/

首先,从GitHub下载最新的frps。frp的官方地址是:https://github.com/fatedier/frp/releases。由于我的服务器系统是CentOS 64位,我需要下载后缀为linux_amd64的文件。

wget https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_linux_amd64.tar.gz

下载完成后解压文件:

tar -xzvf frp_0.33.0_linux_amd64.tar.gz

将可执行文件和配置文件复制到系统相应位置:

cp frps /usr/bin/frps
mkdir /etc/frp
cp frps.ini /etc/frp/frps.ini
cp systemd/frps.service /usr/lib/systemd/system/frps.service

重新加载systemd的服务项:

systemctl daemon-reload

在开启服务之前,需要对frps进行配置,frps的配置文件位于/etc/frp/frps.ini,如何配置可以参考:https://github.com/fatedier/frp/blob/master/README_zh.md。最后,启动服务并设置开机自启:

systemctl start frps
systemctl enable frps

如果启用了Dashboard,在浏览器输入http://[服务器地址]:[Dashboard端口]/,就能看到frps的Dashboard界面了。服务端的部署到此结束。

frps Dashboard界面

客户端(frpc)

首先在https://github.com/fatedier/frp/releases下载frp,由于我使用的是Windows 64位的系统,我需要下载后缀为windows_amd64的文件。接着,再到https://github.com/winsw/winsw/releases下载WinSW,下载后缀为NET461的文件即可。WinSW可以把任何EXE打包成一个服务,而免去了每次都要手动启动的麻烦。解压frp,和WinSW一起放在一个文件夹内。

配置frpc.ini,如何配置可以参考https://github.com/fatedier/frp/blob/master/README_zh.md。将WinSW.NET461.exe重命名为frpc_service.exe。新建一个名为frpc_service.xml的文件,输入以下内容:

<service>
  <id>frpc</id>
  <name>FRPC</name>
  <description>This service runs frp client.</description>
  <executable>frpc.exe</executable>
  <arguments>-c frpc.ini</arguments>
  <logmode>rotate</logmode>
</service>

删除多余的文件,只留下以下几个文件:

把整个文件夹藏到C:\Program Files\中,在文件夹中打开命令提示符,启动打包好的服务:

.\frpc_service.exe install
.\frpc_service.exe start

打开service.msc,可以看到出现了一个新的服务,并且已经被设置为了开机自启:

为了让frpc能够在连接错误退出后重启,需要在恢复选项卡中设置自动重启:

如果启用了Admin UI,在浏览器输入http://localhost:[Admin UI端口]/,就能看到frpc的Admin UI界面了。客户端的部署到此结束。

frpc Admin UI界面

接下来,就能体验frp的各种功能了!