frp(Fast Reverse Proxy)是一款内网穿透的方向代理工具,它可以将内网服务暴露到公网上,从而可以通过公网访问内网中的服务。支持tcp,udp,http和https协议。

frp 分为客户端 fprc 和服务端 frpsfrpc 用于内网主机,frps 用于公网服务器。下载地址

通过IP访问内网

在目录下找到frps.ini配置文件,按照自己的需要修改相关参数,比如监听端口、token等。配置示例:

# frps.ini
[common]
bind_port = 1001 # 绑定端口
token = 123456 #用于身份验证,保证与客户端一致

防火墙或安全组需要开放frps配置的端口

启动 frps

./frps -c ./frps.ini

在目录下找到frpc.ini配置文件,按照自己的需要修改相关参数,比如服务器地址、端口、token等。配置示例:

# frpc.ini
[common]
server_addr = x.x.x.x # 服务端IP
server_port = 1001 # 服务端端口
token = 123456 #用于身份验证,保证与服务端一致

[rdp]
type = tcp
local_ip = 127.0.0.1
local_port = 8880
remote_port = 8880

[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
use_encryption = true # 加密,防止流量拦截
use_compression = true # 压缩,减少流量传输

启动 frpc

./frpc -c ./frpc.ini

上面实现了:

  • 通过服务端IP访问内网中服务:x.x.x.x:1001
  • 通过SSH访问内网机器:ssh -p 6000 user@x.x.x.x

如果防火墙对外网访问进行流量监控与拦截,例如禁止了 SSH 协议等,可以设置 use_encryption = true,将 frpc 与 frps 之间的通信内容加密传输。

如果报文长度过长,可以设置 use_compression = true ,将报文内容进行压缩。

如果需要设置单个proxy占用的带宽,可以设置 bandwidth_limit = 1MB,目前支持 MBKB

注意:[ssh] 这样的名称在多个客户端中必须唯一

通过域名访问内网

如果你想让其他人通过域名访问你在本地搭建的 Web 服务,但由于你的本地机器没有公网 IP,无法将域名解析到你的本地机器,这时就可以使用 frp 工具来实现。

# frps.ini
[common]
bind_port = 1001
vhost_http_port = 8080
token = 123456
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 1001
token = 123456

[web]
type = http
local_port = 80 # 本地web服务端口
custom_domains = your.domain.com # 你的域名

将域名的A记录解析到x.x.x.x

通过浏览器访问 http://your.domain.com:8080 即可访问到处于内网机器上的 Web 服务。

frp 支持HTTP Basic Auth 来保护 web 服务,增加以下配置:

# frpc.ini
http_user = admin
http_pwd = admin

内网对外提供文件访问服务

# frps.ini
[common]
bind_port = 1001
token = 123456
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 1001
token = 123456

[file]
type = tcp
remote_port = 1001
plugin = static_file
plugin_local_path = /root/deploy # 对外的文件路径
plugin_http_user = admin # 访问账号
plugin_http_passwd = admin # 访问密码

通过浏览器访问 http://x.x.x.x:1001 来查看位于内网 /root/deploy 目录下的文件

仪表盘

frps 提供一个可视化的界面,方便查看 frpc 的连接情况

# frps.ini
[common]
bind_port = 3333
token = 123456

dashboard_port = 3334
dashboard_user = admin # 访问账号
dashboard_pwd = admin # 访问密码

通过浏览器访问 http://x.x.x.x:3333 即可查看仪表盘

dashbord1

dashbord2

限制端口

为了限制端口的滥用,可以手动指定哪些端口可以被使用。在 frps.ini 文件中,可以通过设置 allow_ports 参数来进行配置。

# frps.ini
[common]
allow_ports = 1000-2000,2001,2003,2000-30000

该参数允许指定使用某些特定端口或一段范围内的所有端口,多个端口或范围之间使用 , 分隔,范围内的端口使用 - 连接。

连接池

默认情况下,frps 会在接收到用户请求后再向 frpc 发送请求建立连接。这种方式会增加连接建立和控制信息传递的时间。为了避免这种情况发生,可以启用连接池功能。当启用连接池功能时,frp 会预先为每个代理建立一定数量的连接。当接收到用户请求时,frp 可以直接从连接池中选择一个可用的连接来与用户连接。这样可以避免等待建立连接的时间,特别是在有大量短连接请求时更为有效。

# frps.ini
[common]
max_pool_count = 5
# frpc.ini
[common]
pool_count = 1

负载均衡

目前只支持 tcp 类型的 proxy。

# frpc.ini
[web1]
type = tcp
local_port = 8080
remote_port = 1001
group = web
group_key = test

[web2]
type = tcp
local_port = 8081
remote_port = 1001
group = web
group_key = test

web1 和 web2 可以分布在不同的服务器上,名称不允许重复,使用相同 group 进行负载,group_key 用作权限校验,remote_port 必须相同。

健康检查

可以在proxy中实现健康检查的功能,当被代理的服务出现故障时,自动将该服务从负载均衡中移除,避免因为单点故障导致整个系统崩溃的风险,增加系统可用性和容错能力。

目前可选两种检查类型:tcphttp

tcp 类型只要能够与内网服务建立连接,则判断服务为正常。配置如下:

# frpc.ini
[web]
type = tcp
local_port = 80
remote_port = 1001
token = 123456

# 启用健康检查,类型为tcp
health_check_type = tcp
# 最大检查次数,当超过该值时将从负载均衡中移除该proxy
health_check_max_failed = 1 
# 检查时间间隔
health_check_interval_s = 10
# 连接超时时间
health_check_timeout_s = 3

http 类型 frpc 会往内网服务发送 http 请求,当服务返回 2xx 的状态码才判断服务为正常。配置如下:

[web]
type = http
local_port = 8080
remote_port = 1001
token = 123456
custom_domains = your.domain.com

# 启用健康检查,类型为http
health_check_type = http
# 检查路径
health_check_url = /status
# 最大检查次数,当超过该值时将从负载均衡中移除该proxy
health_check_max_failed = 1 
# 检查时间间隔
health_check_interval_s = 10
# 连接超时时间
health_check_timeout_s = 3

frpc 刚启动时,会立马进行一次检查,如果失败则立马从负载均衡中移除proxy,直到下次检查成功时proxy才会被放回负载均衡中。

设置 Header

# frpc.ini
type = http
local_port = 80
custom_domains = your.domain.com

# 修改header
host_header_rewrite = my.domain.com

# 往后端增加header_开头的参数,例如:X-From-Where
header_X-From-Where = frp

URL 路由

frp 支持根据不同 URL 路径转发到不同的后端服务

# frpc.ini
[web1]
type = http
local_port = 80
custom_domains = your.domain.com
locations = /

[web2]
type = http
local_port = 81
custom_domains = your.domain.com
locations = /path1,/path2

设置代理

可以为 frpc 设置代理与 frps 进行连接。

# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 1001
http_proxy = http://user:pwd@host:port

使用 systemd

在 Linux 系统下,使用 systemd 可以方便地控制 frps 的启动和停止、配置后台运行和开启自启。

要使用 systemd 来控制 frps,需要先安装 systemd,然后在 /etc/systemd/system 目录下创建一个 frps.service 文件。

如果Linux服务端上没有安装 systemd,可以使用 yum 或 apt 等命令安装 systemd

# yum
yum install systemd
# apt
apt install systemd

创建并编辑 frps.service 文件。

vim /etc/systemd/system/frps.service

写入内容:

[Unit]
# 服务名称,可自定义
Description = frp server
After = network.target syslog.target
Wants = network.target

[Service]
Type = simple
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart = /path/to/frps -c /path/to/frps.ini

[Install]
WantedBy = multi-user.target

使用 systemd 命令,管理 frps。

# 启动frp
systemctl start frps
# 停止frp
systemctl stop frps
# 重启frp
systemctl restart frps
# 查看frp状态
systemctl status frps

配置 frps 开机自启。

systemctl enable frps