如果你对接过国内的一些开放平台,比如微信(公众号、小程序)、支付宝什么的,你会发现在开发阶段就需要一个公网地址来提供API或者接收回调,你总不能搞个服务器,开发一点,部署一点吧。今天我们介绍一个方法,将服务器的请求,转发到你的开发机上,这样不管是修改代码、查看日志还是跟踪调试,都会很方便。
frp是“一个可用于内网穿透的高性能的反向代理应用”,啥是内网穿透?啥是反向代理?别管它,直接看怎么用起来。frp分为服务端和客户端,两者的源码是放在一起的,你可以在它的releases页面根据你的系统下载对应的二进制包。服务端使用的命令是frps,对应的配置是frps.ini,客户端使用的命令是frpc,对应的配置是frpc.ini。

服务端和客户端都运行起来的时候,两者会建立一个通道,服务端监听到一个请求之后,会通过通道将请求转发到客户端,客户端再将请求转发到实际处理的程序,比如你IDE里正在运行的web应用。
在动手操作之前,你需要有一台服务器,我演示使用的是阿里云的ECS,系统是Ubuntu 18.04。还需要一个域名,就是网站访问时候使用的域名,本文使用frp.fookwood.com域名作为示例。另外你本地需要有个web应用,不管你使用Spring Boot还是Django还是Rails都无所谓,只要你知道端口就行。
服务端配置
服务端的配置非常简单,解压源码之后,打开frps.ini,你会发现里面已经有了一个默认的配置bind_port = 7000
,这个代表frp客户端连服务器的时候连的就是7000端口。你只需要加上一句vhost_http_port = 80
,即可监听80端口。

你还有更简单的写法,不需要配置文件,直接通过命令参数指定端口:

因为要绑定80端口,所以需要root权限。配合nohup命令,我们可以让frps在后台运行,这样服务端就已经配置好了。打开浏览器访问你的域名,出现如图所示页面,就说明frp服务端已经正常工作了。

注意配置云服务器的安全组规则,放开7000端口(或者其他你设置的端口),否则客户端连不上的。
客户端配置
客户端的配置也很简单,需要修改frpc.ini文件。首先需要服务端的地址和端口,方便建立连接。其次是本地web服务的端口,一般是8080或者3000等等,根据你使用的开发框架或者项目里的设置来定。

通过frpc -c frpc.ini
启动客户端之后,整个frp的搭建过程就结束了。你访问链接frp.fookwood.com和访问localhost的效果是一样的。

这样别人就可以通过域名访问你的服务了。比如你想把网页分享给你的朋友,或者想接收第三方平台的回调,都可以实现了。
HTTPS配置
有的时候你可能需要把https证书也配置好。比如你做小程序开发,会知道微信要求你的小程序只能访问https接口。这就麻烦了,因为涉及到一个问题,你要处理https证书。
刚开始的时候,我的选择是把HTTPS的流量直接转发到客户端,在客户端这里配置证书什么的。后来发现不太对,挺麻烦的,毕竟将来部署的时候,也还是需要在服务端配置的。不如就在服务端把HTTPS配置好,将来上线的时候就简单了。
具体做法是,将frps的vhost_http_port设置为8080,然后通过nginx将HTTP和HTTPS请求都转发到8080端口。这样的话,按照上面的介绍的,我们的客户端配置不用改变,只改服务端就行。将来服务要上线的话,把frps关掉,如果你用的是Spring Boot,可以把项目的jar包上传到服务器上,通过java -jar app.jar
运行,默认端口是8080,这样刚好替换了frps,系统正常工作。

工作流程大概就长上图这个样子,这样做的好处就是,frps监听的8080端口,不再需要root权限了,任何一个用户都能运行。同时部署应用的时候,使用Spring Boot默认的8080端口也不需要root权限了。刚好符合“最小权限原则”。
接下来看看nginx如何配置。在Ubuntu 18.04下,通过apt install nginx
安装nginx,它的配置都在/etc/nginx
目录下。其中sites-available
目录用来存放多个站点的配置信息,如果想要开启某个站点,就将其配置文件链接到sites-enabled
目录下。默认会有个default配置文件,修改它为以下内容:

你可以将其中的域名替换成你的域名。证书我用的是letsencrypt生成的,相关文件通常会放在/etc/letsencrypt/live/[域名]/
目录下。证书配置完成之后,通过service nginx restart
重启下nginx,或者通过nginx -s reload
重新加载配置。最后,你通过http或者https都可以成功访问。

总结
frp的确是很有用的工具,github上也已经有了两万多星,本文介绍的配置方式,仍然有很多可以改进和增强的,比如frps和frpc的身份验证,使用图形化工具Dashboard和Admin UI等,有兴趣的可以查看其文档。另外本文的nginx的配置,也是我现用现学的,使用proxy_pass的时候header如何正确设置,我还在研究中,等我搞清楚了,再来写篇文章给大家解释下。