frp 内网穿透实战:从服务端部署到 Web、SSH、远程桌面访问一次讲清


很多站长手里都有 VPS,但真正让人头疼的往往是另一类需求:家里的 NAS、办公室的电脑、内网里的测试站点,明明就在手边,却没有公网 IP,外面根本访问不到。传统做法是找运营商开公网 IP、做端口映射,可大多数宽带早就换成了 NAT 模式,申请流程又长又麻烦。

内网穿透就是解决这个问题的:用一台有公网 IP 的 VPS 做中转,把内网设备的端口"映射"到公网。frp 是目前用得最多、配置最简单的开源方案之一,服务端和客户端都只有一个二进制文件,几分钟就能跑起来。本文按真实操作顺序,把服务端部署、客户端配置、Web / SSH / 远程桌面三个常见场景,以及安全加固和排错一次讲清。

一、frp 是什么,适合哪些场景

frp 全称 Fast Reverse Proxy,是一个反向代理工具。它的工作方式可以拆成两端:

  • frps(服务端):部署在拥有公网 IP 的 VPS 上,负责接收内网客户端的连接,并把公网请求转发进去。
  • frpc(客户端):部署在内网设备上,主动连接 frps,建立一条长连接,把本地端口暴露出去。

因为客户端是"主动往外连"的,所以内网设备不需要公网 IP,也不需要路由器做端口映射,只要能上网就能用。常见场景包括:

  • 把家里的 NAS、路由器管理页、监控画面发布到公网;
  • 在外面用 SSH 管理公司或家里的 Linux 主机;
  • 远程桌面连接内网 Windows 电脑;
  • 给没有公网 IP 的测试服务器做临时域名访问。

和同类方案相比,frp 的优势是部署轻、协议全(TCP、UDP、HTTP、HTTPS 都支持)、配置直观,缺点是流量要经过中转服务器,速度和延迟取决于 VPS 线路。

二、准备工作

开始之前,确认三样东西:

  • 一台有公网 IP 的 VPS:1 核 1G 就够用,系统建议 Debian 12 或 Ubuntu 22.04/24.04,本文命令以这两个系统为准。
  • 一个域名(可选):如果要把内网站点发布成 blog.example.com 这样的地址,需要域名并完成备案(国内服务器)或直接使用海外服务器。
  • 内网设备:能安装 frpc 的 Linux、Windows 或 NAS,以及要暴露的本地端口。

登录 VPS,先更新系统并安装基础工具:

apt update
apt install -y curl wget tar systemd

三、服务端:在 VPS 上部署 frps

frp 官方在 GitHub 发布编译好的二进制包,直接下载解压即可。先设置一个版本变量,实际使用时到 releases 页面换成最新版本号:

FRP_VER="0.61.0"
ARCH="amd64"
cd /tmp
wget https://github.com/fatedier/frp/releases/download/v${FRP_VER}/frp_${FRP_VER}_linux_${ARCH}.tar.gz
tar -xzf frp_${FRP_VER}_linux_${ARCH}.tar.gz
mkdir -p /usr/local/frp
cp frp_${FRP_VER}_linux_${ARCH}/frps /usr/local/frp/
chmod +x /usr/local/frp/frps

新建服务端配置文件 /usr/local/frp/frps.toml。从 v0.52 开始 frp 默认使用 TOML 格式,旧版 ini 写法已经不再推荐:

bindPort = 7000
auth.token = "请换成你自己的强密码"

# 仪表盘,建议只监听本机,通过 SSH 隧道访问
webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "请换成强密码"

# 如要用 HTTP 方式发布网站,开启这一项
vhostHTTPPort = 8080

# 限制客户端可映射的远端端口范围,降低被滥用的风险
allowPorts = [
  { start = 20000, end = 30000 }
]

配置 systemd 托管,保证开机自启、进程掉线自动拉起。新建 /etc/systemd/system/frps.service:

[Unit]
Description=frp server
After=network.target

[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/frp/frps -c /usr/local/frp/frps.toml

[Install]
WantedBy=multi-user.target

启动并检查状态:

systemctl daemon-reload
systemctl enable --now frps
systemctl status frps
journalctl -u frps -f

看到 frps started successfully 就说明服务端已经跑起来了。接着放行防火墙端口,云服务器还要在控制台的安全组里同步放行:

ufw allow 7000/tcp
ufw allow 8080/tcp
ufw allow 2222/tcp
ufw allow 13389/tcp
ufw reload

四、客户端:在内网设备上部署 frpc

以 Linux 客户端为例,下载和安装方式与服务端一致,只需要 frpc 这个二进制:

FRP_VER="0.61.0"
ARCH="amd64"
cd /tmp
wget https://github.com/fatedier/frp/releases/download/v${FRP_VER}/frp_${FRP_VER}_linux_${ARCH}.tar.gz
tar -xzf frp_${FRP_VER}_linux_${ARCH}.tar.gz
mkdir -p /usr/local/frp
cp frp_${FRP_VER}_linux_${ARCH}/frpc /usr/local/frp/
chmod +x /usr/local/frp/frpc

新建 /usr/local/frp/frpc.toml,把地址、Token 和端口换成自己的:

serverAddr = "你的VPS公网IP"
serverPort = 7000
auth.token = "与服务端完全一致"

[[proxies]]
name = "home-web"
type = "http"
localIP = "127.0.0.1"
localPort = 80
customDomains = ["blog.example.com"]

[[proxies]]
name = "home-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 2222

[[proxies]]
name = "home-rdp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3389
remotePort = 13389

同样用 systemd 托管 frpc,新建 /etc/systemd/system/frpc.service:

[Unit]
Description=frp client
After=network.target

[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/frp/frpc -c /usr/local/frp/frpc.toml

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now frpc
systemctl status frpc
journalctl -u frpc -f

日志里出现 start proxy success,说明隧道已经建立。此时在服务端仪表盘里也能看到在线的客户端和代理列表。

五、场景一:把内网 Web 站点发布到公网

上面的 home-web 代理用的是 HTTP 类型。要让它通过域名访问,还需要三步:

1. 解析域名。在 DNS 服务商处添加一条 A 记录,把 blog.example.com 指向 VPS 的公网 IP。

2. 服务端开启 vhostHTTPPort。前面配置里的 vhostHTTPPort = 8080 就是 frp 接收 HTTP 请求的端口。访问 http://blog.example.com:8080 就能命中内网站点。

3. 换成 80/443 端口。直接暴露 8080 不美观,也不利于收录。更推荐用 Nginx 做一层反向代理,把 80/443 的请求转给 frp:

server {
    listen 80;
    server_name blog.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

保存后执行 nginx -t && systemctl reload nginx。再配合 Certbot 申请证书,就能得到完整的 HTTPS 访问。注意 proxy_set_header Host $host 不能漏,否则后端站点可能因为域名不匹配而跳转异常。

六、场景二:在外网 SSH 管理内网机器

home-ssh 代理把内网的 22 端口映射到 VPS 的 2222 端口。连接方式很直接:

ssh -p 2222 用户名@你的VPS公网IP

如果内网机器本身就在 NAT 后面,这相当于给它开了一扇只有你知道的门。几点建议:

  • 不要用默认的 2222,换一个不常见的端口,减少被扫描的概率;
  • 客户端机器上禁用密码登录,改用 SSH 密钥;
  • 在 frps 的 allowPorts 里限定可用端口范围,避免被当成免费跳板。

七、场景三:远程桌面连接内网 Windows

Windows 专业版默认开启 RDP,端口 3389。用 frpc 把它映射到公网的 13389:

[[proxies]]
name = "home-rdp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3389
remotePort = 13389

然后在 Windows 上打开"远程桌面连接",地址填 你的VPS公网IP:13389 即可。RDP 直接暴露在公网风险很高,务必做到:

  • 只允许自己的常用 IP 访问,必要时用云防火墙做源 IP 限制;
  • 开启 Windows 的账户锁定期和登录审计;
  • 能用 VPN 或 ZeroTier 时,优先走 VPN,不要把 3389 长期挂在公网。

八、安全加固:别把穿透做成后门

frp 本身不提供鉴权之外的防护,公网暴露的端口很容易被扫描。下面几项是最低要求:

  • 强 Token:服务端和客户端必须使用同一串足够长的随机字符,不要用默认值。
  • 开启 TLS:在 frps.toml 中加入 transport.tls.force = true,客户端会自动使用 TLS 连接,避免流量被中间人查看。
  • 仪表盘不对外:webServer.addr 保持 127.0.0.1,需要查看时用 ssh -L 7500:127.0.0.1:7500 做本地转发。
  • 限制端口范围:allowPorts 只放行自己需要的区间,防止别人拿你的 frps 做任意端口转发。
  • 及时升级:frp 版本更新较快,关注 releases 页面的安全修复,升级时服务端和客户端尽量保持同版本。

九、常见问题排查

客户端连不上服务端。先在 VPS 上执行 ss -lntp | grep 7000 确认端口在监听,再检查云安全组和 ufw 是否放行。用 telnet 你的IP 7000 从外网测试,能通再排查 Token 和版本。

提示 token 不一致。服务端和客户端的 auth.token 必须完全一样,注意不要带多余空格。修改后重启两端服务。

域名访问 404 或跳转异常。优先检查 Nginx 是否传递了正确的 Host 头,以及 frpc 的 customDomains 是否和访问域名完全一致。

连接偶尔断线。多半是 VPS 到内网之间的网络抖动,可以在 frpc 中加入 transport.heartbeatInterval 和 transport.heartbeatTimeout,并把 systemd 的 Restart=on-failure 保留好,掉线后会自动重连。

速度慢。frp 的流量全程走中转 VPS,线路质量决定体验。需要大流量传输时,选择带宽充足、回程优化好的服务器,或者改用 P2P 类方案。

十、结语

frp 把"没有公网 IP 也能从外网访问内网设备"这件事,压缩成了两份配置文件和两个 systemd 服务。整套流程跑通之后,NAS、SSH、远程桌面、内网测试站都能统一管理,换设备时也只需要改客户端配置。

最后再提醒一句:内网穿透的本质是把内网端口暴露到公网,便利和安全永远是一对矛盾。Token、TLS、端口限制、访问审计这四件事做到位,再谈方便。如果你也在用 frp,欢迎在评论区分享自己的配置方案和踩坑经历。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

curl test

Cloudflare 免费 CDN 实战:DNS 接入、SSL、缓存与防 CC 一次配好

评 论