FRP内网穿透技术实战

一、前提

1. 需求

(1) 本地测试

通常情况下,我们在开发前端项目(手机网页版)时,想实时在模拟器、安卓真机、苹果真机等多个设备上看到实时页面效果,此时如果设备和本地开发用的电脑不在同一个局域网.

(2) 在线演示

本机开发的程序在调试阶段想直接在线演示给同事、领导、客户等用户看,这时又不想直接打包发布,当测试出bug时,想更改后,再次演示

(3) 微信公众号开发

微信开发中某些功能需要在配置好的js安全接口域名下才能正常调用, 比如 微信授权,微信分享, jssdk API调用等,这种频繁的调试不可能每一次都要部署到公网环境下再进行测试,急需一种在本地更改后可实时调试的方案

2. 解决方案

上述需求基本都是围绕如何在本地修改后,能快速让别人看到本地效果或者能快速调试出在真机环境中的bug所在, 针对这种需求, 我们需要选定的服务是 内网穿透.

关于内网穿透, 市面上常见的服务商有花生壳、ngrok、以及其他一些基于ngrok和frp服务搭建的第三方平台, 这些平台提供的免费内网穿透服务带宽及服务器配置较低, 响应速度较慢, 基本不能自定义域名等, 如果需要享用高速带宽和高配置以及自定义域名, 需付费.

如果我们手头有公网IP,域名,那么可尝试搭建一个内网穿透服务来解决我们的实际需求. 本教程选用的方案是使用frp搭建内网穿透服务.

3. frp简介

frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 https 应用协议提供了额外的能力,且尝试性支持了点对点穿透。

github地址: https://github.com/fatedier/frp

详细中文使用文档: https://github.com/fatedier/frp/blob/master/README_zh.md

二、准备

  • 1台拥有公网 IP 的服务器(阿里云、腾讯云等)
  • 公网IP的服务器已安装nginx服务
  • 1个已经备案的域名
  • 指定的二级域名及其泛域名已解析到公网IP(例如: frp.xxx.com, *.frp.xxx.com这2条已添加A记录解析到公网IP)
  • 1台联网的个人电脑
  • 个人电脑上安装了SSH工具(WinSCP, Xshell等)

三、frp的基本配置与使用

1. frp程序下载与存放

根据对应的操作系统及架构,从 https://github.com/fatedier/frp/releases 页面下载最新版本的frp程序。

将 frps 及 frps.ini 放到具有公网 IP 的机器上(用作服务端)。

将 frpc 及 frpc.ini 放到处于内网环境的机器上(用作客户端)。

以下示例中:

frp服务端存放在linux系统(存放目录为:/usr/local/frp/)

frp客户端存放在windows系统(存放目录为: D:\soft\frp\).

2. frp服务端配置

frps.ini文件内容如下:

[common]
# frps服务端口
bind_port = 7000
# 客户端访问端口
vhost_http_port = 7001
# 自定义二级域名, 需将泛域名 *.frp.xxx.com 解析到 frps 所在服务器的IP地址
subdomain_host = frp.xxx.com
# 服务端和客户端的 common 配置中的 token 参数一致则身份验证通过
privilege_token = xxxxxx
# 通过浏览器查看 frp 的状态以及代理统计信息展示
dashboard_port = 7002
dashboard_user = admin
dashboard_pwd = admin
log_file = ./frps.log
log_level = info
log_max_days = 3

3. frp客户端配置

frpc.ini文件内容如下:

[common]
# frp服务端所在的公网IP
server_addr = xx.xx.xx.xx
# frps服务端口
server_port = 7000
# 和服务端配置的token值保持一致
privilege_token = xxxxxx

[web]
type = http
# 本地需要映射的服务端口
local_port = 8080
# 因启用了泛域名解析,不同的人员,可以使用各自不同的子域名,只要不重复,这样可以方便多人共用服务端资源
subdomain = <你的子域名>
# 服务端定义的二级域名
custom_domains = frp.xxx.com
# 压缩
use_compression = true

4. 公网IP服务器nginx配置

注意: nginx代理的端口需与frp服务端配置中的vhost_http_port保持一致

server {
    listen 80;
    server_name frp.xxx.com *.frp.xxx.com;
    location / {
      proxy_read_timeout 1800;
      proxy_buffer_size 64k;
      proxy_buffers   32 32k;
      proxy_busy_buffers_size 128k;
      proxy_pass_header Server;
      proxy_set_header Host $http_host; # proxy_redirect false; proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Scheme $scheme;
      proxy_pass http://frp.xxx.com:7001;
    }
  }

四、frp客户端热加载配置文件

当修改了 frpc 中的代理配置,可以通过 frpc reload 命令来动态加载配置文件,通常会在 10 秒内完成代理的更新。

启用此功能需要在 frpc 中启用 admin 端口,用于提供 API 服务。配置如下:

# frpc.ini
[common]
admin_addr = 127.0.0.1
admin_port = 7400

之后执行热加载命令:

备注: 执行热加载命令前, 需保证frp客户端已处于运行状态

./frpc reload -c ./frpc.ini

五、frp启动方式

1. frp客户端启动

(1) 手动启动

# frp文件目录执行
./frpc -c ./frpc.ini

# 任何目录执行:
D:\soft\frp\./frpc -c D:\soft\frp\./frpc.ini

(2) 配置开机自启

(1)下载最新版本winsw程序

https://github.com/kohsuke/winsw/releases

(2)将下载好的程序重命名为winsw.exe,拷贝到frp文件夹目录下, 并在该目录创建一个utf8编码的文本文件,文件名为 winsw.xml,内容是:

<service>
   <id>frp</id>
   <name>frp服务名称(随便写)</name>
   <description>frp服务介绍(随便写)</description>
   <executable>frpc</executable>
   <arguments>-c frpc.ini</arguments>
   <onfailure action="restart" delay="60 sec"/>
   <onfailure action="restart" delay="120 sec"/>
   <logmode>reset</logmode>
</service>

(3)以管理员权限打开cmd或powershell窗口, cd进入frp文件夹目录,执行以下指令:

winsw install
winsw start

如果需要卸载frp服务, 执行以下指令:

winsw stop
winsw uninstall

2. frp服务端启动

(1) 手动启动

# frp文件目录执行
./frps -c ./frps.ini

# 任何目录执行
/usr/local/frp/.frps -c /usr/local/frp/.frps.ini

(2) 后台运行

# frp文件目录执行
nohup ./frps -c ./frps.ini>frp_nohup_log 2>&1 &

# 任何目录执行
nohup /usr/local/frp/frps -c /usr/local/frp/frps.ini>/usr/local/frp/frp_nohup_log 2>&1 &

(3) 开机启动

(1)在frp文件目录下创建启动脚本文件,名称自定义为:nohup_start_frp

vi /usr/local/frp/nohup_start_frp

该文件内容为:

nohup /usr/local/frp/frps -c /usr/local/frp/frps.ini>/usr/local/frp/frp_nohup_log 2>&1 &

(2)给nohup_start_frp文件添加可执行权限

chmod +x /usr/local/frp/nohup_start_frp

(3)创建frp开机启动脚本

vi /etc/init.d/frp

该文件内容为:

#!/bin/bash
#
# frp startup script for the server
#
# chkconfig: 2345 90 10
# description: start the frp
#
# Source function library
. /etc/rc.d/init.d/functions
 
#脚本名称
prog=frp
 
#frp安装目录
FRP_HOME=/usr/local/frp/
export FRP_HOME
 
#frp运行命令
FRP_RUN_SERVICE=/usr/local/frp/nohup_start_frp
 
 
case "$1" in
    start)
    echo "Starting frp..."
    $FRP_RUN_SERVICE
    ;;
 
*)
    echo "Usage: $prog {start}"
    ;;
esac
exit 0

(4)给frp开机自启脚本文件添加可执行权限

chmod a+x frp

(5)将frp脚本添加到系统启动队列

chkconfig --add frp

可通过以下指令查看系统启动队列

chkconfig --list

若添加成功,则 frp一列显示为以下内容:

frp 0:off 1:off 2:on 3:on 4:on 5:on 6:off
# 或中文内容
frp 0:关闭 1:关闭 2:启用 3:启用 4:启用 5:启用 6:关闭

(6)启动frp服务

service frp start