thumbnail
FRP 内网穿透与代理实战:服务暴露、STCP 与 SOCKS5

FRP 内网穿透与代理流量转发示意图

FRP(Fast Reverse Proxy)是一款专注于内网穿透的高性能反向代理工具。它由两部分组成:

  • frps:部署在具有公网 IP 的服务器上;
  • frpc:部署在内网服务所在机器上,主动连接 frps。

外部访问公网服务器的端口或域名后,流量通过 FRP 隧道转发到内网服务。

1
访问者 → 公网 frps → FRP 隧道 → 内网 frpc → 内网服务

截至 2026 年 6 月 25 日,FRP 最新稳定版为 v0.69.1。当前推荐使用 TOML、YAML 或 JSON 配置;INI 已被弃用,新功能也不会继续支持 INI。

一、什么场景适合用 FRP

使用场景 推荐模式 原因
将内网 TCP 服务映射到公网端口 TCP 最简单直接
转发 DNS、游戏等 UDP 服务 UDP 原生 UDP 转发
多个网站共用公网 80/443 HTTP/HTTPS 按域名路由,不必每个网站占一个端口
只允许指定客户端访问 STCP/SUDP 公网不直接开放业务端口
希望点对点传输、节省 VPS 带宽 XTCP 打洞成功后不经过 frps
将内网机器作为 SOCKS5 出口 TCP + SOCKS5 插件 最简单,公网端口必须限制来源
私有方式使用 SOCKS5 STCP + SOCKS5 插件 公网不直接暴露代理端口
多个内网节点提供同一服务 负载均衡 + 健康检查 单节点故障时自动切换
希望两端像虚拟局域网一样通信 VirtualNet 提供 TUN 层网络通信,但目前仍是 Alpha

FRP 最适合“内网端主动连接公网中转节点,再把服务提供出去”的场景。

以下情况不建议直接使用普通 TCP 公网映射:

  • 数据库、Redis、管理后台等敏感服务;
  • 只允许自己或固定设备访问的服务;
  • 没有认证能力的调试接口;
  • 希望访问多个内网 TCP 服务,而不是几个固定端口。

这些情况应根据访问方式选择 STCP 或 SOCKS5 插件。VirtualNet 能提供 IP 层通信,但当前仍是 Alpha,不建议作为生产方案。

二、从零部署

下载与系统架构对应的压缩包:

1
https://github.com/fatedier/frp/releases

公网服务器保留 frps,内网机器保留 frpc。

1. 服务端基础配置

frps.toml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bindPort = 7000

auth.method = "token"
auth.token = "替换为足够长的随机值"

transport.tls.force = true

allowPorts = [
{ start = 20000, end = 20100 }
]

webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "替换为强密码"

配置说明:

  • bindPort:frpc 连接 frps 的控制端口;
  • auth.token:客户端与服务端共享认证凭据;
  • transport.tls.force:拒绝未使用 TLS 的客户端;
  • allowPorts:限制客户端可以申请的公网端口;
  • Dashboard 只监听 127.0.0.1,不要直接暴露到公网。

FRP 从 v0.50.0 起默认启用 TLS 加密,但默认情况下 frpc 不验证 frps 证书身份。对安全要求较高时,应配置 CA 和服务端证书,而不是只依赖随机证书加密。

生产环境可以使用 tokenSource 从文件加载 Token,避免把密钥直接写入配置:

1
2
auth.tokenSource.type = "file"
auth.tokenSource.file.path = "/etc/frp/server_token"

客户端也配置相同内容,并指向自己的 Token 文件。

2. TCP 端口映射

例如把内网 127.0.0.1:8080 映射到公网 20081。

frpc.toml:

1
2
3
4
5
6
7
8
9
10
11
12
serverAddr = "公网服务器地址"
serverPort = 7000

auth.method = "token"
auth.token = "与服务端一致"

[[proxies]]
name = "internal-web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 20081

访问:

1
http://公网服务器地址:20081

UDP 写法基本相同,只需修改类型:

1
2
3
4
5
6
[[proxies]]
name = "internal-udp"
type = "udp"
localIP = "127.0.0.1"
localPort = 53
remotePort = 20053

3. 按域名发布 Web 服务

公网服务端增加:

1
2
vhostHTTPPort = 80
vhostHTTPSPort = 443

客户端:

1
2
3
4
5
6
[[proxies]]
name = "blog"
type = "http"
localIP = "127.0.0.1"
localPort = 8080
customDomains = ["blog.example.com"]

将 blog.example.com 解析到 frps 公网 IP 后,frps 会根据 HTTP Host 将请求转发到对应客户端。

如果不需要域名路由、请求头处理或 BasicAuth 等 HTTP 功能,直接使用 TCP 类型更简单。

4. 启动和验证

启动前先检查配置:

1
2
./frps verify -c ./frps.toml
./frpc verify -c ./frpc.toml

启动:

1
2
./frps -c ./frps.toml
./frpc -c ./frpc.toml

长期运行建议交给 systemd、Supervisor 或 Windows 服务管理工具,不要依赖临时终端。

三、敏感服务不要直接暴露:使用 STCP

普通 TCP 模式会在 frps 上监听公网端口,任何人都可以尝试连接。

STCP(Secret TCP)不会直接公开业务端口。服务端和访问端都运行 frpc,并使用相同的 secretKey。

服务所在机器

1
2
3
4
5
6
7
8
9
10
serverAddr = "公网服务器地址"
serverPort = 7000
auth.token = "与 frps 一致"

[[proxies]]
name = "private-web"
type = "stcp"
secretKey = "替换为单独的随机密钥"
localIP = "127.0.0.1"
localPort = 8080

访问端

1
2
3
4
5
6
7
8
9
10
11
serverAddr = "公网服务器地址"
serverPort = 7000
auth.token = "与 frps 一致"

[[visitors]]
name = "private-web-visitor"
type = "stcp"
serverName = "private-web"
secretKey = "与服务端一致"
bindAddr = "127.0.0.1"
bindPort = 18080

访问端只需打开:

1
http://127.0.0.1:18080

数据仍然经过 frps 中转,但公网服务器不会直接开放这个业务端口。

STCP 适合:

  • 内网管理后台;
  • 数据库管理工具;
  • 只允许固定设备访问的研发服务;
  • 安全测试中临时建立受控访问入口。

四、使用 FRP 提供受控 SOCKS5

FRP 内置 SOCKS5 客户端插件。只运行 frpc,就能把 frpc 所在机器变成代理出口,不需要再安装 Squid、GOST 等代理服务。

代理出口始终位于运行插件的机器:

1
测试机 → frps → frpc SOCKS5 插件 → 目标地址

有两种发布方式:

发布方式 流程 适用场景
普通 TCP 测试机直接连接 frps:remotePort 临时测试、配置最少
STCP 测试机运行 Visitor,再连接本地端口 不希望公网暴露代理端口

普通 TCP 更直接,但必须同时配置:

  • SOCKS5 用户名和强密码;
  • 云安全组或系统防火墙来源 IP 白名单;
  • frps 的 allowPorts。

FRP Token 只认证 frpc 是否允许接入 frps,不能替代 SOCKS5 用户认证。

STCP 安全性更高,但需要测试机额外运行一个 frpc Visitor。第三节已经给出了 STCP 的完整配置,下面的实战采用普通 TCP,突出最短可用流程。

五、实战:将入口机 A 作为内网代理出口

假设入口机 A:

  • 已获得授权执行权限;
  • 能主动连接公网 frps;
  • 能访问目标内网 10.20.0.0/24。

最直接的做法是让 frpc 在公网服务器上开放一个 SOCKS5 端口:

1
2
3
4
测试机
→ 公网 frps:20080
→ A 上的 frpc SOCKS5 插件
→ 目标内网 10.20.0.0/24

不需要 STCP Visitor,也不需要在测试机运行 frpc。

1. 先确认两个方向都可达

A 必须能连接 frps:

1
nc -vz 公网服务器地址 7000

Windows:

1
Test-NetConnection 公网服务器地址 -Port 7000

A 也必须能访问目标内网服务:

1
2
nc -vz 10.20.0.25 8080
curl -I http://10.20.0.25:8080

第一项失败,frpc 无法上线;第二项失败,即使 SOCKS5 已成功建立,也无法访问目标。

2. 公网 frps

frps.toml:

1
2
3
4
5
6
7
8
9
10
bindPort = 7000

auth.method = "token"
auth.token = "REPLACE_WITH_RANDOM_TOKEN"

transport.tls.force = true

allowPorts = [
{ single = 20080 }
]

启动:

1
2
./frps verify -c ./frps.toml
./frps -c ./frps.toml

公网服务器需要放行:

  • 7000/TCP:A 上的 frpc 连接;
  • 20080/TCP:测试机连接 SOCKS5。

建议分别限制来源:

  • 7000/TCP 只允许 A 的出口公网 IP;
  • 20080/TCP 只允许测试机公网 IP。

如果 A 的出口 IP 不固定,至少应保证 Token 随机、TLS 强制开启;20080/TCP 仍应尽量限制测试机来源。

3. A 上运行 frpc SOCKS5 插件

frpc.toml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
serverAddr = "公网服务器地址"
serverPort = 7000

auth.method = "token"
auth.token = "REPLACE_WITH_RANDOM_TOKEN"

[[proxies]]
name = "internal-socks"
type = "tcp"
remotePort = 20080

[proxies.plugin]
type = "socks5"
username = "audit"
password = "REPLACE_WITH_STRONG_PASSWORD"

启动:

1
2
./frpc verify -c ./frpc.toml
./frpc -c ./frpc.toml

FRP 会在公网服务器的 20080 端口提供 SOCKS5,实际流量出口位于 A。

4. 测试机直接使用公网代理

代理地址:

1
socks5://audit:REPLACE_WITH_STRONG_PASSWORD@公网服务器地址:20080

访问 A 可达的内网 Web 服务:

1
2
curl --proxy socks5h://audit:REPLACE_WITH_STRONG_PASSWORD@公网服务器地址:20080 \
http://10.20.0.25:8080

使用 socks5h 可以让域名在 A 侧解析,适合访问内部域名。

浏览器、Burp Suite 等工具直接设置:

1
2
3
4
Host: 公网服务器地址
Port: 20080
Username: audit
Password: 配置中的密码

需要让不原生支持 SOCKS5 的命令行工具走代理时,可以使用 ProxyChains:

1
2
3
4
5
strict_chain
proxy_dns

[ProxyList]
socks5 公网服务器地址 20080 audit REPLACE_WITH_STRONG_PASSWORD

验证:

1
2
proxychains4 curl http://10.20.0.25:8080
proxychains4 nmap -sT -Pn -n -p 80,443,445,3389 10.20.0.0/24

普通 SOCKS5 主要转发 TCP。经过 ProxyChains 使用 Nmap 时:

  • 使用 TCP Connect 扫描 -sT;
  • 使用 -Pn 跳过 ICMP 主机发现;
  • 使用 -n 避免本地 DNS 干扰;
  • 不要期待 SYN 扫描 -sS、UDP 扫描 -sU 或 ping 正常穿过 SOCKS5。

5. 能访问哪些目标

代理出口在 A,因此范围取决于 A 的网络可达性:

1
2
3
4
5
A 能访问 10.20.0.0/24
→ SOCKS5 可以访问 10.20.0.0/24

A 不能访问 10.30.0.0/24
→ SOCKS5 也不能访问 10.30.0.0/24

如果只有后续主机 B 能访问更深层网段,就需要把同样的 frpc SOCKS5 配置部署到 B。FRP 不会自动增加路由或替代下一层代理出口。

常见故障可以按数据流逐段检查:

现象 检查位置
frpc 无法登录 A → frps:7000、Token、TLS
公网 20080 未监听 frpc 是否注册成功、allowPorts、端口冲突
SOCKS5 认证失败 插件用户名和密码
代理连接成功但目标不通 A → 目标 IP:端口
IP 可访问但内部域名失败 socks5h、proxy_dns、A 的 DNS

实战中只需抓住两条链路:先确认 A → frps,再确认 A → 目标内网。两条都通后再启动 SOCKS5;若只有 B 能访问目标网段,就把 frpc 部署到 B。公网 SOCKS5 端口必须同时使用认证和来源 IP 白名单。

上一篇
下一篇