frp - 开源高性能内网穿透神器

6 阅读8分钟

背景

在日常开发和运维工作中,我们经常会遇到这样的场景:

  • 在家需要访问公司内网的开发服务器
  • 需要将本地开发的小程序或 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)  │
                                        └─────────────┘
  1. frps (Server): 部署在有公网 IP 的服务器上,作为中转桥梁
  2. frpc (Client): 部署在需要暴露的内网机器上,建立到 frps 的连接
  3. 用户通过访问 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.comapi.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_proxyHTTP 代理
socks5SOCKS5 代理
static_file静态文件服务器
https2httpHTTPS 转 HTTP
https2httpsHTTPS 转 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: 如何保证传输安全?

  1. 启用 TLS 加密 (transport.tls.enable = true)
  2. 使用 Token 或 OIDC 认证
  3. 对敏感服务使用 STCP 模式 + 预共享密钥
  4. 使用 HTTP Basic Auth 保护 Web 服务

Q5: 连接不稳定怎么办?

  1. 检查服务器防火墙是否放行端口
  2. 尝试更换传输协议 (TCP → KCP/QUIC)
  3. 启用连接池和 TCP 流复用
  4. 检查网络 NAT 类型是否限制穿透

总结

frp 是一款功能强大、配置灵活的内网穿透工具,具有以下核心优势:

优势说明
✅ 完全可控自建服务,数据完全自主掌控
✅ 高性能支持 KCP/QUIC 加速,TCP 流复用
✅ 多协议TCP、UDP、HTTP、HTTPS、SOCKS5
✅ 安全可靠TLS 加密、Token/OIDC 认证
✅ 功能丰富负载均衡、健康检查、热更新
✅ 易于使用配置文件简洁,学习成本低
✅ 活跃社区97K+ Star,持续迭代更新

无论是远程访问家庭设备、暴露开发环境,还是搭建私有 VPN,frp 都能提供稳定、高效的解决方案。建议有相关需求的读者部署自己的 frp 服务,享受完全自主的内网穿透体验。


相关资源


如果你觉得这个工具对你有帮助,欢迎关注我们的更多技术分享。