一、frp 简介
frp 是一个高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议,能够帮助用户轻松实现内网穿透。它的核心思想是将内网服务通过一台具有公网 IP 的服务器暴露出去,流量经过服务器转发或通过 P2P 直连。
项目地址 :https://github.com/fatedier/frp
主要特性:
-
支持多种代理类型(TCP、UDP、HTTP、HTTPS、STCP、XTCP)
-
支持负载均衡、健康检查
-
提供身份验证和 TLS 加密
-
支持 P2P 点对点穿透(XTCP)
-
提供可视化仪表盘,便于监控
组件说明:
-
frps:服务端程序,部署在具有公网 IP 的服务器上
-
frpc:客户端程序,部署在需要穿透的内网机器上
二、基础环境搭建
2.1 准备工作
-
一台具有公网 IP 的服务器(VPS 或云主机)
-
内网中需要暴露服务的目标机器
-
从 GitHub Releases 下载对应系统架构的最新版本
注意:目前 frp 已全面采用 TOML 格式作为配置文件,取代了旧版的 INI 格式。本文基于 v0.60.0 及以上版本编写 。
2.2 服务端部署(公网服务器)
下载并解压 frp:
wget https://github.com/fatedier/frp/releases/download/v0.60.0/frp_0.60.0_linux_amd64.tar.gz
tar -xzvf frp_0.60.0_linux_amd64.tar.gz
cd frp_0.60.0_linux_amd64
编辑服务端配置文件 frps.toml :
# frps.toml
bindPort = 7000 # 服务端监听端口,客户端通过此端口连接
auth.method = "token" # 认证方式
auth.token = "your-strong-token" # 客户端连接密码
# 可选:开启仪表盘监控
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin"
# 如需支持 HTTP/HTTPS 穿透,需设置以下端口
vhostHTTPPort = 80
vhostHTTPSPort = 443
启动服务端:
./frps -c frps.toml
# 后台运行(使用 screen 或 systemd)
# 或直接使用 nohup
nohup ./frps -c frps.toml &
防火墙放行端口(以 Ubuntu 为例):
ufw allow 7000/tcp # frp 通信端口
ufw allow 7500/tcp # 仪表盘端口
ufw allow 80/tcp # HTTP 穿透端口
ufw allow 443/tcp # HTTPS 穿透端口
如果是云服务器,还需在安全组中放行相应端口 。
2.3 客户端部署(内网机器)
在内网目标机器上下载对应版本的 frp,然后编辑客户端配置文件 frpc.toml。
基础配置示例 :
# frpc.toml
serverAddr = "your-server-ip" # 公网服务器 IP 或域名
serverPort = 7000 # 与服务端 bindPort 一致
auth.method = "token"
auth.token = "your-strong-token" # 与服务端 token 一致
# 定义代理规则(将在后续章节详细说明)
# [[proxies]]
# name = "proxy-name"
# type = "tcp"
# localIP = "127.0.0.1"
# localPort = 22
# remotePort = 6000
启动客户端:
./frpc -c frpc.toml
# 或后台运行
nohup ./frpc -c frpc.toml &
三、核心代理类型详解
frp 支持多种代理类型,适用于不同场景。下面逐一介绍每种类型的使用方法。
3.1 TCP 代理:暴露 SSH、RDP 等服务
TCP 是最基础的代理类型,适用于任何基于 TCP 的协议。以暴露内网 SSH 服务为例 :
客户端配置 (frpc.toml):
serverAddr = "your-server-ip"
serverPort = 7000
auth.token = "your-strong-token"
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000 # 公网服务器上监听的端口
配置说明:
-
localIP和localPort:内网服务的地址和端口 -
remotePort:公网服务器上开放的端口,访问此端口即相当于访问内网的localPort
访问方式:
ssh -p 6000 username@your-server-ip
类似地,可以暴露 RDP 服务(Windows 远程桌面):
[[proxies]]
name = "rdp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3389
remotePort = 7001
访问时使用 mstsc 连接 your-server-ip:7001 即可 。
3.2 UDP 代理:转发 DNS、游戏流量等
UDP 代理配置与 TCP 类似,只需将 type 改为 udp。
示例:暴露内网 DNS 服务:
[[proxies]]
name = "dns"
type = "udp"
localIP = "192.168.1.100"
localPort = 53
remotePort = 5353
3.3 HTTP/HTTPS 代理:暴露 Web 服务
HTTP 代理支持域名路由,可以通过不同域名访问不同的内网 Web 服务 。
服务端配置 (frps.toml) 需开启虚拟主机端口:
bindPort = 7000
vhostHTTPPort = 80 # 开启 HTTP 支持
vhostHTTPSPort = 443 # 开启 HTTPS 支持
客户端配置:暴露内网 Web 服务(假设运行在 80 端口)
[[proxies]]
name = "web"
type = "http"
localPort = 80
localIP = "127.0.0.1"
customDomains = ["www.your-domain.com"] # 绑定的域名
访问方式 :
将域名 www.your-domain.com 解析到公网服务器 IP,浏览器访问 http://www.your-domain.com 即可到达内网 Web 服务 。
HTTPS 配置 :如果需要 HTTPS,可以使用 type = "https" 配合插件将 HTTPS 转为 HTTP :
[[proxies]]
name = "web-https"
type = "https"
customDomains = ["www.your-domain.com"]
[proxies.plugin]
type = "https2http"
localAddr = "127.0.0.1:80"
crtPath = "./server.crt" # 证书路径
keyPath = "./server.key" # 私钥路径
hostHeaderRewrite = "127.0.0.1"
requestHeaders.set.x-from-where = "frp"
3.4 STCP 代理:安全的 TCP 服务暴露
STCP (Secret TCP) 用于需要安全访问的场景,只有部署了 frpc 的授权用户才能访问服务 。
适用场景:数据库管理、内部管理系统等不希望直接暴露在公网的服务。
第一步:在服务提供方(内网服务器)配置 frpc.toml:
serverAddr = "your-server-ip"
serverPort = 7000
auth.token = "your-strong-token"
[[proxies]]
name = "secret_mysql"
type = "stcp"
secretKey = "my-secret-key" # 共享密钥,访问方需相同
localIP = "127.0.0.1"
localPort = 3306 # MySQL 服务端口
第二步:在访问方机器上配置 frpc.toml :
serverAddr = "your-server-ip"
serverPort = 7000
auth.token = "your-strong-token"
[[visitors]]
name = "secret_mysql_visitor"
type = "stcp"
serverName = "secret_mysql" # 对应服务端的 proxy name
secretKey = "my-secret-key" # 密钥需一致
bindAddr = "127.0.0.1"
bindPort = 3307 # 本地监听端口
访问方式 :
在访问方机器上,连接本地的 127.0.0.1:3307 即可访问内网的 MySQL 服务:
mysql -h 127.0.0.1 -P 3307 -u root -p
STCP 的特点:服务不直接暴露在公网,只有持有正确 secretKey 的客户端才能访问,大大提高了安全性 。
3.5 XTCP 代理:P2P 点对点穿透
XTCP 是 frp 的一大亮点,它尝试在双方之间建立直接的 P2P 连接。一旦打洞成功,后续流量将不再经过 frp 服务器,大幅提升传输速度且不受服务器带宽限制 。
适用场景:大文件传输、视频流、远程桌面等高带宽需求场景。
注意事项:XTCP 并非适用于所有 NAT 类型,如果打洞失败,会自动降级为 STCP 模式 。
第一步:服务提供方配置 :
serverAddr = "your-server-ip"
serverPort = 7000
# 如果默认 STUN 服务器不可用,可自定义
# natHoleStunServer = "stun.qq.com:3478"
[[proxies]]
name = "p2p_ssh"
type = "xtcp"
secretKey = "abcdefg"
localIP = "127.0.0.1"
localPort = 22
第二步:访问方配置 :
serverAddr = "your-server-ip"
serverPort = 7000
[[visitors]]
name = "p2p_ssh_visitor"
type = "xtcp"
serverName = "p2p_ssh"
secretKey = "abcdefg"
bindAddr = "127.0.0.1"
bindPort = 6000
# 如果需要自动保持隧道打开,设置为 true
# keepTunnelOpen = true
访问方式:
ssh -oPort=6000 user@127.0.0.1
建立连接后,可以通过抓包验证流量是否直接通信(不再经过服务器)。
四、高级功能
4.1 负载均衡与健康检查
当内网有多个相同的服务实例时,可以配置负载均衡 。
服务端配置:无需特殊设置。
客户端配置(多个相同服务的代理):
# 服务实例 A
[[proxies]]
name = "web-a"
type = "tcp"
localIP = "192.168.1.10"
localPort = 80
remotePort = 8000
# 添加健康检查
healthCheck.type = "tcp"
healthCheck.timeoutSeconds = 3
healthCheck.maxFailed = 3
healthCheck.intervalSeconds = 10
# 服务实例 B
[[proxies]]
name = "web-b"
type = "tcp"
localIP = "192.168.1.11"
localPort = 80
remotePort = 8000
healthCheck.type = "tcp"
healthCheck.timeoutSeconds = 3
healthCheck.maxFailed = 3
healthCheck.intervalSeconds = 10
frp 会自动将请求分发到健康的实例上。
4.2 身份验证与 TLS 加密
Token 验证已在基础配置中展示。
TLS 加密:启用后可以加密 frp 客户端与服务端的通信 。
服务端配置 (frps.toml):
# 启用 TLS
transport.tls.force = true
客户端配置 (frpc.toml):
transport.tls.enable = true
4.3 通过代理连接服务端
如果客户端网络需要经过代理才能访问公网,可以配置代理 :
transport.proxyURL = "socks5://user:pass@proxy-ip:1080"
# 或 HTTP 代理
transport.proxyURL = "http://user:pass@proxy-ip:8080"
4.4 日志配置
[log]
log.to = "console" # 或文件路径,如 "./frpc.log"
log.level = "info" # 日志级别:trace, debug, info, warn, error
log.maxDays = 3 # 日志保留天数
log.disablePrintColor = false