FRP 内网穿透 2020年12月16日 IT Tech 0次评论 1次阅读 1732字数 预计阅读时间5分钟 FRP 内网穿透 ### 写在前面 FRP 是一个开源的反向代理工具,常见用途是:把家里、办公室、NAS、PVE、Docker 容器里的服务,通过一台有公网 IP 的服务器转发出来访问。 它的结构很简单: - `frps`:服务端,部署在有公网 IP 的 VPS 上。 - `frpc`:客户端,部署在内网机器上,比如 NAS、PVE、家里的小主机。 - 内网服务不需要主动暴露公网端口,`frpc` 会主动连接 `frps`,外部访问再由 `frps` 转发回内网。 截至本文重写时,FRP 最新版本是 `v0.69.1`。新版配置已经推荐使用 `TOML / YAML / JSON`,旧版 `INI` 配置仍可用,但官方已经标记为不推荐,后续新功能也主要只在新配置格式里支持。 ### 什么时候适合用 FRP 适合: - 家里没有公网 IP,但想远程访问 NAS、PVE、Home Assistant、SSH、Web 服务。 - VPS 带宽够用,想把多个内网服务统一通过 VPS 转发。 - 想快速搭建一个可控的内网穿透方案,不想依赖第三方 SaaS 隧道。 不太适合: - 对安全要求很高,但又不愿意做鉴权、白名单、反代保护。 - 大流量视频转发,例如长期把 Emby/Jellyfin 全量经 VPS 转发,VPS 带宽和流量账单容易炸。 - 需要极稳定的点对点打洞。`XTCP` 的成功率取决于 NAT 类型,不能当成稳定公网线路用。 我的建议是:**管理后台、SSH、轻量 Web 服务可以用 FRP;大流量媒体服务尽量走直连、IPv6、Tailscale / WireGuard,或者只给自己用。** ### 下载安装 去官方 GitHub Release 页面下载对应系统和架构的压缩包: ```text https://github.com/fatedier/frp/releases ``` Linux AMD64 示例: ```bash cd /opt wget https://github.com/fatedier/frp/releases/download/v0.69.1/frp_0.69.1_linux_amd64.tar.gz tar -zxvf frp_0.69.1_linux_amd64.tar.gz mv frp_0.69.1_linux_amd64 frp ``` 目录里通常会包含: ```text frps # 服务端程序 frpc # 客户端程序 frps.toml # 服务端配置示例 frpc.toml # 客户端配置示例 ``` ### 最小可用配置:穿透 SSH 假设: - VPS 公网 IP:`1.2.3.4` - 内网机器 SSH 端口:`22` - 希望通过 VPS 的 `6000` 端口访问内网 SSH - FRP 控制连接端口:`7000` #### 1. VPS 上配置 frps 创建 `/opt/frp/frps.toml`: ```toml bindPort = 7000 # 建议开启鉴权,不要裸跑。 auth.method = "token" auth.token = "换成一串足够长的随机字符串" ``` 启动测试: ```bash cd /opt/frp ./frps -c ./frps.toml ``` #### 2. 内网机器上配置 frpc 创建 `/opt/frp/frpc.toml`: ```toml serverAddr = "1.2.3.4" serverPort = 7000 auth.method = "token" auth.token = "和 frps.toml 保持一致" [[proxies]] name = "ssh" type = "tcp" localIP = "127.0.0.1" localPort = 22 remotePort = 6000 ``` 启动测试: ```bash cd /opt/frp ./frpc -c ./frpc.toml ``` #### 3. 外部访问 在外部电脑上执行: ```bash ssh -p 6000 用户名@1.2.3.4 ``` 流量路径是: ```text 外部电脑 → VPS:6000 → frps → frpc → 内网机器:22 ``` ### 常用场景:通过域名访问内网 Web 服务 如果要暴露的是 Web 服务,比如内网机器上的 `http://127.0.0.1:8080`,更推荐使用 `type = "http"`,这样多个 Web 服务可以复用一个 HTTP 入口端口,再用域名区分。 #### frps.toml ```toml bindPort = 7000 vhostHTTPPort = 8080 auth.method = "token" auth.token = "换成一串足够长的随机字符串" ``` #### frpc.toml ```toml serverAddr = "1.2.3.4" serverPort = 7000 auth.method = "token" auth.token = "和 frps.toml 保持一致" [[proxies]] name = "nas-web" type = "http" localIP = "127.0.0.1" localPort = 8080 customDomains = ["nas.example.com"] ``` 然后把域名解析到 VPS: ```text nas.example.com → A 记录 → 1.2.3.4 ``` 访问: ```text http://nas.example.com:8080 ``` 注意:FRP 的 HTTP 入口端口由 `vhostHTTPPort` 决定。如果你想直接用 80/443,通常建议前面再放一层 Nginx,由 Nginx 负责证书、HTTPS、Basic Auth、访问控制和反代。 ### HTTPS 怎么处理 这里容易踩坑。 FRP 的 `type = "https"` 并不是让 frps 自动帮你申请证书、终止 TLS。官方文档也说得很清楚:HTTPS 代理要求本地服务本身就是 HTTPS 服务,frps 端不会做 TLS 终止。 我更推荐这两种方式: #### 方案 A:Nginx 终止 HTTPS,再反代到 FRP HTTP 入口 这是我最推荐的方式: ```text 用户 → https://nas.example.com → Nginx:443 → frps vhostHTTPPort → frpc → 内网 HTTP 服务 ``` 好处: - 证书统一由 Nginx / Certbot 管理。 - 可以加 Basic Auth、Cloudflare Access、IP 白名单。 - 日志、限速、安全头都好做。 #### 方案 B:本地服务自己提供 HTTPS,再用 FRP 的 https 类型 适合本地服务本身已经有 HTTPS 证书和配置的情况。 一般家庭自托管里,方案 A 更省心。 ### 用 systemd 后台运行 #### frps.service VPS 上创建 `/etc/systemd/system/frps.service`: ```ini [Unit] Description=frp server After=network.target [Service] Type=simple ExecStart=/opt/frp/frps -c /opt/frp/frps.toml Restart=always RestartSec=5s LimitNOFILE=1048576 [Install] WantedBy=multi-user.target ``` 启用: ```bash systemctl daemon-reload systemctl enable --now frps systemctl status frps --no-pager ``` #### frpc.service 内网机器上创建 `/etc/systemd/system/frpc.service`: ```ini [Unit] Description=frp client After=network-online.target Wants=network-online.target [Service] Type=simple ExecStart=/opt/frp/frpc -c /opt/frp/frpc.toml Restart=always RestartSec=5s LimitNOFILE=1048576 [Install] WantedBy=multi-user.target ``` 启用: ```bash systemctl daemon-reload systemctl enable --now frpc systemctl status frpc --no-pager ``` ### 配置校验 新版 FRP 提供配置校验命令,改配置后建议先跑一遍: ```bash /opt/frp/frps verify -c /opt/frp/frps.toml /opt/frp/frpc verify -c /opt/frp/frpc.toml ``` 看到类似结果就说明语法没问题: ```text frpc: the configuration file ./frpc.toml syntax is ok ``` ### 安全建议 FRP 本身只是通道,真正的安全取决于你暴露了什么服务、有没有鉴权、有没有限制来源。 我建议至少做到下面这些: #### 1. 必须配置 token 不要裸跑: ```toml auth.method = "token" auth.token = "换成一串足够长的随机字符串" ``` 更进一步,可以把 token 放到单独文件,通过 `tokenSource` 读取,避免直接写在配置文件里。 #### 2. 不要直接暴露管理后台 像这些服务不建议裸露公网: - PVE 管理后台 - NAS 管理后台 - 宝塔面板 - qBittorrent / Transmission WebUI - Home Assistant - 路由器管理页 如果确实要暴露,至少套一层: - Nginx Basic Auth - Cloudflare Access - IP 白名单 - WireGuard / Tailscale - 服务自身强密码和 2FA #### 3. 只开放必要端口 VPS 防火墙只放行需要的端口,例如: ```text 7000:frpc 连接 frps 的控制端口 6000:示例 SSH 穿透端口 80/443:Web 入口,由 Nginx 接管 ``` 没用的 dashboard、admin、随机测试端口不要一直开着。 #### 4. 谨慎使用 dashboard FRP 支持 dashboard,但它不应该裸露到公网。建议只监听本机,再通过 SSH 隧道或内网访问。 例如: ```toml webServer.addr = "127.0.0.1" webServer.port = 7500 webServer.user = "admin" webServer.password = "换成强密码" ``` #### 5. HTTP 代理要升级到新版本 FRP `v0.68.1` 修复过一个和 HTTP 代理鉴权相关的问题。如果你使用 `type = "http"`,尤其是配置了 `routeByHTTPUser`、`httpUser`、`httpPassword` 之类功能,建议至少升级到 `v0.68.1` 以上。当前直接用最新版 `v0.69.1` 即可。 #### 6. 注意 v0.69 的 wireProtocol 变化 从 `v0.69.0` 开始,FRP 引入了 `transport.wireProtocol`,用于未来协议演进。 当前默认仍是: ```toml transport.wireProtocol = "v1" ``` 如果你想尝试: ```toml transport.wireProtocol = "v2" ``` 需要注意: - 先升级 `frps`,再升级 `frpc`。 - v2 客户端不能连接旧版 frps。 - SUDP / XTCP 相关场景更要保证两端版本匹配。 - 普通用户现在不必急着改,默认 v1 继续可用。 ### XTCP、STCP 怎么选 FRP 支持 `STCP` 和 `XTCP` 这类更偏私有访问的模式。 简单理解: - `STCP`:更稳定,流量仍经过 frps,但不会直接开放公网端口给所有人访问,需要 visitor 端配合访问。 - `XTCP`:尝试 P2P 打洞,成功后流量不经过 frps,速度可能更好,但成功率取决于双方 NAT 类型,不稳定。 我的建议: ```text 追求稳定:选 STCP 想尝试 P2P:选 XTCP,但必须接受失败和回退 给管理后台用:优先 STCP / VPN,不要裸 TCP 暴露 ``` 新版 XTCP 支持 `fallbackTo`,可以在打洞失败时回退到 STCP visitor。这个思路很好,但配置复杂度也更高,普通用户先把 TCP / HTTP / STCP 用明白就够了。 ### 常见排错 #### frpc 连不上 frps 检查: ```bash systemctl status frps --no-pager systemctl status frpc --no-pager ss -tulpen | grep 7000 ``` 从内网机器测试 VPS 端口: ```bash nc -vz 1.2.3.4 7000 ``` 常见原因: - VPS 防火墙没放行 `7000` - 云服务商安全组没放行 - `serverAddr` 写错 - token 不一致 - frps 没启动 #### 外部访问 remotePort 失败 检查: ```bash ss -tulpen | grep 6000 ``` 确认 frps 是否真的监听了远程端口。还要确认: - frpc 日志里代理是否启动成功 - `remotePort` 有没有被其他服务占用 - VPS 防火墙是否放行对应端口 #### HTTP 域名访问失败 检查: ```bash curl -H 'Host: nas.example.com' http://1.2.3.4:8080 ``` 常见原因: - 域名没有解析到 VPS - `customDomains` 和实际 Host 不一致 - `vhostHTTPPort` 没开放 - 本地服务 `localPort` 写错 - 本地服务只监听了其他地址 ### 我的推荐部署方式 如果是个人 NAS / Homelab,我建议这样搭: ```text 公网 VPS:frps + Nginx + HTTPS + Basic Auth / Access 内网机器:frpc 公网只暴露:80、443、7000,以及少数必要 TCP 端口 管理类服务:尽量不要直接裸露,用 Nginx 鉴权或 VPN 大流量媒体:尽量不要走 FRP,除非 VPS 带宽和流量都够 ``` FRP 很好用,但不要把它当成「开洞神器」随便把内网服务都挂到公网。真正靠谱的做法是:**只暴露必要服务,默认加鉴权,重要后台走 VPN 或访问控制。** ### 参考资料 - FRP 官方文档: - FRP GitHub: - FRP Release: - 配置文件说明: - SSH 穿透示例: - HTTP / HTTPS 说明: - XTCP 说明: 本文由 Derrors 创作,采用 知识共享署名4.0 国际许可协议. 最后编辑时间: 2026年06月19日 13:59.