Frp 网络穿透工具(v0.66.0)
📖 概述
FRP (Fast Reverse Proxy) 是一个高性能的反向代理应用,可以帮助你将内网服务暴露到公网。
📦 安装
| Bash |
|---|
| # 解压到指定目录
tar -zxvf frp_0.66.0_linux_amd64.tar.gz -C /opt/
cd /opt
mv frp_0.66.0_linux_amd64 frp
# 查看目录结构
tree frp/
frp/
├── frpc # 客户端程序
├── frpc.toml # 客户端配置文件
├── frps # 服务端程序
├── frps.toml # 服务端配置文件
├── LICENSE # 开源协议
└── systemd/ # Systemd 服务文件
├── frpc.service
├── frpc@.service
├── frps.service
└── frps@.service
|
📚 基本概念
| 术语 |
说明 |
| frps |
FRP 服务端,运行在具有公网 IP 的服务器上 |
| frpc |
FRP 客户端,运行在内网需要穿透的服务器上 |
| proxy |
代理配置,定义要暴露的内网服务 |
| auth.token |
认证令牌,用于服务端和客户端之间的认证 |
| clientID |
客户端唯一标识(v0.66+ 新增) |
服务端配置(frps.toml)
基础配置参数
| TOML |
|---|
| bindAddr = "0.0.0.0"
bindPort = 7000
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
bindAddr |
否 |
0.0.0.0 |
服务端监听地址 |
bindAddr = "0.0.0.0" |
bindPort |
是 |
7000 |
服务端与客户端通信的 TCP 端口 |
bindPort = 7000 |
kcpBindPort |
否 |
- |
KCP 协议监听的 UDP 端口 |
kcpBindPort = 7000 |
quicBindPort |
否 |
- |
QUIC 协议监听的 UDP 端口 |
quicBindPort = 7001 |
说明
bindAddr:默认监听所有网卡,生产环境可指定具体 IP
kcpBindPort:KCP 适合高延迟、易丢包网络,但多消耗 10-20% 带宽
quicBindPort:QUIC 协议,基于 UDP 的低延迟传输
代理端口配置
| 参数 |
必填 |
默认值 |
说明 |
示例 |
vhostHTTPPort |
否 |
- |
HTTP 反向代理监听端口 |
vhostHTTPPort = 80 |
vhostHTTPSPort |
否 |
- |
HTTPS 反向代理监听端口 |
vhostHTTPSPort = 443 |
tcpMux |
否 |
true |
是否启用 TCP 多路复用 |
tcpMux = true |
tcpMuxKeepaliveInterval |
否 |
60 |
TCP 多路复用保活间隔(秒) |
tcpMuxKeepaliveInterval = 60 |
说明
vhostHTTPPort:启用后,可通过域名访问内网 HTTP 服务
vhostHTTPSPort:启用后,可通过域名访问内网 HTTPS 服务
tcpMux:启用后,多个连接可复用同一个 TCP 连接,提高性能
Web 控制台配置(Dashboard)
| TOML |
|---|
| webServer.addr = "0.0.0.0"
webServer.port = 5500
webServer.user = "admin"
webServer.password = "your_password"
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
webServer.addr |
否 |
0.0.0.0 |
Dashboard 监听地址 |
webServer.addr = "0.0.0.0" |
webServer.port |
否 |
- |
Dashboard 监听端口 |
webServer.port = 5500 |
webServer.user |
否 |
admin |
Dashboard 登录用户名 |
webServer.user = "admin" |
webServer.password |
否 |
admin |
Dashboard 登录密码 |
webServer.password = "xxx" |
webServer.tls.certFile |
否 |
- |
Dashboard SSL 证书路径 |
webServer.tls.certFile = "/etc/ssl/dashboard.pem" |
webServer.tls.keyFile |
否 |
- |
Dashboard SSL 密钥路径 |
webServer.tls.keyFile = "/etc/ssl/dashboard.key" |
说明
- Dashboard 用于查看 frp 运行状态、代理信息、客户端管理等
- v0.66+ 支持客户端唯一标识(clientID)管理
- 生产环境建议启用 SSL 保护 Dashboard
日志配置
| TOML |
|---|
| log.to = "/var/log/frps.log"
log.level = "warn"
log.maxDays = 7
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
log.to |
否 |
console |
日志文件路径,console 表示输出到终端 |
log.to = "/var/log/frps.log" |
log.level |
否 |
info |
日志级别:trace, debug, info, warn, error |
log.level = "warn" |
log.maxDays |
否 |
- |
日志保留天数 |
log.maxDays = 7 |
log.disablePrintColor |
否 |
false |
是否禁用日志颜色 |
log.disablePrintColor = false |
日志级别说明
trace:最详细,包含所有调试信息
debug:详细调试信息
info:一般信息(推荐)
warn:警告信息
error:错误信息
认证配置
| TOML |
|---|
| auth.token = "your_token_here"
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
auth.token |
推荐 |
- |
客户端连接所需的认证令牌 |
auth.token = "your_token_here" |
auth.additionalScopes |
否 |
- |
额外认证范围:HeartBeats, NewWorkConns |
auth.additionalScopes = ["HeartBeats"] |
OIDC 认证(高级)
| TOML |
|---|
| [auth.oidc]
issuer = "https://accounts.google.com"
audience = "your-audience"
skipExpiryCheck = false
skipIssuerCheck = false
|
说明
auth.token:服务端和客户端必须配置相同的 token 才能连接
auth.additionalScopes:启用后,心跳和新连接也需要认证
- OIDC 认证:支持外部身份提供商(如 Google、Azure AD)
连接限制配置
| TOML |
|---|
| maxPoolCount = 5
maxPortsPerClient = 0
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
maxPoolCount |
否 |
5 |
每个代理的连接池最大连接数 |
maxPoolCount = 5 |
maxPortsPerClient |
否 |
0 |
每个客户端可使用的最大端口数,0 表示无限制 |
maxPortsPerClient = 0 |
allowPorts |
否 |
- |
允许客户端使用的端口 |
allowPorts = [{start=5002,end=5100}] |
allowPorts 格式说明
| TOML |
|---|
| allowPorts = [
{ single = 5001 }, # 单个端口
{ start = 5002, end = 5100 } # 端口范围
]
|
子域名配置
| 参数 |
必填 |
默认值 |
说明 |
示例 |
subDomainHost |
否 |
- |
子域名主机名 |
subDomainHost = "example.com" |
说明
- 启用后,客户端可使用
xxx.example.com 形式的子域名
- 需要配置 DNS 泛解析
*.example.com 到服务器 IP
传输配置
| TOML |
|---|
| [transport]
tcpMux = true
tcpMuxKeepaliveInterval = 60
tcpKeepalive = 60
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
transport.tcpMux |
否 |
true |
是否启用 TCP 多路复用 |
transport.tcpMux = true |
transport.tcpMuxKeepaliveInterval |
否 |
60 |
TCP 多路复用保活间隔(秒) |
transport.tcpMuxKeepaliveInterval = 60 |
transport.tcpKeepalive |
否 |
60 |
TCP 保活间隔(秒) |
transport.tcpKeepalive = 60 |
transport.maxPoolCount |
否 |
5 |
连接池最大连接数 |
transport.maxPoolCount = 5 |
功能开关(Feature Gates)
| TOML |
|---|
| [featureGates]
VirtualNet = false # 虚拟网络功能(Alpha)
|
| 功能 |
说明 |
状态 |
VirtualNet |
虚拟网络,创建 TUN 设备实现 Layer 3 连通性 |
Alpha |
说明
- 实验性功能默认关闭
- 配置为
true 启用
- 生产环境慎用
完整服务端配置示例
| TOML |
|---|
| # === 基础配置 ===
bindAddr = "0.0.0.0"
bindPort = 5000
# kcpBindPort = 5000 # 不启用 KCP 时注释
# === 代理端口 ===
vhostHTTPPort = 5080
vhostHTTPSPort = 5443
# === 认证配置 ===
auth.token = "your_token_here"
# === Dashboard 配置 ===
webServer.addr = "0.0.0.0"
webServer.port = 5500
webServer.user = "admin"
webServer.password = "your_password"
# === 日志配置 ===
log.to = "/var/log/frps.log"
log.level = "warn"
log.maxDays = 7
# === 连接限制 ===
maxPoolCount = 5
maxPortsPerClient = 0
# === 允许端口 ===
allowPorts = [
{ single = 5001 },
{ start = 5002, end = 5100 }
]
# === 子域名 ===
# subDomainHost = "example.com"
# === 传输配置 ===
[transport]
tcpMux = true
tcpKeepalive = 60
|
客户端配置(frpc.toml)
基础配置参数
| TOML |
|---|
| serverAddr = "x.x.x.x"
serverPort = 5000
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
serverAddr |
是 |
- |
服务端地址(公网 IP 或域名) |
serverAddr = "x.x.x.x" |
serverPort |
是 |
- |
服务端 bindPort 端口 |
serverPort = 5000 |
clientID |
否 |
- |
客户端唯一标识(v0.66+ 新增) |
clientID = "unique-client-001" |
loginFailExit |
否 |
true |
登录失败后是否退出 |
loginFailExit = false |
说明
clientID:用于服务端 Dashboard 识别和管理客户端
loginFailExit = false:登录失败后持续重试,适合移动网络
认证配置
| TOML |
|---|
| auth.token = "your_token_here"
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
auth.token |
推荐 |
- |
与服务端一致的认证令牌 |
auth.token = "your_token_here" |
auth.additionalScopes |
否 |
- |
额外认证范围:HeartBeats, NewWorkConns |
auth.additionalScopes = ["HeartBeats"] |
日志配置
| TOML |
|---|
| log.to = "/var/log/frpc.log"
log.level = "warn"
log.maxDays = 7
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
log.to |
否 |
console |
日志文件路径 |
log.to = "/var/log/frpc.log" |
log.level |
否 |
info |
日志级别:trace, debug, info, warn, error |
log.level = "warn" |
log.maxDays |
否 |
- |
日志保留天数 |
log.maxDays = 7 |
log.disablePrintColor |
否 |
false |
是否禁用日志颜色 |
log.disablePrintColor = false |
Web 控制台配置(Admin API)
| TOML |
|---|
| webServer.addr = "0.0.0.0"
webServer.port = 5400
webServer.user = "admin"
webServer.password = "your_password"
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
webServer.addr |
否 |
127.0.0.1 |
Web 控制台监听地址 |
webServer.addr = "0.0.0.0" |
webServer.port |
否 |
- |
Web 控制台监听端口 |
webServer.port = 5400 |
webServer.user |
否 |
- |
Web 控制台用户名 |
webServer.user = "admin" |
webServer.password |
否 |
- |
Web 控制台密码 |
webServer.password = "xxx" |
说明
- 启用后可通过 Web 界面管理 frpc(如热重载配置)
- API 端点:
http://127.0.0.1:5400/api/reload
传输配置
| TOML |
|---|
| [transport]
protocol = "tcp"
heartbeatInterval = 30
heartbeatTimeout = 90
|
| 参数 |
必填 |
默认值 |
说明 |
示例 |
transport.protocol |
否 |
tcp |
与服务端通信的协议:tcp, kcp, quic |
transport.protocol = "tcp" |
transport.heartbeatInterval |
否 |
30 |
心跳间隔(秒) |
transport.heartbeatInterval = 30 |
transport.heartbeatTimeout |
否 |
90 |
心跳超时时间(秒) |
transport.heartbeatTimeout = 90 |
transport.poolCount |
否 |
1 |
连接池大小(预建立连接数) |
transport.poolCount = 1 |
transport.tcpMux |
否 |
true |
是否启用 TCP 多路复用 |
transport.tcpMux = true |
说明
protocol = "kcp":在高延迟、易丢包网络下性能更好
poolCount:预建立连接数,越大连接建立越快,但消耗更多资源
完整客户端配置示例
| TOML |
|---|
| # === 服务端配置 ===
serverAddr = "x.x.x.x"
serverPort = 5000
clientID = "unique-client-001"
# === 认证配置 ===
auth.token = "your_token_here"
# === Web 控制台 ===
webServer.addr = "0.0.0.0"
webServer.port = 5400
webServer.user = "admin"
webServer.password = "your_password"
# === 日志配置 ===
log.to = "/var/log/frpc.log"
log.level = "warn"
log.maxDays = 7
# === 传输配置 ===
[transport]
protocol = "tcp"
heartbeatInterval = 30
heartbeatTimeout = 90
poolCount = 1
tcpMux = true
|
常用代理配置
TCP 端口映射
| TOML |
|---|
| [[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
|
| 参数 |
说明 |
示例 |
name |
代理名称(唯一) |
"ssh" |
type |
代理类型 |
"tcp" |
localIP |
内网服务地址 |
"127.0.0.1" |
localPort |
内网服务端口 |
22 |
remotePort |
服务端暴露的公网端口 |
6000 |
使用方式: ssh -p 6000 user@x.x.x.x
特殊场景
| TOML |
|---|
| # 启用代理(默认启用)
enabled = true
# 负载均衡组
loadBalancer.group = "ssh-group"
loadBalancer.groupKey = "secret-key"
|
UDP 服务
| TOML |
|---|
| [[proxies]]
name = "dns"
type = "udp"
localIP = "8.8.8.8"
localPort = 53
remotePort = 6001
|
| 参数 |
说明 |
示例 |
name |
代理名称 |
"dns" |
type |
代理类型 |
"udp" |
localIP |
内网服务地址 |
"8.8.8.8" |
localPort |
内网服务端口 |
53 |
remotePort |
服务端暴露的公网端口 |
6001 |
HTTP 反向代理
| TOML |
|---|
| [[proxies]]
name = "web"
type = "http"
localIP = "127.0.0.1"
localPort = 80
customDomains = ["www.yourdomain.com"]
|
| 参数 |
说明 |
示例 |
name |
代理名称 |
"web" |
type |
代理类型 |
"http" |
localIP |
内网服务地址 |
"127.0.0.1" |
localPort |
内网服务端口 |
80 |
customDomains |
自定义域名数组 |
["www.yourdomain.com"] |
使用方式: 访问 http://www.yourdomain.com
多域名配置
| TOML |
|---|
| customDomains = ["lovev.top", "www.lovev.top"]
|
HTTPS 反向代理
| TOML |
|---|
| [[proxies]]
name = "web-https"
type = "https"
localIP = "127.0.0.1"
localPort = 443
customDomains = ["www.yourdomain.com"]
|
| 参数 |
说明 |
示例 |
name |
代理名称 |
"web-https" |
type |
代理类型 |
"https" |
localIP |
内网服务地址 |
"127.0.0.1" |
localPort |
内网服务端口 |
443 |
customDomains |
自定义域名数组 |
["www.yourdomain.com"] |
使用方式: 访问 <https://www.yourdomain.com>
子域名配置
| TOML |
|---|
| # 服务端配置
subDomainHost = "example.com"
# 客户端配置
[[proxies]]
name = "blog"
type = "http"
localIP = "127.0.0.1"
localPort = 80
subdomain = "blog"
|
使用方式: 访问 http://blog.example.com
负载均衡(v0.66+ 增强)
| TOML |
|---|
| [[proxies]]
name = "web-01"
type = "http"
localIP = "127.0.0.1"
localPort = 80
customDomains = ["www.yourdomain.com"]
# 负载均衡组
loadBalancer.group = "web-group"
loadBalancer.groupKey = "secret-key"
# 健康检查
healthCheck.type = "http"
healthCheck.path = "/status"
healthCheck.intervalSeconds = 10
healthCheck.maxFailed = 3
healthCheck.timeoutSeconds = 2
|
| 参数 |
说明 |
示例 |
loadBalancer.group |
负载均衡组名 |
"web-group" |
loadBalancer.groupKey |
组密钥(组内必须一致) |
"secret-key" |
healthCheck.type |
健康检查类型:tcp, http |
"http" |
healthCheck.path |
健康检查路径 |
"/status" |
healthCheck.intervalSeconds |
检查间隔(秒) |
10 |
healthCheck.maxFailed |
最大失败次数 |
3 |
healthCheck.timeoutSeconds |
超时时间(秒) |
2 |
HTTPS 负载均衡(v0.66+ 新增)
| TOML |
|---|
| [[proxies]]
name = "web-https-01"
type = "https"
localIP = "127.0.0.1"
localPort = 443
customDomains = ["www.yourdomain.com"]
loadBalancer.group = "web-https-group"
loadBalancer.groupKey = "secret-key"
|
代理启用/禁用开关(v0.66+ 新增)
| TOML |
|---|
| [[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
enabled = false # 禁用但不删除配置
|
说明
enabled = true:启用代理(默认)
enabled = false:禁用代理,配置保留
插件功能
| TOML |
|---|
| # HTTP 代理插件
[[proxies]]
name = "http-proxy"
type = "tcp"
remotePort = 6002
[proxies.plugin]
type = "http_proxy"
httpUser = "abc"
httpPassword = "abc"
# Unix Domain Socket 插件
[[proxies]]
name = "unix-socket"
type = "tcp"
remotePort = 6003
[proxies.plugin]
type = "unix_domain_socket"
unixPath = "/var/run/docker.sock"
|
可用插件
http_proxy:HTTP 代理
socks5:SOCKS5 代理
unix_domain_socket:Unix 域套接字
http2https:HTTP 转 HTTPS
https2http:HTTPS 转 HTTP
高级配置
| TOML |
|---|
| [[proxies]]
name = "web"
type = "http"
localIP = "127.0.0.1"
localPort = 80
customDomains = ["www.yourdomain.com"]
# 元数据
metadatas.key1 = "value1"
metadatas.key2 = "value2"
|
注解(Annotations)
| TOML |
|---|
| [[proxies]]
name = "web"
type = "http"
localIP = "127.0.0.1"
localPort = 80
# 注解
annotations."k8s.io/service-name" = "my-service"
annotations."k8s.io/service-namespace" = "default"
|
说明
- 注解用于 K8s 等场景
- 格式:
annotations."key" = "value"
流量控制
| TOML |
|---|
| [[proxies]]
name = "web"
type = "http"
localIP = "127.0.0.1"
localPort = 80
# 流量控制
transport.proxyProtocolVersion = "v2"
transport.useEncryption = true
transport.useCompression = true
|
| 参数 |
说明 |
示例 |
transport.proxyProtocolVersion |
Proxy Protocol 版本 |
"v2" |
transport.useEncryption |
是否启用加密 |
true |
transport.useCompression |
是否启用压缩 |
true |
启动与管理
启动命令
| Bash |
|---|
| # 服务端启动
./frps -c ./frps.toml
# 后台启动
nohup ./frps -c frps.toml > /dev/null 2>&1 &
# 客户端启动
./frpc -c ./frpc.toml
# 后台启动
nohup ./frpc -c frpc.toml > /dev/null 2>&1 &
|
配置验证
| Bash |
|---|
| # 验证服务端配置
./frps -c ./frps.toml --verify
# 验证客户端配置
./frpc -c ./frpc.toml --verify
|
热重载配置
| Bash |
|---|
| # 通过 Web API 重载
curl http://127.0.0.1:5400/api/reload
# 查看状态
curl http://127.0.0.1:5400/api/status
|
Systemd 服务配置
frps.service(服务端)
| INI |
|---|
| [Unit]
Description=Frp Server Service
After=network.target
[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/opt/frp/frps -c /opt/frp/frps.toml
[Install]
WantedBy=multi-user.target
|
frpc.service(客户端)
| INI |
|---|
| [Unit]
Description=Frp Client Service
After=network.target
[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/opt/frp/frpc -c /opt/frp/frpc.toml
[Install]
WantedBy=multi-user.target
|
启用服务:
| Bash |
|---|
| # 复制服务文件
cp frps.service /etc/systemd/system/
cp frpc.service /etc/systemd/system/
# 重载 systemd
systemctl daemon-reload
# 启用并启动
systemctl enable frps
systemctl start frps
systemctl enable frpc
systemctl start frpc
# 查看状态
systemctl status frps
systemctl status frpc
|
故障排查
检查连接状态
| Bash |
|---|
| # 查看 Dashboard
curl http://127.0.0.1:5500
# 查看代理状态
curl http://127.0.0.1:5400/api/status
|
查看日志
| Bash |
|---|
| # 实时日志
tail -f /var/log/frps.log
tail -f /var/log/frpc.log
# 最近错误
grep -i "error" /var/log/frps.log
grep -i "error" /var/log/frpc.log
# Systemd 日志
journalctl -u frps -n 50 --no-pager
journalctl -u frpc -n 50 --no-pager
|
测试连通性
| Bash |
|---|
| # 测试服务端端口
telnet x.x.x.x 5000
# 测试代理
curl -I http://www.yourdomain.com
curl -I https://www.yourdomain.com
|
常见问题
| 问题 |
原因 |
解决 |
| 连接被拒绝 |
防火墙阻止 |
检查安全组规则 |
| token 认证失败 |
token 不一致 |
检查服务端和客户端配置 |
| 域名无法访问 |
DNS 未解析 |
检查 DNS 配置 |
| 端口无法使用 |
端口被占用 |
检查端口占用情况 |
| KCP 连接失败 |
端口冲突 |
检查 kcpBindPort 是否与 bindPort 相同 |
v0.66+ 新增功能检查
| Bash |
|---|
| # 查看客户端唯一标识
curl http://127.0.0.1:5400/api/client/status
# 查看 Store 管理(内置存储)
curl http://127.0.0.1:5400/api/store/proxies
|
版本差异速查
配置格式对比
| 配置项 |
v0.27.0(INI) |
v0.66.0(TOML) |
| 服务端端口 |
bind_port = 7000 |
bindPort = 5000 |
| KCP 端口 |
kcp_bind_port = 7000 |
kcpBindPort = 5000 |
| HTTP 端口 |
vhost_http_port = 80 |
vhostHTTPPort = 5080 |
| 认证 Token |
token = xxx |
auth.token = "xxx" |
| Dashboard 端口 |
dashboard_port = 7500 |
webServer.port = 5500 |
| 日志文件 |
log_file = ./frps.log |
log.to = "/var/log/frps.log" |
| 自定义域名 |
custom_domains = a.com,b.com |
customDomains = ["a.com","b.com"] |
v0.66.0 新增功能
| 功能 |
说明 |
clientID |
客户端唯一标识,用于多客户端管理 |
enabled |
代理启用/禁用开关 |
loadBalancer.group(HTTPS) |
HTTPS 负载均衡支持 |
tokenSource |
动态令牌认证(OIDC 增强) |
featureGates |
功能开关机制 |
VirtualNet |
虚拟网络(实验性) |
metadatas / annotations |
元数据和注解支持 |
| 新版 Dashboard |
现代化 UI、暗黑模式 |