适用版本:frp v0.71.0 (2026-08-14 发布),配置文件统一使用 TOML 格式。
v0.52.0 起 frp 支持 TOML / YAML / JSON,INI 已废弃且新特性只在非 INI 格式中可用,本文所有示例均以 TOML 为准。
目录
-
- [frp 是什么,能解决什么问题](#frp 是什么,能解决什么问题)
- 准备工作
- [安装 frp](#安装 frp)
-
- [Linux 手动安装(推荐,最通用)](#Linux 手动安装(推荐,最通用))
- [Windows 安装](#Windows 安装)
- [macOS 安装](#macOS 安装)
- [快速上手:穿透 SSH](#快速上手:穿透 SSH)
-
- [第 1 步:服务端(公网服务器)](#第 1 步:服务端(公网服务器))
- [第 2 步:客户端(内网机器)](#第 2 步:客户端(内网机器))
- [第 3 步:验证](#第 3 步:验证)
- [第 4 步:配置为 systemd 服务(开机自启)](#第 4 步:配置为 systemd 服务(开机自启))
- [Windows 开机自启](#Windows 开机自启)
- [服务端 frps 详解](#服务端 frps 详解)
- [客户端 frpc 详解](#客户端 frpc 详解)
- 实战场景配置集
-
- [远程桌面(Windows RDP)](#远程桌面(Windows RDP))
- [暴露本地 Web 服务(HTTP)](#暴露本地 Web 服务(HTTP))
- 泛子域名(subdomain)
- [HTTPS 加密访问](#HTTPS 加密访问)
-
- [https2http 插件(frp 侧终止 TLS,最省事)](#https2http 插件(frp 侧终止 TLS,最省事))
- [Nginx / Caddy 反向代理(推荐生产用)](#Nginx / Caddy 反向代理(推荐生产用))
- [本地已是 HTTPS 服务](#本地已是 HTTPS 服务)
- [安全暴露服务:stcp(强烈推荐用于 SSH / RDP / 数据库)](#安全暴露服务:stcp(强烈推荐用于 SSH / RDP / 数据库))
- [P2P 点对点穿透:xtcp](#P2P 点对点穿透:xtcp)
- [UDP 穿透(DNS / 游戏 / WireGuard)](#UDP 穿透(DNS / 游戏 / WireGuard))
- [临时文件共享(static_file 插件)](#临时文件共享(static_file 插件))
- [把内网机器变成 SOCKS5 代理](#把内网机器变成 SOCKS5 代理)
- 穿透局域网内其他机器
- 运维:日志、热加载、监控
- 故障排查速查表
- 进阶特性
-
- 负载均衡(同组多实例)
- 健康检查
- 带宽限速
- [PROXY Protocol(透传真实客户端 IP)](#PROXY Protocol(透传真实客户端 IP))
- 传输协议选择
- VirtualNet(虚拟组网,实验特性)
- 常见参数速查
- [老版本 INI 配置迁移对照](#老版本 INI 配置迁移对照)
- 附录:完整配置参考
frp 是什么,能解决什么问题
frp(Fast Reverse Proxy)是一个 Go 编写的反向代理 / 内网穿透工具。它把内网里没有公网 IP 的服务,"映射"到一台有公网的服务器上,从而让外网能够访问。
典型场景:
| 场景 | 说明 |
|---|---|
| 远程 SSH / 远程桌面 | 在家连公司或家里的 Linux / Windows 机器 |
| 暴露本地 Web 服务 | 给客户演示本地跑的项目、微信小程序/公众号回调调试、支付回调联调 |
| NAS / Home Assistant | 外网访问家里的群晖、Emby、HA |
| 自建游戏联机 / DNS | UDP 协议穿透 |
| 临时文件共享 | 用内置插件把本地目录变成静态文件服务 |
| 安全内网访问 | 用 stcp 让服务"只对自己可见",完全不暴露公网端口 |
前提条件:你必须有一台带公网 IP 的服务器(云服务器 / 轻量应用服务器即可,腾讯云、阿里云、华为云等几十元一年的轻量服务器完全够用)。frp 只是"中转",没有公网服务器就无从谈起。
⚠️ 合规提示:frp 是中立的网络工具。请确保你穿透的服务是自己的、且用途合法合规;不要用它绕过企业网络管控或对外提供违规服务。
与同类方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| frp | 开源、自建可控、带宽/域名自己掌握、功能极全 | 需要一台公网服务器,需自己维护 |
| 花生壳 / 金万维等 | 开箱即用、无需服务器 | 免费版限速限流量,商业版按年付费 |
| ngrok | 命令简单 | 免费版域名随机且会变,国内速度一般 |
| Tailscale / ZeroTier | 组网体验好、P2P 直连 | 是组网而非端口转发,多端都要装客户端 |
| 服务器端口映射 | 稳定 | 需要有公网 IP,很多宽带不给 |
端口理解
| 端口 | 配置项 | 在哪儿监听 | 作用 |
|---|---|---|---|
| serverPort / bindPort | frps 的 bindPort,frpc 的 serverPort |
公网服务器 | frpc 与 frps 之间的控制通道,只跑 frp 自己的协议,不跑业务流量 |
| localPort | frpc 的 localPort |
内网机器 | 你真正要暴露的本地服务端口(如 SSH 的 22) |
| remotePort | frpc 的 remotePort |
公网服务器 | 暴露在公网上、供外网用户访问的端口(如 6000) |
HTTP/HTTPS 类型代理不用
remotePort,而是共用 frps 的vhostHTTPPort/vhostHTTPSPort,靠域名 区分(虚拟主机)。stcp / xtcp 类型代理不用
remotePort也不监听公网端口。
组件角色
| 组件 | 运行位置 | 作用 |
|---|---|---|
| frps | 公网服务器 | 服务端,接收 frpc 连接、对外提供端口/域名 |
| frpc | 内网机器 | 客户端,主动连 frps 并声明要暴露哪些服务 |
| proxy | frpc 配置 | 一条穿透规则([[proxies]]) |
| visitor | frpc 配置 | 访问端,用于访问 stcp/xtcp 类型的代理([[visitors]]) |
代理类型一览
| 类型 | 用途 | 是否占公网端口 |
|---|---|---|
tcp |
通用 TCP:SSH、RDP、MySQL、Redis 等 | 是(remotePort) |
udp |
通用 UDP:DNS、游戏、QUIC 部分场景 | 是 |
http |
HTTP 网站,按域名路由 | 否(共用 vhostHTTPPort) |
https |
HTTPS 网站,按域名路由 | 否(共用 vhostHTTPSPort) |
tcpmux |
多服务复用同一端口(HTTP Connect 方式) | 是(复用 tcpmuxHTTPConnectPort) |
stcp |
安全 TCP:只有特定 frpc 能访问,不暴露公网端口 | 否 |
sudp |
安全 UDP,同上 | 否 |
xtcp |
P2P 点对点穿透,流量不经过服务器 | 否 |
准备工作
硬件 / 网络
- 一台公网服务器:Linux(推荐 Ubuntu 22.04 / Debian 12),有独立公网 IPv4。
- 一台内网机器:Linux / Windows / macOS 均可。
- 确认服务器能被访问:安全组 + 系统防火墙都要放行端口(新手 90% 的问题出在这里)。
需要放行的端口
| 端口 | 说明 | 是否必须 |
|---|---|---|
7000(bindPort) |
frpc → frps 控制通道 | 必须 |
6000、6001...(remotePort) |
每个 tcp/udp 代理暴露的端口 | 按你的配置 |
80 / 443(vhost 端口) |
HTTP/HTTPS 代理 | 用 HTTP 代理时 |
7500(webServer.port) |
Dashboard 管理面板 | 可选 |
云服务器务必检查"安全组":腾讯云/阿里云/华为云控制台里的安全组是独立于系统防火墙的第二道闸,两边都要开,否则端口依然不通。
确认系统架构
bash
uname -m
# x86_64 → 下载 amd64
# aarch64 / arm64 → 下载 arm64
# armv7l → 下载 arm
安装 frp
Linux 手动安装(推荐,最通用)
示例版本为0.71.0,下载之后上传至服务器与客户机。
bash
# 设置版本号,可改为最新版
VERSION=0.71.0
tar -zxvf frp_${VERSION}_linux_amd64.tar.gz
sudo mkdir -p /opt/frp /etc/frp
sudo mv frp_${VERSION}_linux_amd64/frps /opt/frp/ # 服务端只需要 frps
sudo mv frp_${VERSION}_linux_amd64/frpc /opt/frp/ # 客户端只需要 frpc
sudo chmod +x /opt/frp/frps /opt/frp/frpc
# 验证
/opt/frp/frps --version
每个发行包里同时含 frps 和 frpc。服务端只留 frps,客户端只留 frpc 即可,不要在同一台机器上混淆。
Windows 安装
- 从 Releases 下载
frp_0.71.0_windows_amd64.zip,解压到C:\frp\。 - 新建
C:\frp\frpc.toml,内容参考后文。 - 测试:
.\frpc.exe -c .\frpc.toml - 常见杀软会误报 frpc(因为它是反向代理工具),请在杀毒软件里把
C:\frp加入白名单。
macOS 安装
bash
VERSION=0.71.0
curl -LO https://github.com/fatedier/frp/releases/download/v${VERSION}/frp_${VERSION}_darwin_arm64.tar.gz
tar -zxvf frp_${VERSION}_darwin_arm64.tar.gz
sudo mkdir -p /usr/local/frp && sudo mv frp_${VERSION}_darwin_arm64/frpc /usr/local/frp/
快速上手:穿透 SSH
目标:让外网通过 公网IP:6000 SSH 登录到内网机器的 22 端口。
第 1 步:服务端(公网服务器)
创建或打开frps.toml,例如配置文件在
/etc/frp/frps.toml
bash
sudo cat /etc/frp/frps.toml
bindPort = 7000
auth.method = "token"
auth.token = "MyStr0ng_Token_ChangeMe_2026"
# 使用nano或vi进行修改
sudo nano /etc/frp/frpc.toml
放行端口:
bash
# Ubuntu/Debian (ufw)
sudo ufw allow 7000/tcp
sudo ufw allow 6000/tcp
sudo ufw reload
# RHEL/CentOS/Rocky (firewalld)
sudo firewall-cmd --permanent --add-port=7000/tcp
sudo firewall-cmd --permanent --add-port=6000/tcp
sudo firewall-cmd --reload
⚠️ 别忘了去云厂商控制台的安全组里同样放行 7000 和 6000。
前台启动测试(先跑通再配 systemd):
bash
/opt/frp/frps -c /etc/frp/frps.toml
# 看到 "frps started successfully" 即成功,Ctrl+C 停止
第 2 步:客户端(内网机器)
创建或打开frpc.toml,例如配置文件在
/etc/frp/frpc.toml
bash
sudo mkdir -p /etc/frp
sudo cat /etc/frp/frpc.toml
# 核对以下格式与配置
serverAddr = "1.2.3.4" # 换成你的公网服务器 IP
serverPort = 7000
auth.method = "token"
auth.token = "MyStr0ng_Token_ChangeMe_2026" # 必须与服务端一致
[[proxies]]
name = "home-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
# 使用nano或vi进行修改
sudo nano /etc/frp/frpc.toml
启动:
bash
/opt/frp/frpc -c /etc/frp/frpc.toml
# 日志出现 "login to server success" 和 "start proxy success" 即成功
第 3 步:验证
bash
ssh -oPort=6000 用户名@1.2.3.4
能登录就说明隧道通了
第 4 步:配置为 systemd 服务(开机自启)
服务端 /etc/systemd/system/frps.service:
ini
[Unit]
Description=frp server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/opt/frp/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=5s
StartLimitIntervalSec=60
StartLimitBurst=3
LimitNOFILE=1048576
# 安全加固(可选)
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
[Install]
WantedBy=multi-user.target
bash
sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo systemctl status frps
客户端 /etc/systemd/system/frpc.service:
ini
[Unit]
Description=frp client
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/opt/frp/frpc -c /etc/frp/frpc.toml
ExecReload=/opt/frp/frpc reload -c /etc/frp/frpc.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
bash
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo journalctl -u frpc -f # 实时看日志
Windows 开机自启
方式 1:任务计划程序(无需额外软件)
- 打开"任务计划程序" → "创建基本任务"
- 触发器:计算机启动时
- 操作:启动程序
- 程序:
C:\frp\frpc.exe - 参数:
-c C:\frp\frpc.toml - 起始于:
C:\frp
- 程序:
- 勾选"不管用户是否登录都要运行"
方式 2:WinSW(更稳,支持日志和自动重启)
下载 WinSW,在同目录放 frpc-service.xml:
xml
<service>
<id>frpc</id>
<name>frp client</name>
<description>frp 内网穿透客户端</description>
<executable>C:\frp\frpc.exe</executable>
<arguments>-c C:\frp\frpc.toml</arguments>
<logmode>roll</logmode>
<onfailure action="restart" delay="5 sec"/>
</service>
然后 winsw install → winsw start。
服务端 frps 详解
推荐的完整生产配置
/etc/frp/frps.toml:
toml
# ============ 基础 ============
bindAddr = "0.0.0.0"
bindPort = 7000
# 也可改成非默认端口(如 17000)降低被扫描概率
# ============ 认证 ============
auth.method = "token"
auth.token = "用 openssl rand -hex 32 生成的一串随机串"
# ============ Dashboard 管理面板 ============
webServer.addr = "0.0.0.0" # 公网可访问;若只本地看就保持 127.0.0.1
webServer.port = 7500
webServer.user = "admin"
webServer.password = "强密码"
# 如需 HTTPS 访问面板:
# webServer.tls.certFile = "/etc/frp/certs/server.crt"
# webServer.tls.keyFile = "/etc/frp/certs/server.key"
# ============ 传输加密 ============
transport.tls.force = true # 强制所有客户端必须使用 TLS 连接
# ============ 端口管控 ============
allowPorts = [
{ single = 6000 },
{ single = 6001 },
{ start = 6100, end = 6199 },
]
maxPortsPerClient = 10 # 限制单个客户端最多创建 10 个代理
# ============ HTTP/HTTPS 虚拟主机 ============
vhostHTTPPort = 80
vhostHTTPSPort = 443
subDomainHost = "frp.example.com" # 泛子域名,需 *.frp.example.com 解析到本服务器
# ============ 日志 ============
log.to = "/var/log/frp/frps.log"
log.level = "info" # trace/debug/info/warn/error
log.maxDays = 7
log.disablePrintColor = true # 写文件时关闭颜色,避免 ANSI 转义符
使用前准备:
bash
sudo mkdir -p /var/log/frp
/opt/frp/frps verify -c /etc/frp/frps.toml # 校验配置,输出 ok 才启动
生成强 Token
bash
openssl rand -hex 32
从 v0.64.0 起支持从文件读取 token,避免密钥明文写进配置文件:
bash
sudo sh -c 'umask 027; openssl rand -hex 32 > /etc/frp/server_token'
sudo chmod 640 /etc/frp/server_token
toml
auth.method = "token"
auth.tokenSource.type = "file"
auth.tokenSource.file.path = "/etc/frp/server_token"
auth.token与auth.tokenSource互斥,二选一,不能同时配置。
关键参数说明
| 参数 | 默认值 | 说明 |
|---|---|---|
bindAddr |
0.0.0.0 |
监听地址 |
bindPort |
7000 |
控制通道端口 |
vhostHTTPPort |
无 | HTTP 类型代理共用的入口端口 |
vhostHTTPSPort |
无 | HTTPS 类型代理共用的入口端口 |
tcpmuxHTTPConnectPort |
无 | tcpmux 类型代理复用端口 |
subDomainHost |
无 | 泛域名后缀,配合客户端 subdomain 使用 |
auth.method |
token |
认证方式,另有 oidc |
auth.token |
无 | 认证密钥 |
transport.tls.force |
false |
强制客户端启用 TLS |
allowPorts |
全部 | 限制客户端可申请的 remotePort 范围 |
maxPortsPerClient |
0(不限) |
单客户端最大代理数 |
webServer.* |
无 | Dashboard 配置 |
log.to |
console |
日志输出,可写文件路径 |
log.level |
info |
日志级别 |
log.maxDays |
3 |
日志保留天数 |
校验与启动
bash
# 校验语法(强烈建议每次改配置后先跑)
/opt/frp/frps verify -c /etc/frp/frps.toml
# 输出:frps: the configuration file /etc/frp/frps.toml syntax is ok
# 关闭严格模式(有自定义字段时才需要)
/opt/frp/frps verify -c /etc/frp/frps.toml --strict-config=false
# 重载 / 重启
sudo systemctl restart frps
注意 :
frps不支持热重载全局配置,改完配置需restart。只有frpc支持reload。
客户端 frpc 详解
完整示例
/etc/frp/frpc.toml:
toml
# ============ 连接服务端 ============
serverAddr = "1.2.3.4"
serverPort = 7000
user = "home-nas" # 不同客户端用不同 user,避免代理名冲突
# ============ 认证 ============
auth.method = "token"
auth.token = "MyStr0ng_Token_ChangeMe_2026"
# ============ 传输 ============
transport.tls.enable = true # 服务端开了 force 时必须开
transport.protocol = "tcp" # 可选 tcp / kcp / quic / websocket / wss
# ============ 本机管理界面(可选)============
webServer.addr = "127.0.0.1"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "admin"
# ============ 日志 ============
log.to = "/var/log/frp/frpc.log"
log.level = "info"
log.maxDays = 3
# ============ 代理规则 ============
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
[[proxies]]
name = "nas-web"
type = "http"
localIP = "127.0.0.1"
localPort = 5000
customDomains = ["nas.example.com"]
代理(proxy)通用字段
| 字段 | 说明 |
|---|---|
name |
代理唯一名称,同一客户端内不可重复 |
type |
tcp/udp/http/https/stcp/sudp/xtcp/tcpmux |
localIP |
本地服务 IP,可填局域网内其他机器(如 192.168.1.50) |
localPort |
本地服务端口 |
remotePort |
服务端暴露的端口(http/https/stcp/xtcp 不需要) |
customDomains |
自定义域名(http/https) |
subdomain |
子域名,配合服务端 subDomainHost |
transport.bandwidthLimit |
限速,如 "1MB"、"500KB" |
transport.bandwidthLimitMode |
client(默认)或 server |
healthCheck.* |
健康检查,失败则摘除该代理 |
loadBalancer.group / groupKey |
同组负载均衡 |
metadatas.* |
自定义元数据,传给服务端插件 |
localIP不只能填127.0.0.1。把 frpc 装在家庭网关/一台常开的机器上,localIP填192.168.1.x,就能穿透局域网里任意一台设备的服务------这是非常实用的技巧。
配置校验与热加载
bash
# 校验
/opt/frp/frpc verify -c /etc/frp/frpc.toml
# 热加载(需开启 webServer 管理端口)
/opt/frp/frpc reload -c /etc/frp/frpc.toml
# 通过 systemd 热加载
sudo systemctl reload frpc
热加载的边界:
proxies的增删改、visitors 变更等大部分内容 可以热更新;serverAddr、serverPort、auth等连接层参数不支持热更新,需重启。
配置拆分(includes)
代理多了以后,一个文件会很长。可以拆分:
toml
# /etc/frp/frpc.toml
serverAddr = "1.2.3.4"
serverPort = 7000
auth.method = "token"
auth.token = "xxx"
includes = ["/etc/frp/confd/*.toml"]
toml
# /etc/frp/confd/ssh.toml
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
toml
# /etc/frp/confd/web.toml
[[proxies]]
name = "web"
type = "http"
localPort = 8080
customDomains = ["dev.example.com"]
被 include 的文件只能包含代理配置,公共参数必须留在主配置文件。
环境变量模板(避免明文密钥)
toml
serverAddr = "{{ .Envs.FRP_SERVER_ADDR }}"
serverPort = 7000
auth.token = "{{ .Envs.FRP_TOKEN }}"
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = {{ .Envs.FRP_SSH_REMOTE_PORT }}
bash
export FRP_SERVER_ADDR="1.2.3.4"
export FRP_TOKEN="xxxx"
export FRP_SSH_REMOTE_PORT="6000"
/opt/frp/frpc -c /etc/frp/frpc.toml
systemd 里配合 EnvironmentFile=/etc/frp/frpc.env 使用,密钥不落进配置文件。
实战场景配置集
远程桌面(Windows RDP)
服务端无需改动(确认 7000 和 63389 已放行)。
客户端 frpc.toml(运行在被控 Windows 上):
toml
serverAddr = "1.2.3.4"
serverPort = 7000
auth.method = "token"
auth.token = "xxx"
[[proxies]]
name = "rdp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3389
remotePort = 63389
transport.bandwidthLimit = "2MB" # 可选:限速,避免占满服务器带宽
连接:mstsc → 1.2.3.4:63389
🔒 安全建议:RDP 直接裸奔公网风险很高。更推荐用 8.5 的 stcp 方式,或先连 VPN/Tailscale 再 RDP。至少也要保证 Windows 账户是强密码 + 开启网络级别身份验证(NLA)。
暴露本地 Web 服务(HTTP)
服务端:
toml
bindPort = 7000
vhostHTTPPort = 8080 # 若用 80,注意别和已有 Nginx 冲突
客户端:
toml
serverAddr = "1.2.3.4"
serverPort = 7000
auth.method = "token"
auth.token = "xxx"
[[proxies]]
name = "dev-web"
type = "http"
localIP = "127.0.0.1"
localPort = 3000
customDomains = ["dev.example.com"]
DNS :把 dev.example.com 的 A 记录解析到 1.2.3.4(或 CNAME 到服务器已有域名)。
访问:http://dev.example.com:8080
若
vhostHTTPPort = 80,直接http://dev.example.com即可。
泛子域名(subdomain)
适合多人共用一台 frps,每人一个子域名,不用每次都改 DNS。
DNS :添加一条泛解析 *.frp.example.com A → 1.2.3.4
服务端:
toml
bindPort = 7000
vhostHTTPPort = 80
subDomainHost = "frp.example.com"
客户端:
toml
[[proxies]]
name = "my-blog"
type = "http"
localPort = 4000
subdomain = "alice" # 最终访问 alice.frp.example.com
HTTPS 加密访问
三种方案,按需选择:
https2http 插件(frp 侧终止 TLS,最省事)
本地是 HTTP 服务,想让外网用 HTTPS 访问:
toml
# 客户端
[[proxies]]
name = "web-https"
type = "https"
customDomains = ["dev.example.com"]
[proxies.plugin]
type = "https2http"
localAddr = "127.0.0.1:8080" # 本地 HTTP 服务
crtPath = "/etc/frp/certs/dev.example.com/fullchain.pem"
keyPath = "/etc/frp/certs/dev.example.com/privkey.pem"
hostHeaderRewrite = "127.0.0.1"
requestHeaders.set.x-from-where = "frp"
服务端只需 vhostHTTPSPort = 443。证书可以用 Let's Encrypt / 各家免费证书。
Nginx / Caddy 反向代理(推荐生产用)
frp 只做 HTTP 转发,TLS 交给服务器上的 Nginx/Caddy,证书自动续期,还能统一加鉴权、WAF、限流。
Caddy 示例(Caddyfile):
caddyfile
dev.example.com {
reverse_proxy 127.0.0.1:8080 # 8080 即 frps 的 vhostHTTPPort
}
Caddy 会自动申请并续期证书。
本地已是 HTTPS 服务
toml
[[proxies]]
name = "web"
type = "https"
localPort = 443
customDomains = ["dev.example.com"]
服务端配 vhostHTTPSPort = 443。
安全暴露服务:stcp(强烈推荐用于 SSH / RDP / 数据库)
stcp 让服务完全不在公网监听端口 ,只有持有相同 secretKey 的另一个 frpc 才能访问。
服务端 :无需特殊配置,bindPort = 7000 即可。
被访问端(内网机器 A):
toml
serverAddr = "1.2.3.4"
serverPort = 7000
auth.method = "token"
auth.token = "xxx"
[[proxies]]
name = "secret_ssh"
type = "stcp"
secretKey = "a-very-long-secret-key"
localIP = "127.0.0.1"
localPort = 22
# allowUsers = ["*"] # 允许哪些 user 访问,默认只允许同 user
访问端(你的笔记本 B):
toml
serverAddr = "1.2.3.4"
serverPort = 7000
auth.method = "token"
auth.token = "xxx"
[[visitors]]
name = "secret_ssh_visitor"
type = "stcp"
serverName = "secret_ssh" # 对应对端的 proxies.name
secretKey = "a-very-long-secret-key"
bindAddr = "127.0.0.1"
bindPort = 6000
连接:
bash
ssh -oPort=6000 user@127.0.0.1
这样公网服务器上没有任何暴露的业务端口,安全性比 tcp 直暴露高一个量级。代价是访问端也必须装 frpc。
sudp 用法相同,用于 UDP 服务。
P2P 点对点穿透:xtcp
流量不经过服务器,适合大流量传输(如远程看 NAS 视频)。
被访问端:
toml
[[proxies]]
name = "p2p_ssh"
type = "xtcp"
secretKey = "abcdefg"
localIP = "127.0.0.1"
localPort = 22
访问端:
toml
[[visitors]]
name = "p2p_ssh_visitor"
type = "xtcp"
serverName = "p2p_ssh"
secretKey = "abcdefg"
bindAddr = "127.0.0.1"
bindPort = 6000
keepTunnelOpen = false # true = 常保持隧道打开
maxRetriesAnHour = 8
minRetryInterval = 90
# fallbackTo = "secret_ssh_visitor" # 打洞失败时回退到 stcp
# fallbackTimeoutMs = 500
xtcp 依赖 NAT 打洞,成功率不是 100% (对称型 NAT、多层 NAT 常常失败)。失败时 frp 会自动回退到 stcp 中转(需配置
fallbackTo),所以建议同时配置一个 stcp 代理作为兜底。若默认 STUN 服务器不可用,可配置
natHoleStunServer = "stun.xxx:3478"。
UDP 穿透(DNS / 游戏 / WireGuard)
toml
[[proxies]]
name = "wireguard"
type = "udp"
localIP = "127.0.0.1"
localPort = 51820
remotePort = 51820
UDP 穿透在 NAT 下存在"连接空闲超时"问题,长时间无流量可能被运营商回收映射。可开启
keepTunnelOpen = true(xtcp 场景)或让客户端定期发送保活包。
临时文件共享(static_file 插件)
把本地目录变成带 Basic 认证的静态文件服务:
toml
[[proxies]]
name = "static_file"
type = "tcp"
remotePort = 6006
[proxies.plugin]
type = "static_file"
localPath = "/var/www/blog"
stripPrefix = "static"
httpUser = "abc"
httpPassword = "abc"
访问:http://1.2.3.4:6006/static/
把内网机器变成 SOCKS5 代理
toml
[[proxies]]
name = "socks5"
type = "tcp"
remotePort = 6008
[proxies.plugin]
type = "socks5"
username = "abc"
password = "abc"
这会让你家里/公司的网络出口被复用。仅在自用且授权的场景下使用,务必设置强密码并配合 stcp 使用,不要裸奔在公网。
穿透局域网内其他机器
frpc 装在 192.168.1.2 上,但要穿透 192.168.1.50 的群晖:
toml
[[proxies]]
name = "dsm"
type = "http"
localIP = "192.168.1.50"
localPort = 5000
customDomains = ["nas.example.com"]
运维:日志、热加载、监控
日志查看
bash
# systemd 方式
sudo journalctl -u frps -f # 实时
sudo journalctl -u frps --since "1 hour ago"
sudo journalctl -u frps -n 200
# 文件方式
tail -f /var/log/frp/frps.log
调试时把 log.level 改成 debug(排完记得改回 info)。
端口与连通性检查
bash
# 服务端是否在监听
sudo ss -lntp | grep frps
# 客户端能否连上服务端 7000
nc -vz 1.2.3.4 7000
# 或
telnet 1.2.3.4 7000
# 本地服务是否真的在跑(在内网机器上)
ss -lntp | grep 22
curl -I http://127.0.0.1:8080
Prometheus 监控
toml
# frps.toml
webServer.port = 7500
enablePrometheus = true
指标地址:http://1.2.3.4:7500/metrics
Dashboard
浏览器打开 http://1.2.3.4:7500,可查看:
- 在线客户端、clientID、连接历史
- 各代理的流量统计、连接数
- 服务端系统信息
v0.67.0 起重做了 Dashboard UI,支持暗色模式与更丰富的统计维度。
备份与恢复
建议把 /etc/frp/ 整个目录纳入备份(含 toml、token 文件、systemd 无需备份)。
故障排查速查表
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
dial tcp 1.2.3.4:7000: connect: connection refused |
frps 没启动 / 端口没监听 | systemctl status frps;`ss -lntp |
login to server failed: EOF |
网络不通、安全组未放行、端口被运营商封 | 检查云安全组 + 系统防火墙;nc -vz IP 7000 测试 |
authentication failed / token in login doesn't match... |
两端 token 不一致 | 仔细比对,注意首尾空格、大小写;用文件方式读取可避免手误 |
port already used |
remotePort 被其他代理或程序占用 | 换端口;服务端 `ss -lntp |
proxy name [xxx] is already in use |
同一客户端内代理名重复,或不同客户端 user 相同且重名 | 改名;给不同客户端设不同 user |
proxy [xxx] port is not allowed |
服务端 allowPorts 未放行该端口 |
在 allowPorts 中加入该端口 |
get hostname from http request error |
HTTP 代理缺 customDomains,或用 IP 直接访问 vhost 端口 |
配 customDomains/subdomain,用域名访问 |
连得上但访问超时(connection timeout) |
localIP/localPort 写错,或本地服务没启动 | 在 frpc 所在机器 curl 127.0.0.1:端口 自测 |
| Dashboard 打不开 | webServer.addr 默认是 127.0.0.1 |
改成 0.0.0.0,并放行 7500;检查日志有无 dashboard listen on |
| 服务频繁重启 | systemd StartLimitBurst 触发 / 配置错误 |
journalctl -u frps -n 100 看具体错误 |
| 速度很慢 / 延迟高 | 服务器带宽小、跨运营商、P2P 未成功 | 换离你近的服务器;stcp/xtcp;检查带宽是否跑满 |
| 隔一段时间就断 | 长连接被运营商/防火墙回收 | 服务端适当调小心跳相关参数;或用 transport.protocol = "kcp"/wss 尝试 |
frpc: the configuration file xxx syntax is not ok |
TOML 语法错误 | 用 frpc verify -c 定位;常见是引号/缩进/数组括号问题 |
| 改了配置不生效 | frps 不支持热重载 | systemctl restart frps;frpc 可用 reload |
排查顺序(推荐)
- 服务端:frps 是否 running?端口是否 listen?
- 网络 :客户端
nc -vz 服务端IP 7000通不通?云安全组开了没? - 认证:两端 token 完全一致?
- 本地服务 :frpc 所在机器能否访问
localIP:localPort? - 日志 :两端同时
journalctl -f,日志基本会直接告诉你原因。
进阶特性
负载均衡(同组多实例)
多台内网机器提供同一服务时,frp 会在组内随机分发:
toml
# 机器 A
[[proxies]]
name = "web-a"
type = "http"
localPort = 8080
customDomains = ["app.example.com"]
loadBalancer.group = "web"
loadBalancer.groupKey = "group-secret"
# 机器 B(配置相同,仅 name 不同)
[[proxies]]
name = "web-b"
type = "http"
localPort = 8080
customDomains = ["app.example.com"]
loadBalancer.group = "web"
loadBalancer.groupKey = "group-secret"
健康检查
摘除不健康的后端:
toml
[[proxies]]
name = "web"
type = "http"
localPort = 8080
customDomains = ["app.example.com"]
healthCheck.type = "http"
healthCheck.path = "/status"
healthCheck.intervalSeconds = 10
healthCheck.maxFailed = 3
healthCheck.timeoutSeconds = 3
TCP 类型用 healthCheck.type = "tcp"。
带宽限速
toml
[[proxies]]
name = "ssh"
type = "tcp"
localPort = 22
remotePort = 6000
transport.bandwidthLimit = "1MB"
transport.bandwidthLimitMode = "client" # client(默认) 或 server
PROXY Protocol(透传真实客户端 IP)
内网服务需要拿到访客真实 IP 时:
toml
[[proxies]]
name = "web"
type = "https"
localPort = 443
customDomains = ["app.example.com"]
transport.proxyProtocolVersion = "v2"
后端(Nginx 等)也必须开启
proxy_protocol支持,否则会报解析错误。
传输协议选择
toml
transport.protocol = "tcp" # 默认
# transport.protocol = "kcp" # 弱网/丢包环境可能更稳,但更耗带宽
# transport.protocol = "quic"
# transport.protocol = "websocket" # 穿越只放行 80/443 的严格防火墙
# transport.protocol = "wss"
VirtualNet(虚拟组网,实验特性)
较新版本支持通过 frp 组建虚拟网络(类似轻量 VPN),需开启 featureGates 并配合 virtual_net 插件。属于新特性,使用前请查阅对应版本文档。
常见参数速查
frps.toml
toml
bindAddr = "0.0.0.0"
bindPort = 7000
vhostHTTPPort = 80
vhostHTTPSPort = 443
tcpmuxHTTPConnectPort = 5002
subDomainHost = "frp.example.com"
auth.method = "token"
auth.token = "xxx"
# auth.tokenSource.type = "file"
# auth.tokenSource.file.path = "/etc/frp/server_token"
transport.tls.force = true
allowPorts = [{ single = 6000 }, { start = 6100, end = 6199 }]
maxPortsPerClient = 10
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin"
enablePrometheus = true
log.to = "/var/log/frp/frps.log"
log.level = "info"
log.maxDays = 7
frpc.toml
toml
serverAddr = "1.2.3.4"
serverPort = 7000
user = "my-client"
auth.method = "token"
auth.token = "xxx"
transport.tls.enable = true
transport.protocol = "tcp"
webServer.addr = "127.0.0.1"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "admin"
log.to = "/var/log/frp/frpc.log"
log.level = "info"
log.maxDays = 3
# --- 代理 ---
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
# --- 访问者(stcp/xtcp)---
[[visitors]]
name = "ssh_visitor"
type = "stcp"
serverName = "ssh"
secretKey = "abcdefg"
bindAddr = "127.0.0.1"
bindPort = 6000
常用命令
| 命令 | 作用 |
|---|---|
frps -c /etc/frp/frps.toml |
启动服务端 |
frpc -c /etc/frp/frpc.toml |
启动客户端 |
frps verify -c <file> |
校验服务端配置 |
frpc verify -c <file> |
校验客户端配置 |
frpc reload -c <file> |
客户端热加载 |
frps --version / frpc -v |
查看版本 |
systemctl restart frps/frpc |
重启 |
journalctl -u frps -f |
实时日志 |
老版本 INI 配置迁移对照
如果你从旧教程迁移过来,对照改即可:
| INI(旧) | TOML(新) |
|---|---|
[common] |
去掉,直接写顶层键值 |
bind_port = 7000 |
bindPort = 7000 |
vhost_http_port |
vhostHTTPPort |
vhost_https_port |
vhostHTTPSPort |
subdomain_host |
subDomainHost |
dashboard_port |
webServer.port |
dashboard_user |
webServer.user |
dashboard_pwd |
webServer.password |
token = "xxx" |
auth.token = "xxx" |
tls_enable = true |
transport.tls.enable = true |
server_addr |
serverAddr |
server_port |
serverPort |
[ssh](代理段) |
[[proxies]] + name = "ssh" |
type = tcp |
type = "tcp"(值要加引号) |
local_ip |
localIP |
local_port |
localPort |
remote_port |
remotePort |
custom_domains |
customDomains = ["a.com", "b.com"] |
sk |
secretKey |
role = visitor |
移到 [[visitors]] 段 |
server_name |
serverName |
完整迁移示例
旧 frpc.ini:
ini
[common]
server_addr = 1.2.3.4
server_port = 7000
token = abc123
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
新 frpc.toml:
toml
serverAddr = "1.2.3.4"
serverPort = 7000
auth.method = "token"
auth.token = "abc123"
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
命名规则:下划线分隔 → 小驼峰;
[[proxies]]/[[visitors]]是 TOML 的数组表语法,每个代理复制一整块。改完务必用
frpc verify -c校验一遍。
附录:完整配置参考
frp 参数众多,完整字段清单请查阅官方示例:
- 服务端完整示例:
https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml - 客户端完整示例:
https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml - 官方文档:
https://gofrp.org/zh-cn/docs/