背景
在日常开发和运维工作中,我们经常会遇到这样的场景:
- 在家需要访问公司内网的开发服务器
- 需要将本地开发的小程序或 Web 应用暴露给外部测试
- 远程访问部署在家庭网络的 NAS 或树莓派
- 将内网的 Windows 远程桌面服务暴露给外部访问
这些场景的共同特点是:你的服务在内网中,没有公网 IP,无法直接从互联网访问。
传统的解决方案包括花生壳、Ngrok 等第三方服务,但它们往往有诸多限制:
| 方案 | 限制 |
|---|---|
| 花生壳 | 免费版带宽有限,需要付费才能获得更多功能 |
| Ngrok | 免费版只能访问随机生成的 URL,不支持自定义域名 |
| 花生壳 | 服务不稳定,安全性无法保证 |
| 商业 VPN | 配置复杂,成本高昂 |
今天要介绍的 frp (Fast Reverse Proxy) 完美解决了这些问题,让你拥有完全可控、稳定、高效的内网穿透系统。
什么是 frp
frp 是一个开源的高性能反向代理工具,通过客户端-服务器架构,将内网服务安全地暴露到公网。
核心特性
| 特性 | 说明 |
|---|---|
| 多协议支持 | 支持 TCP、UDP、HTTP、HTTPS、SOCKS5 等协议 |
| 简单配置 | 仅需一个配置文件即可完成穿透设置 |
| 高性能 | 支持 TCP 流复用、KCP、QUIC 等加速协议 |
| 安全可靠 | 支持 TLS 加密、Token 认证、OIDC 认证 |
| 热更新 | 支持在不重启服务的情况下更新配置 |
| Web 仪表盘 | 提供可视化的服务监控和管理界面 |
| P2P 模式 | 支持点对点直连,大幅降低服务器带宽消耗 |
| 插件扩展 | 提供丰富的插件支持静态文件、HTTP 代理等 |
GitHub 数据
- Star: 97.4K
- 语言: Go
- 协议: Apache-2.0
- 维护: 活跃维护中
工作原理
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 用户端 │ ---> │ frps │ ---> │ frpc │
│ (公网) │ │ (服务器) │ │ (内网) │
└─────────────┘ └─────────────┘ └─────────────┘
│
v
┌─────────────┐
│ 内网服务 │
│ (SSH/Web) │
└─────────────┘
- frps (Server): 部署在有公网 IP 的服务器上,作为中转桥梁
- frpc (Client): 部署在需要暴露的内网机器上,建立到 frps 的连接
- 用户通过访问 frps 的公网地址,间接访问到内网服务
快速开始
安装
从 GitHub Release 页面下载对应平台的二进制文件:
# 下载 (Linux AMD64 为例)
wget https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_amd64.tar.gz
tar -xzf frp_0.61.1_linux_amd64.tar.gz
cd frp_0.61.1_linux_amd64
# 服务器端文件
ls frps*
# 客户端文件
ls frpc*
服务器端配置
编辑 frps.toml:
# frps.toml - 服务器配置
bindPort = 7000 # frpc 连接的端口
# Web 仪表盘 (可选)
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin"
# 允许使用的端口范围 (可选)
allowPorts = [
{ start = 2000, end = 3000 },
{ single = 3001 },
{ start = 4000, end = 50000 }
]
启动服务器:
./frps -c ./frps.toml
客户端配置
编辑 frpc.toml:
# frpc.toml - 客户端配置
serverAddr = "你的服务器IP"
serverPort = 7000
# 认证配置 (与服务器一致)
auth.method = "token"
auth.token = "your_token_here"
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
启动客户端:
./frpc -c ./frpc.toml
SSH 远程访问
配置完成后,即可通过服务器 IP 访问内网 SSH:
ssh -oPort=6000 用户名@服务器IP
核心功能详解
1. HTTP/HTTPS 服务暴露
将内网 Web 服务通过自定义域名暴露到公网:
服务器端配置:
# frps.toml
bindPort = 7000
vhostHTTPPort = 8080
vhostHTTPSPort = 8443
subDomainHost = "example.com"
客户端配置:
# frpc.toml
serverAddr = "x.x.x.x"
serverPort = 7000
[[proxies]]
name = "web"
type = "http"
localPort = 80
customDomains = ["www.example.com"]
[[proxies]]
name = "api"
type = "http"
localPort = 8080
customDomains = ["api.example.com"]
locations = ["/api"]
DNS 配置:
将 www.example.com 和 api.example.com 的 A 记录解析到服务器 IP。
2. 保护敏感服务 (STCP)
对于敏感服务,可以使用 Secret TCP 模式,需要预共享密钥才能访问:
服务端 (机器 B):
# frpc.toml
[[proxies]]
name = "secret_ssh"
type = "stcp"
secretKey = "abcdefg"
localIP = "127.0.0.1"
localPort = 22
访问端 (机器 C):
# frpc.toml
[[visitors]]
name = "secret_ssh_visitor"
type = "stcp"
serverName = "secret_ssh"
secretKey = "abcdefg"
bindAddr = "127.0.0.1"
bindPort = 6000
访问时执行:
ssh -oPort=6000 user@127.0.0.1
3. P2P 直连模式 (XTCP)
用于传输大量数据的场景,数据直接在各户端之间传输,服务器只负责建立连接:
# frpc.toml (被访问端)
[[proxies]]
name = "p2p_ssh"
type = "xtcp"
secretKey = "abcdefg"
localIP = "127.0.0.1"
localPort = 22
# frpc.toml (访问端)
[[visitors]]
name = "p2p_ssh_visitor"
type = "xtcp"
serverName = "p2p_ssh"
secretKey = "abcdefg"
bindAddr = "127.0.0.1"
bindPort = 6000
4. TCP 端口复用
多个 SSH 服务共享同一端口,通过域名区分:
服务器端:
# frps.toml
bindPort = 7000
tcpmuxHTTPConnectPort = 5002
机器 A:
# frpc.toml
[[proxies]]
name = "ssh1"
type = "tcpmux"
multiplexer = "httpconnect"
customDomains = ["machine-a.example.com"]
localIP = "127.0.0.1"
localPort = 22
机器 B:
# frpc.toml
[[proxies]]
name = "ssh2"
type = "tcpmux"
multiplexer = "httpconnect"
customDomains = ["machine-b.example.com"]
localIP = "127.0.0.1"
localPort = 22
5. 插件功能
frp 提供丰富的插件扩展:
| 插件 | 用途 |
|---|---|
unix_domain_socket | 暴露 Unix 域套接字 |
http_proxy | HTTP 代理 |
socks5 | SOCKS5 代理 |
static_file | 静态文件服务器 |
https2http | HTTPS 转 HTTP |
https2https | HTTPS 转 HTTPS |
静态文件服务器示例:
[[proxies]]
name = "file_server"
type = "tcp"
remotePort = 6000
[proxies.plugin]
type = "static_file"
localPath = "/tmp/files"
stripPrefix = "static"
httpUser = "admin"
httpPassword = "admin"
6. 负载均衡
支持多个后端服务负载均衡:
[[proxies]]
name = "web1"
type = "tcp"
localPort = 8080
remotePort = 80
loadBalancer.group = "web"
loadBalancer.groupKey = "secret"
[[proxies]]
name = "web2"
type = "tcp"
localPort = 8081
remotePort = 80
loadBalancer.group = "web"
loadBalancer.groupKey = "secret"
7. 健康检查
支持服务健康检查,实现高可用:
[[proxies]]
name = "web"
type = "http"
localIP = "127.0.0.1"
localPort = 80
customDomains = ["web.example.com"]
healthCheck.type = "http"
healthCheck.path = "/status"
healthCheck.timeoutSeconds = 3
healthCheck.maxFailed = 3
healthCheck.intervalSeconds = 10
高级配置
TLS 加密
frp 默认启用 TLS,强制服务器端仅接受 TLS 连接:
# frps.toml
transport.tls.force = true
transport.tls.certFile = "server.crt"
transport.tls.keyFile = "server.key"
KCP 协议加速
使用 KCP 协议可以减少延迟 30-40%:
# frps.toml
bindPort = 7000
kcpBindPort = 7000
# frpc.toml
serverAddr = "x.x.x.x"
serverPort = 7000
transport.protocol = "kcp"
QUIC 协议支持
QUIC 是基于 UDP 的新一代多路复用传输协议:
# frps.toml
bindPort = 7000
quicBindPort = 7000
# frpc.toml
transport.protocol = "quic"
连接池
预建立连接池,减少连接建立时间:
# frps.toml
transport.maxPoolCount = 5
# frpc.toml
transport.poolCount = 2
热更新配置
修改配置后无需重启客户端:
./frpc reload -c ./frpc.toml
端口范围映射
批量创建端口映射:
{{- range $_, $v := parseNumberRangePair "6000-6007" "6000-6007" }}
[[proxies]]
name = "tcp-{{ $v.First }}"
type = "tcp"
localPort = {{ $v.First }}
remotePort = {{ $v.Second }}
{{- end }}
实战场景
场景一:远程访问家中 NAS
假设你有一台群晖 NAS 部署在家庭网络,想要从外部访问:
# NAS 上的 frpc.toml
serverAddr = "你的服务器IP"
serverPort = 7000
[[proxies]]
name = "nasDSM"
type = "tcp"
localIP = "192.168.1.100"
localPort = 5000
remotePort = 5000
[[proxies]]
name = "nasSSH"
type = "tcp"
localIP = "192.168.1.100"
localPort = 22
remotePort = 2222
场景二:暴露本地开发环境
开发微信小程序或需要回调的 Web 应用时使用:
# frpc.toml
serverAddr = "你的服务器IP"
serverPort = 7000
[[proxies]]
name = "web"
type = "https"
customDomains = ["dev.yourdomain.com"]
[proxies.plugin]
type = "https2http"
localAddr = "127.0.0.1:8080"
crtPath = "./server.crt"
keyPath = "./server.key"
hostHeaderRewrite = "127.0.0.1"
场景三:Windows 远程桌面
# frpc.toml
serverAddr = "你的服务器IP"
serverPort = 7000
[[proxies]]
name = "rdp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3389
remotePort = 3389
transport.useEncryption = true
transport.useCompression = true
场景四:搭建 SOCKS5 代理
通过服务器转发网络流量:
[[proxies]]
name = "socks5"
type = "tcp"
remotePort = 1080
[proxies.plugin]
type = "socks5"
httpUser = "user"
httpPassword = "password"
常见问题
Q1: frpc 被杀毒软件误删怎么办?
frp 是网络穿透工具,部分杀毒软件会将其误判为潜在有害程序。请在杀毒软件中将 frpc 添加到白名单。
Q2: 如何选择 TCP/KCP/QUIC 协议?
| 协议 | 适用场景 |
|---|---|
| TCP | 稳定可靠,兼容性最好 |
| KCP | 网络延迟高时,可提升 30-40% 速度 |
| QUIC | 需要低延迟和高吞吐量的场景 |
Q3: frp 和 VPN 有什么区别?
- VPN: 建立虚拟网络,所有流量都走 VPN,适合长期办公场景
- frp: 按需暴露特定端口和服务,资源消耗更小,配置更灵活
Q4: 如何保证传输安全?
- 启用 TLS 加密 (
transport.tls.enable = true) - 使用 Token 或 OIDC 认证
- 对敏感服务使用 STCP 模式 + 预共享密钥
- 使用 HTTP Basic Auth 保护 Web 服务
Q5: 连接不稳定怎么办?
- 检查服务器防火墙是否放行端口
- 尝试更换传输协议 (TCP → KCP/QUIC)
- 启用连接池和 TCP 流复用
- 检查网络 NAT 类型是否限制穿透
总结
frp 是一款功能强大、配置灵活的内网穿透工具,具有以下核心优势:
| 优势 | 说明 |
|---|---|
| ✅ 完全可控 | 自建服务,数据完全自主掌控 |
| ✅ 高性能 | 支持 KCP/QUIC 加速,TCP 流复用 |
| ✅ 多协议 | TCP、UDP、HTTP、HTTPS、SOCKS5 |
| ✅ 安全可靠 | TLS 加密、Token/OIDC 认证 |
| ✅ 功能丰富 | 负载均衡、健康检查、热更新 |
| ✅ 易于使用 | 配置文件简洁,学习成本低 |
| ✅ 活跃社区 | 97K+ Star,持续迭代更新 |
无论是远程访问家庭设备、暴露开发环境,还是搭建私有 VPN,frp 都能提供稳定、高效的解决方案。建议有相关需求的读者部署自己的 frp 服务,享受完全自主的内网穿透体验。
相关资源
- GitHub: github.com/fatedier/fr…
- 官方文档: frp.readthedocs.io/
- 插件仓库: github.com/gofrp/plugi…
如果你觉得这个工具对你有帮助,欢迎关注我们的更多技术分享。