在日常开发中,我们经常会遇到需要将本地服务暴露给外部用户的情况,比如测试同学需要临时测试一个本地开发的 Web 服务,或者希望在出差时远程访问家里的 NAS。这些需求的核心问题都是如何实现内网穿透。
一、为什么选择 frp?
经过对多种工具的尝试,我最终选择了 GitHub 上拥有 93.8k Star 的开源项目 frp。frp 不仅支持全协议,包括 TCP、UDP、HTTP/HTTPS,还通过 P2P 减少服务器中转开销,最重要的是,它是完全开源的,配置灵活,可以根据需求自由调整。接下来,我将从开发者的实用角度出发,带你从零开始掌握 frp 的核心用法。
内网穿透的典型场景包括:
- 本地 Web 服务测试:当你在本地开发了一个 Spring Boot API 服务(端口 8080),需要让身在异地的客户临时测试,但你的设备可能处于运营商 NAT 后或防火墙限制下,无法直接通过公网访问。
- 远程访问 NAS:你有一台放置在家里的 NAS,存储了照片和文档,但出差时希望通过公网访问这些文件,同样面临没有公网 IP 或防火墙限制的问题。
传统解决方案包括:
- 申请公网 IP:成本较高,部分运营商不提供动态公网 IP 地址,需要使用动态 DNS(DDNS)来维护 IP 地址的变更。
- 第三方穿透工具:如 Ngrok(免费版功能受限)、花生壳(收费且流量费用高),关键问题是数据需要经过第三方服务器,安全性存疑。
frp(Fast Reverse Proxy)作为反向代理工具,通过“服务端 + 客户端”模式完美解决了上述问题,并具备以下核心优势:
- 完全开源:代码透明,用户可根据需要自行修改和扩展。
- 协议全面:支持 TCP(如 SSH、数据库)、UDP(如游戏联机)、HTTP/HTTPS(Web 服务)等协议。
- 功能灵活:支持端口复用、负载均衡、P2P 直连(减少服务器流量)、加密压缩(TLS/SSL)等。
- 轻量高效:服务端仅需一个二进制文件,资源占用极低,实测 1 核 1G 的云服务器可支撑数百连接。
二、快速上手:5 分钟实现本地服务公网访问
-
准备工作:
- 一台公网服务器(如阿里云、腾讯云),用于部署 frp 服务端(frps)。
- 本地电脑(或内网设备),用于部署 frp 客户端(frpc)。
- 从 frp Releases 页面下载对应系统的二进制包(如 Linux 选 frp_0.51.3_linux_amd64.tar.gz)。
Windows:https://github.com/fatedier/frp/releases/download/v0.57.0/frp_0.57.0_windows_amd64.zipLinux:https://github.com/fatedier/frp/releases/download/v0.57.0/frp_0.57.0_linux_amd64.tar.gz # 或者 wget https://github.com/fatedier/frp/releases/download/v0.59.0/frp_0.59.0_linux_amd64.tar.gzmwget https://github.com/fatedier/frp/releases/download/v0.59.0/frp_0.59.0_linux_amd64.tar.gz
-
服务端配置(公网服务器):
-
解压后,服务端核心配置文件是
frps.toml
。 -
以 TCP 代理为例,配置一个基础服务端:
# frps.toml bindPort = 7000 # frp服务端与客户端通信的端口(必选) vhostHTTPPort = 8080 # HTTP虚拟主机端口(可选,用于暴露Web服务) vhostHTTPSPort = 8443 # HTTPS虚拟主机端口(可选)
- 启动服务端:
./frps -c ./frps.toml
-
-
客户端配置(本地电脑):
- 解压后,修改客户端配置文件
frpc.toml
,将本地 8080 端口的 Web 服务暴露到公网。
# frpc.toml serverAddr = "你的公网服务器IP" # 必选,公网服务器IP serverPort = 7000 # 必选,与服务端bindPort一致[[proxies]] name = "web-demo" # 代理名称(唯一标识) type = "http" # 代理类型(http/https/tcp/udp/stcp等) localIP = "127.0.0.1" # 本地服务IP(默认本机) localPort = 8080 # 本地服务端口(必选) customDomains = ["web.yourdomain.com"] # 自定义域名(需解析到公网服务器IP)
- 启动客户端:
./frpc -c ./frpc.toml
- 解压后,修改客户端配置文件
- 验证效果:
- 域名解析:将
web.yourdomain.com
的 A 记录指向公网服务器 IP。 - 访问测试:在公网环境浏览器输入
http://web.yourdomain.com:8080
,应能看到本地 Web 服务的内容。
- 域名解析:将
输入地址(公网ip:端口号)可以查看服务端管理页面。
服务端显示注册了两个连接,一个tcp,一个http。
三、进阶玩法:全场景覆盖
除了基础的穿透功能,frp 还支持更复杂的场景:
-
HTTPS 代理:当需要暴露生产环境的 Web 服务(如前端项目或 API 接口)时,HTTPS 是必需的。frp 支持直接配置 SSL 证书,步骤如下:
- 准备证书:可通过 Let’s Encrypt 申请免费证书(
fullchain.pem
和privkey.pem
),或自签名(参考 frp 文档的 TLS 配置)。 - 服务端配置:
# frps.toml vhostHTTPSPort = 443 # 常用HTTPS端口 tlsOnly = true # 强制使用TLS(可选)
- 客户端配置:
# frpc.toml [[proxies]] name = "web-https" type = "https" localPort = 8080 customDomains = ["web.yourdomain.com"] # 若服务端已配置证书,客户端无需重复配置;否则需指定证书路径 # tlsCertFile = "./fullchain.pem" # tlsKeyFile = "./privkey.pem"
- 准备证书:可通过 Let’s Encrypt 申请免费证书(
-
UDP 穿透:当需要实时通信(如游戏联机、视频流)时,使用 UDP 协议。frp 的
udp
类型代理可直接穿透:# frpc.toml [[proxies]] name = "game-server" type = "udp" localIP = "192.168.1.100" # 内网网络服务器IP localPort = 27015 # 游戏服务端口 remotePort = 27015 # 公网映射端口(需与服务端协商未被占用)
-
安全增强:frp 提供了多层安全防护:
- 加密:配置
useEncryption = true
,客户端与服务端通信加密(防中间人攻击)。 - 压缩:配置
useCompression = true
,减少传输流量(适合带宽有限场景)。 - HTTP 基本认证:为 HTTP 代理添加用户名和密码,防止恶意访问:
[[proxies]] name = "web-auth" type = "http" localPort = 8080 httpUser = "admin" # 用户名 httpPwd = "123456" # 密码
- 加密:配置
-
P2P 直连:传统穿透模式中,所有流量都经过公网服务器中转,对于大流量场景(如视频流),服务器带宽成本较高。frp 的
stcp
模式支持 P2P 直连,流量直接在客户端和访问者之间传输,仅需服务器做握手协商:- 被穿透方(B)配置:
[[proxies]] name = "secret-ssh" type = "stcp" serverName = "secret-ssh" # 与访问者协商的服务名 secretKey = "abcdefg" # 通信密钥(需与访问者一致) localPort = 22 # 本地SSH端口
- 访问者(C)配置:
[[proxies]] name = "access-ssh" type = "stcp" role = "visitor" # 标记为访问者 serverName = "secret-ssh" # 与被穿透方一致 secretKey = "abcdefg" # 密钥一致 bindAddr = "127.0.0.1" # 访问者本地绑定IP bindPort = 6000 # 访问者本地端口(通过ssh -p 6000 127.0.0.1访问)
四、实战场景:开发者最常用的 3 类需求
-
本地开发调试:当前端同学在开发 Vue/React 项目时,需要将本地
localhost:3000
暴露给测试或客户。使用 frp 的 HTTP 代理模式,只需:- 服务端开放 8080 端口。
- 客户端配置
customDomains
为临时域名(如dev.yourdomain.com
)。 - 测试人员直接访问
http://dev.yourdomain.com:8080
即可,无需安装任何工具。
-
远程运维:对于没有公网 IP 的内网服务器(如工厂里的工控机),可以通过 frp 的 TCP 代理暴露 SSH 端口(22)。运维人员通过公网服务器 IP + 映射端口(如 6000),即可远程登录:
ssh -p 6000 user@公网服务器IP
-
家庭 NAS:家里的 NAS(如群晖)通常处于运营商 NAT 后,无法直接公网访问。通过 frp 将 NAS 的 5000(HTTP)和 5001(HTTPS)端口映射到公网,出差时可以通过
https://nas.yourdomain.com:5001
访问私有云,数据仅经自己的服务器中转,比第三方网盘更安全。
五、设置服务自启动
在 Linux 系统下,使用 systemd 可以方便地控制 frps 服务端的启动、停止、配置后台运行以及开机自启动。
以下是具体的操作步骤:
-
安装 systemd
如果您的 Linux 服务器上尚未安装 systemd,可以使用包管理器如
yum
(适用于 CentOS/RHEL)或apt
(适用于 Debian/Ubuntu)来安装它:# 使用 yum 安装 systemd(CentOS/RHEL) yum install systemd# 使用 apt 安装 systemd(Debian/Ubuntu) apt install systemd
-
创建 frps.service 文件
使用文本编辑器(如 vim)在
/etc/systemd/system
目录下创建一个frps.service
文件,用于配置 frps 服务。$ sudo vim /etc/systemd/system/frps.service
-
写入内容
在
frps.service
文件中写入以下内容:[Unit] Description=frp service After=network.target[Service] Type=simple ExecStart=/home/ubuntu/frp_0.59.0_linux_amd64/frps -c /home/ubuntu/frp_0.59.0_linux_amd64/frps.toml KillSignal=SIGQUIT TimeoutStopSec=5 Restart=on-failure RestartSec=5s KillMode=process PrivateTmp=true StandardOutput=syslog StandardError=inherit[Install] WantedBy=multi-user.target
-
使用 systemd 命令管理 frps 服务
使用以下命令启动、停止、重启和查看 frps 服务的状态:
# 启动frp sudo systemctl start frps# 停止frp sudo systemctl stop frps# 重启frp sudo systemctl restart frps# 查看frp状态 sudo systemctl status frps
-
设置 frps 开机自启动
使用以下命令设置 frps 服务开机自启动:
sudo systemctl enable frps
总结
内网穿透是一种通过公共网络连接两个私有网络的技术,使得外部用户可以访问内部网络中的服务。frp 作为反向代理工具,凭借其全面的协议支持、灵活的配置选项、P2P 直连等功能,为开发者提供了便捷且安全的远程访问解决方案。通过本文,相信你已经掌握了 frp 的基础与进阶用法,可以更好地应对各种内网穿透需求。
frp 中文官网:https://gofrp.org/zh-cn/
frp 中文文档:https://gofrp.org/zh-cn/docs/
其他资源
使用frp实现内网穿透教程 https://blog.csdn.net/jichencsdn/article/details/138253143
frp实现内网穿透(一篇解决所有问题!) https://blog.csdn.net/weixin_44700323/article/details/140777393