跳转至

FRP 实战上手:原理、部署、解决什么问题

写在前面

很多运维同学都听过 FRP 这个名字,但真正动手部署过的不多。典型场景:

研发:「我家里跑了个本地服务,想让外面的同事访问。」
运维:「FRP 一下就能搞定。」
研发:「具体怎么搞?」
运维:「……我看一下文档。」

或者面试场景:

面试官:「你们生产环境怎么从云上访问 IDC 内网的服务?」
你:「用 FRP。」
面试官:「能讲一下 FRP 的工作原理吗?穿透 NAT 是怎么做的?」
你:「……」

这篇文章的目标,是让一个没动手部署过 FRP 的运维,用一两个小时把"原理 + 部署 + 生产实战 + 面试问答"全部打通

不会展开协议层的所有细节,重点放在:

  • FRP 解决什么问题,跟 OpenVPN/WireGuard/Nginx 反代是什么关系
  • 工作原理(一张图就讲完)
  • 一套最小可用的部署流程(云上 + 内网两端)
  • 常见用法:暴露 HTTP、SSH、MySQL、K8s API
  • 安全加固和生产坑
  • 面试问答

一句话理解 FRP

FRP = 在公网服务器上打个洞,让你内网的服务能从这个洞被外界访问。

更准确点:

内网客户端主动连出到公网服务器建立长连接,外部访问公网服务器某个端口时,流量被反向转发到内网客户端,再转给真正的内网服务。

跟 OpenVPN 的关键区别:

FRP 把"服务"搬到公网;OpenVPN 把"用户"塞进内网。

跟 Nginx 反向代理的关键区别:

Nginx 要求自己能直接连到后端服务,所以后端必须有公网 IP 或在同一网络里;FRP 不要求,它的精髓就是让没有公网 IP 的内网服务也能被访问

它解决什么问题

flowchart LR
    Inet[公网用户] -.访问不到.- Home[家庭/公司内网]
    Home --> Service[内网服务<br/>Web / SSH / MySQL]
    NAT[家用路由器/企业 NAT<br/>没有公网 IP] -.挡住入站.- Inet
    Home --- NAT

家用宽带、办公室网络、IDC 机房都有同样的问题:能主动连出去,但外面进不来。原因是 NAT、运营商不给公网 IP、防火墙默认拒绝入站。

FRP 的解法:在公网租一台便宜云服务器(一年几十块),FRP 客户端在内网主动连这台云服务器,建立一根长连接当成"反向通道"。外面访问云服务器的某个端口时,云服务器把流量沿着这根反向通道送到内网,再转给真实服务。

flowchart LR
    Inet[公网用户] -->|访问 cloud.com:80| Cloud[云服务器<br/>跑 frps]
    Cloud -.反向通道.- Client[内网机器<br/>跑 frpc]
    Client --> Service[内网服务<br/>192.168.1.10:80]

FRP 在远程接入家族里的位置

方案 解决什么 适合
FRP 把内网服务暴露到公网 临时调试、单服务对外、家庭实验室
OpenVPN / WireGuard 把人虚拟接入内网 多人远程办公、要访问大量内网资源
Nginx 反向代理 已经有公网入口的流量分发 同一网络/直连场景的流量编排
Tailscale / Zerotier 自动组网,每台机器互通 个人多设备、小团队

FRP 的定位:轻量、专一、好搭、稳定。最擅长"我有个内网服务,想给少量外部用户访问" 这种场景。

工作原理:一张图讲完

sequenceDiagram
    participant U as 公网用户
    participant S as 公网服务器<br/>frps(端口 7000+暴露端口 80)
    participant C as 内网客户端<br/>frpc
    participant I as 内网真实服务<br/>192.168.1.10:80

    Note over C,S: 启动阶段
    C->>S: 主动建立 TCP 长连接(连 7000)<br/>带 token 鉴权
    S->>C: 鉴权通过 + 注册"暴露 80 端口给 web 服务"

    Note over U,I: 运行时
    U->>S: HTTP 请求 cloud.com:80
    S->>C: 通过反向通道转发请求
    C->>I: 转给本地 192.168.1.10:80
    I->>C: 响应
    C->>S: 响应回送
    S->>U: 返回响应

关键概念:

  • frps(s = server):跑在公网服务器上,它是被连的那一端
  • frpc(c = client):跑在内网,它是主动连出去的那一端
  • 控制连接:frpc 启动后跟 frps 建立的那根 TCP 长连接,平时只用来传控制信令、心跳
  • 数据连接:每来一个外部访问,frps 会通知 frpc 新建一根数据连接来转发数据
  • token 鉴权:frps 和 frpc 共享一个 token,防止任意人连你的 frps 把流量打进来

部署:最小可用流程

下面用最经典的「公网 1 台 + 内网 1 台」过一遍。

1. 在公网服务器装 frps

# 下载(注意选你机器的架构,常见 amd64)
wget https://github.com/fatedier/frp/releases/download/v0.62.1/frp_0.62.1_linux_amd64.tar.gz
tar -xzf frp_0.62.1_linux_amd64.tar.gz
cd frp_0.62.1_linux_amd64

# 把可执行文件和配置放规范位置
install -m 755 frps /usr/local/bin/
mkdir -p /etc/frp
cp frps.toml /etc/frp/frps.toml

/etc/frp/frps.toml(FRP 0.52+ 推荐 TOML 配置):

# frpc 连接 frps 用的端口
bindPort = 7000

# 鉴权 token:frpc 必须配同一个
auth.method = "token"
auth.token = "your-strong-random-token"

# 用 HTTP 端口暴露内网 web 服务(可选)
vhostHTTPPort = 80

# 监控面板(生产不要直接对公网开)
webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin-strong-password"

# 日志
log.to = "/var/log/frps.log"
log.level = "info"
log.maxDays = 7

systemd 单元 /etc/systemd/system/frps.service

[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

启动:

systemctl daemon-reload
systemctl enable --now frps

# 检查端口
ss -tlnp | grep -E "7000|80|7500"

防火墙记得放行 7000(控制连接)和你想暴露的端口(这里是 80)。

2. 在内网机器装 frpc

# 同样下载,把 frpc 放好
install -m 755 frpc /usr/local/bin/
mkdir -p /etc/frp

/etc/frp/frpc.toml

# 公网 frps 的地址
serverAddr = "cloud.example.com"
serverPort = 7000

# 必须和 frps 配同样的 token
auth.method = "token"
auth.token = "your-strong-random-token"

# 暴露一个 TCP 服务(比如 SSH)
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000     # 在公网服务器上开 6000 端口

# 暴露一个 HTTP 网站(用 vhostHTTPPort 复用 80)
[[proxies]]
name = "blog"
type = "http"
localIP = "192.168.1.10"
localPort = 80
customDomains = ["blog.example.com"]   # 域名解析到 frps 服务器

# 暴露 MySQL(高敏感,加密码)
[[proxies]]
name = "mysql"
type = "tcp"
localIP = "192.168.1.20"
localPort = 3306
remotePort = 6306

同样写 systemd unit:

[Unit]
Description=Frp Client Service
After=network.target

[Service]
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml

[Install]
WantedBy=multi-user.target

启动:

systemctl enable --now frpc
journalctl -u frpc -f

3. 验证

# 从外网试 SSH(走公网 frps 的 6000 端口)
ssh -p 6000 user@cloud.example.com

# 浏览器访问 http://blog.example.com(DNS 解析到 cloud.example.com)

# 从外网连 MySQL
mysql -h cloud.example.com -P 6306 -u user -p

通了说明全链路 OK。

几种常见 proxy 类型

type 作用 典型用法
tcp 暴露任意 TCP 端口 SSH、MySQL、Redis、K8s API
udp 暴露 UDP 端口 DNS、游戏服务器
http 复用 80 端口 + 域名分发 多个内网网站
https 复用 443 端口 跟 http 配套
stcp / xtcp 点对点,需要双方都装 frpc 安全场景,不暴露公网端口

stcp(Secret TCP)值得单独讲:它不在 frps 上开公网端口,只有同样持有密钥的 frpc 客户端能从隧道里访问。生产里"我只想让运维自己能从家访问公司内网 K8s API"这种场景非常合适——对外完全不可见

# 内网侧(暴露方)
[[proxies]]
name = "k8s-api"
type = "stcp"
secretKey = "shared-secret-only-ops-knows"
localIP = "10.0.0.1"
localPort = 6443

# 访问方(运维自己电脑也跑一个 frpc)
[[visitors]]
name = "k8s-api-visitor"
type = "stcp"
serverName = "k8s-api"
secretKey = "shared-secret-only-ops-knows"
bindAddr = "127.0.0.1"
bindPort = 16443
# 之后本地 kubectl --server=https://127.0.0.1:16443 就能用

安全加固(生产必做)

裸跑 FRP 几乎等于"在公网开门"。生产里至少做这 6 件事:

  1. 强 token:32 位以上随机串。openssl rand -hex 32
  2. 关闭 dashboard 公网访问webServer.addr = "127.0.0.1",要用就 SSH 隧道连
  3. 限制白名单:用 allowPorts 限定 frpc 能开的远程端口范围,防止被篡改的 frpc 配置乱开端口
  4. TLS 加密控制连接transport.tls.enable = true(双向 TLS 更好)
  5. 防止 frps 被人乱蹭:在 frps 前面挂 iptables/安全组,只放行 7000 给受控的内网公网出口 IP
  6. 暴露的服务本身要有认证:暴露 MySQL 必须强密码,暴露 SSH 强烈建议改用密钥登录、禁 root
# frps.toml 加固示例
bindPort = 7000
auth.method = "token"
auth.token = "your-32-byte-random-token"

allowPorts = [
  { start = 6000, end = 6010 },
  { single = 6306 }
]

transport.tls.force = true
transport.tls.certFile = "/etc/frp/server.crt"
transport.tls.keyFile  = "/etc/frp/server.key"
transport.tls.trustedCaFile = "/etc/frp/ca.crt"

webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "strong-password"

生产里的几种常见用法

用法一:临时让外部访问内网调试服务

研发本地起了一个服务,想让产品经理在外面看一眼。FRP 一行配置 + 5 分钟就能搞定,比运维拖一个公网域名快得多。

用法二:从云上反向访问 IDC 内网

阿里云上的应用想访问公司 IDC 机房的 MySQL。让 IDC 机房的一台机器跑 frpc 主动连阿里云上的 frps,云上应用通过 frps:6306 就能连到 IDC 的 MySQL。省掉拉专线和打通 VPN 的成本

(写这一段就是因为这正是"基于 FRP 搭建混合云远程接入通道"的典型场景。)

用法三:家庭实验室对外

家里跑了 K8s 集群、博客、NAS,想在外面访问。家里没公网 IP,用 FRP + 一台 30/月的云服务器搞定。

用法四:替代向跳板机做端口转发

以前做法是用 SSH 端口转发:ssh -L 16443:k8s-api:6443 jump-host,每次都要先 SSH 上跳板机。用 FRP 的 stcp 模式可以变成永久后台连接 + 本地直接 kubectl

常见故障排查

现象 多半原因
frpc 起不来:login to server failed: i/o timeout 公网 frps 端口 7000 没开放 / 公网安全组没放行
frpc 起不来:auth failed token 不一致
外部访问 frps 端口连不上 frps 安全组没放行远程端口;或 allowPorts 没把这个端口加进去
HTTP 类型 proxy 不通 域名解析没指到 frps,或 frps 没开 vhostHTTPPort
偶尔断流 frps/frpc 心跳超时;调大 transport.heartbeatTimeout
流量异常增大 可能 token 泄露被人滥用了 → 立刻换 token + 检查 dashboard 流量

调试命令:

# frps 日志
tail -f /var/log/frps.log

# frpc 日志
journalctl -u frpc -f

# 看连接状态(dashboard)
curl -u admin:admin-password http://127.0.0.1:7500/api/proxy/tcp

# 抓控制连接包
tcpdump -i any tcp port 7000 -nn

面试可能被问到的点(重点)

Q1:FRP 和 OpenVPN 有什么区别?

  • FRP 暴露服务:内网服务被反向代理到公网某个端口,访问方拿到的是公网入口
  • OpenVPN 接入用户:用户连上 VPN 后获得内网 IP,可以访问内网所有可达资源
  • 选型:少量服务对外、临时调试 → FRP;多人远程办公、要访问大量内网服务 → OpenVPN/WireGuard

Q2:FRP 怎么实现 NAT 穿透的?

不靠 NAT 穿透,而是靠"内网主动连出"。NAT 默认允许出向连接,所以 frpc 能连出去;连接建立后双向数据都走这根已建立的连接,不需要 NAT 设备允许入向。这跟 STUN/UDP 打洞那类真正的穿透技术不一样。

Q3:你怎么保证 FRP 通道的安全?

至少 4 件事:

  • 强 token + TLS 加密控制连接
  • 限制 frps 暴露端口范围(allowPorts
  • 暴露的服务本身有认证(密码、密钥、白名单)
  • 用 stcp 模式让通道对公网完全不可见,只有持密钥的访问方能进来

Q4:FRP 和 Nginx 反向代理什么区别?

Nginx 必须能直接连到后端,所以后端要么有公网 IP,要么和 Nginx 在同一网络;FRP 不要求,靠"内网主动连出"打反向通道。两者其实是配合的——很多生产里 frps 上层挂 Nginx 做 TLS 卸载和域名分发,frps 只负责跨网通道。

Q5:FRP 适合做生产高并发流量入口吗?

不适合。FRP 设计偏轻量,单实例几千并发没问题,做主流量入口(每秒几万 QPS)就力不从心了,且单点风险高。生产高流量场景应该上专线 / VPC 互联 / 云厂商提供的网关。FRP 适合:内部工具访问、调试通道、小流量服务暴露、家庭实验室。

Q6:stcp 模式相比 tcp 模式的核心优势?

tcp 模式在 frps 上开一个公网端口,全网可见,任何人都能尝试连接(拼的就是后端服务自己的认证强度)。stcp 模式 frps 上不开任何公网端口,访问方也必须装 frpc 并持有密钥才能进入隧道——不可见 = 不可被扫描 = 不可被穷举。运维内部通道首选 stcp。

Q7:FRP 高可用怎么做?

  • frps 单点是大问题,可以多节点 + DNS 轮询 / 公网 LB
  • frpc 端配置多 frps 地址自动 failover
  • 监控告警:dashboard /api/proxy/... 接口拉指标进 Prometheus
  • 配置版本化、一键下发,避免手改 frpc 出错

一句话总结

FRP = 在公网租一台机器开一个"反向门",让你内网的服务能从这扇门被外界访问,靠的是"内网主动连出 + 长连接反向转发",不靠 NAT 穿透

把「为什么要它、它和 OpenVPN/Nginx 的差异、token+TLS+stcp 安全模型、生产用法」这四块讲清楚,面试这块基本不会被卡。