SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-21

CGNAT 下用 VPS 反向隧道发布家庭服务

CGNAT 没有公网 IP,端口转发自然不起作用。本文用低价 VPS 部署 frp,由家用主机主动建立隧道,并在公网端配置 HTTPS 证书。

CGNAT 后端口转发为何不起作用

在 CGNAT(运营商级网络地址转换)环境中,路由器的 WAN 地址与其他用户共享。因此,您没有专属公网 IP,也就没有可供转发的端口。反向隧道可以解决这一问题:一台低价 VPS 提供公网 IP,您的家用主机主动连接 VPS,入站请求再沿着家用主机已经建立的连接返回。您可以继续使用现有硬件,只需租用 ISP 不会提供的那项资源:可路由的地址。

下面的每条命令都标明了运行它的主机。此方案需要两台主机:一台具有公网 IP 的 VPS,以及一台运行目标服务、供您远程访问的家用主机。

如何判断自己是否实际位于 CGNAT 后

打开路由器管理页面,查看它报告的 WAN 地址。然后查询互联网可见的地址。

# on the home box
curl -4 -s https://ifconfig.me; echo

如果两个地址一致,您拥有公网 IP,不需要执行以下操作。转发端口即可,无需继续阅读。如果路由器的 WAN 地址位于 100.64.0.0/10 内,您处于 CGNAT 后。该地址段是 RFC 6598 共享地址空间,专门保留用于此用途。有些 ISP 会在 WAN 侧分配 10.0.0.0/8,本质上情况相同,只是名称不同。

租用任何服务前,先检查一项内容。许多使用 CGNAT 的 ISP 会分配真实的 IPv6 前缀。如果您的家庭设备拥有全局 IPv6 地址,您可以为该地址放行防火墙,从而完全跳过隧道。但当访问者位于仅支持 IPv4 的网络时,这种方式就无法使用,因此大多数人最终仍会采用隧道方案。

VPS 反向隧道的工作方式:从内向外建立连接

CGNAT 和普通家用路由器都会阻止未经请求的入站连接。企业防火墙也是如此。但它们不会阻止出站连接,因为浏览器和更新客户端每天都会发起出站连接。NAT 设备检测到出站 TCP 连接后,会为其创建映射,并允许该连接上的返回流量。外部设备无法主动连接到您的家用主机。因此,由家用主机发起连接,隧道再通过同一连接将流量反向传回。

这就是完整的工作机制。家用主机通过一个端口连接到 VPS,并保持连接处于打开状态。VPS 接收公网请求,再通过现有连接将请求转发给家用主机。整个过程中都不需要访问您的家庭 IP 地址。

这会带来两个有用的结果。您的 DNS 记录始终指向 VPS,而不是您的家庭网络。您的公网地址也变成 VPS 的地址,因此任何人通过 IP 查询获得的信息,指向的都是租用的服务器,而不是您的家庭网络。

构建方式

  1. ssh -R:两端都已安装,适合单个服务或临时演示。它没有控制面板,也没有真正可用的重连逻辑。
  2. frp:一个小型 Go 服务器(frps)和与之匹配的客户端(frpc)。适合在一个主机名后长期运行多个服务。本指南主要介绍这种方式。
  3. 网状 VPN:Tailscale,或自行运行的 WireGuard 服务器。适合让您自己的设备彼此私密访问,而不是将服务发布到公网。

如果您的目标是从自己控制的设备进行私密访问,请选择网状 VPN。Tailscale Serve 和 Funnel介绍如何将服务发布到 tailnet 外部;同一 VPS 上自行托管的 WireGuard VPN则提供相同的网络结构,且链路中不需要第三方协调服务器。阅读其中一篇,然后跳过本页其余内容。以下内容均假设您需要一个任何人都能访问的公共 HTTPS 主机名。

快速方案:使用 ssh -R 转发单个服务

假设家庭服务器上的应用监听 127.0.0.1:3000,并且您已经可以通过 SSH 访问 VPS。

# on the home box
ssh -N \
  -o ExitOnForwardFailure=yes \
  -o ServerAliveInterval=30 \
  -o ServerAliveCountMax=3 \
  -R 127.0.0.1:8080:127.0.0.1:3000 \
  tunnel@vps.example.com

-R 127.0.0.1:8080:127.0.0.1:3000 会让 VPS 上的 sshd 监听自身的 127.0.0.1:8080,并将该端口收到的所有流量转发到家庭服务器上的 127.0.0.1:3000-N 表示不启动 shell。两个 ServerAlive 选项会让 ssh 在大约九十秒后检测到链路已断开,而不是一直挂起在已经不存在的连接上。

下面是最容易混淆的部分。该监听器绑定在 loopback 上,因此从其他位置访问 curl http://vps.example.com:8080 都会失败。sshd 默认使用 GatewayPorts no,也就是说,远程转发只绑定 loopback 接口。不要通过设置 GatewayPorts yes 来解决此问题。保留绑定在 loopback 上的转发,并在其前面使用 nginx,就像下面的 frp 配置一样。这样公网端口使用带证书的 443,隧道端口不会直接暴露到互联网。如果您不确定当前有哪些进程正在监听,以及它们绑定在哪个接口上,可以花十分钟阅读Linux 端口和监听器简介

如果 VPS 上的端口已被占用,ssh 会输出以下内容;ExitOnForwardFailure=yes 会让它直接退出,而不是在隧道未正常工作的情况下继续建立连接:

Warning: remote port forwarding failed for listen port 8080

通常的原因是之前的会话异常终止,而 sshd 没有检测到。请在 VPS 的 /etc/ssh/sshd_config 中设置 ClientAliveInterval 30ClientAliveCountMax 3,以便清理失效会话并释放端口。使用 Restart=always 将整个命令封装在 systemd 单元中,并使用专用密钥;或者使用 autossh。如果需要转发多个服务,请停止阅读此处,改用 frp。

在 VPS 上安装 frp,并固定版本标签

frp 以静态 Go 二进制文件形式发布,不在 Ubuntu 或 Debian 软件仓库中,因此需要自行下载发布版本并验证。请固定版本。v0.52.0 修改了配置格式,此后选项名称也发生过变化,因此过时的教程可能会提供当前二进制文件无法识别的配置项。本指南使用于 2026 年 8 月 14 日发布的 v0.71.0

# on the VPS
FRP_VERSION=0.71.0
ARCH=amd64   # use arm64 if `uname -m` prints aarch64
cd /tmp
curl -fsSLO "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
curl -fsSLO "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_sha256_checksums.txt"
sha256sum --check --ignore-missing frp_sha256_checksums.txt

sha256sum 应准确输出一行:

frp_0.71.0_linux_amd64.tar.gz: OK

由于校验和文件涵盖全部十八个发布资源,而您只下载了其中一个,因此需要使用 --ignore-missing。不使用该选项时,sha256sum 会将其余十七个资源报告为缺失,并以非零状态退出。这看起来像是验证失败,但实际并无问题。

# on the VPS
tar xzf "frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
sudo install -m 755 "frp_${FRP_VERSION}_linux_${ARCH}/frps" /usr/local/bin/frps
sudo useradd --system --no-create-home --shell /usr/sbin/nologin frp
sudo install -d -m 750 -o root -g frp /etc/frp
frps --version

frps --version 会输出 0.71.0。只有 frps 应安装在 VPS 上。frpc 应安装在家用主机上。把两个二进制文件都安装到所有设备上,容易导致误在家用主机上运行隧道服务器。

VPS 配置:令牌、强制 TLS、本地回环监听器

先生成令牌。它是隧道与扫描 VPS 端口的其他人之间唯一的防线。

# on the VPS
openssl rand -base64 32

将该值写入 /etc/frp/frps.toml

bindAddr = "0.0.0.0"
bindPort = 7000

# Every listener frp creates for a proxy, including the HTTP vhost, stays on loopback.
proxyBindAddr = "127.0.0.1"
vhostHTTPPort = 8080

auth.method = "token"
auth.token = "PASTE_THE_OPENSSL_OUTPUT_HERE"

transport.tls.force = true

webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "PASTE_A_SECOND_SECRET_HERE"

log.level = "info"

其中 4 行负责安全设置,下面逐行说明。

客户端上的 auth.token 必须与 auth.token 匹配。没有它,frps 会接受任何找到 7000 端口的客户端连接。该客户端随后可以通过你的 VPS 和证书发布任意内容。

transport.tls.force = true 会拒绝所有不是 TLS(传输层安全)的控制连接。自 v0.50.0 起,客户端默认启用 TLS,因此实际使用中无需额外配置。它还可以阻止旧客户端或手动编写的客户端在未通知你的情况下明文连接。

proxyBindAddr = "127.0.0.1" 是大多数指南遗漏的配置,也是此设置可以长期运行且保持安全的原因。它会将 frp 代表代理打开的所有监听器,包括 HTTP 虚拟主机和客户端请求的任意 remotePort,都绑定到本地回环接口。互联网完全无法访问这些监听器。唯一的公网入口是 443 端口上的 nginx,而 nginx 由你配置和控制。

webServer.addr = "127.0.0.1" 会阻止仪表板监听公网接口。仪表板完整展示你的私有服务及其流量,只由一个 HTTP basic auth 密码保护,因此不应绑定到 0.0.0.0

设置文件所有权,避免令牌对所有用户可读,然后在启动任何服务前检查语法:

# on the VPS
sudo chown root:frp /etc/frp/frps.toml
sudo chmod 640 /etc/frp/frps.toml
sudo -u frp frps verify -c /etc/frp/frps.toml

有效文件会输出:

frps: the configuration file /etc/frp/frps.toml syntax is ok

还有一个格式细节,可以避免你浪费 1 小时。frp 根据文件扩展名选择解析器,并支持 .toml.yaml.yml.json。旧的 .ini 文件仍可通过旧版转换路径加载,但 INI 已弃用,新选项只记录在 TOML 文档中。如果教程要求你使用 [common] 部分和 server_addr = x.x.x.x,说明它早于 v0.52.0,其键名将与刚安装的二进制文件不匹配。

以非特权服务运行 frps

bindPort 为 7000,vhostHTTPPort 为 8080。两者都大于 1024,因此 frps 无需 root,也无需 CAP_NET_BIND_SERVICE。这也是不将 vhost 放在 80 端口、而让 nginx 接管该端口的原因。

编写 /etc/systemd/system/frps.service

[Unit]
Description=frp reverse tunnel server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=65535
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true

[Install]
WantedBy=multi-user.target
# on the VPS
sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo journalctl -u frps -n 20 --no-pager

日志应显示这两个监听器。地址比端口更重要:

frps tcp listen on 0.0.0.0:7000
http service listen on 127.0.0.1:8080

ProtectSystem=strict 使该服务看到的整个文件系统变为只读。frps 可以正常运行,因为其日志默认写入标准输出,并由 journald 捕获。如果将 log.to 设置为文件路径,服务在添加匹配的 ReadWritePaths= 行之前无法写入该文件,因此请保留默认设置。

防火墙:只开放一个端口,不要开放端口范围

# on the VPS
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 7000/tcp
sudo ufw enable
sudo ufw status numbered

共需要4条规则,其中1条仅用于证书续期。22是 SSH 端口。80将请求重定向到443,并响应 ACME(自动证书管理环境)质询。443为所有通过隧道转发的应用提供服务。7000是 frp 控制端口,也是客户端唯一需要访问的端口。

如果指南要求开放类似 sudo ufw allow 20000:30000/tcp 这样的端口范围,说明它采用的是另一种设计:每个服务占用一个独立的公网 TCP 端口。这里不需要这样做,因为所有请求都通过443到达,再由 frp 根据主机名进行路由。如果以后确实需要开放一个公网 TCP 端口,请将 proxyBindAddr 恢复为 0.0.0.0,并添加限制,使客户端只能占用你指定的端口:

allowPorts = [
  { start = 20000, end = 20010 }
]
maxPortsPerClient = 5

大多数云服务提供商还会在控制面板中提供网络防火墙,它与服务器上的 ufw 分开。如果 sudo ufw status 中的规则看起来正确,但连接仍然超时,通常是被云服务商的网络防火墙阻止了。VPS 实际需要的 ufw 规则将介绍本节所采用的默认拒绝配置。

在 VPS 上使用真实证书终止 HTTPS

home.example.com 的 A 记录指向 VPS 的公网 IP。不要指向您家里的地址。您家没有可供指向的公网地址,这正是需要解决的问题。

# on the VPS
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx

先为 /etc/nginx/sites-available/home.example.com 创建一个仅包含 80 端口的配置块,让 certbot 有可匹配的 server_name

server {
    listen 80;
    listen [::]:80;
    server_name home.example.com;
    location / { return 404; }
}
# on the VPS
sudo ln -s /etc/nginx/sites-available/home.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot certonly --nginx -d home.example.com

如果配置文件解析成功,nginx -t 会输出 nginx: configuration file /etc/nginx/nginx.conf test is successful。每次 reload 前都运行它。reload 失败时,nginx 会继续运行旧配置,因此错误的修改看起来就像没有生效。

WebSocket 升级需要在 http 级别配置一个 map。将其放入 /etc/nginx/conf.d/upgrade.conf

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

现在将站点文件替换为正式配置:

server {
    listen 80;
    listen [::]:80;
    server_name home.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name home.example.com;

    ssl_certificate     /etc/letsencrypt/live/home.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/home.example.com/privkey.pem;

    client_max_body_size 512m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        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;
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        $connection_upgrade;
        proxy_read_timeout 3600s;
    }
}

这里不能省略 proxy_set_header Host $host;。frp 的 HTTP vhost 会根据 Host 请求头进行路由,并将其与客户端配置中的 customDomains 列表匹配。省略该请求头后,nginx 会发送 Host: 127.0.0.1,frp 找不到该名称对应的代理,访问者收到的就会是 frp 返回的空白 404,而不是应用页面。逐行解释 nginx 反向代理配置块介绍了其他请求头的作用。

# on the VPS
sudo nginx -t && sudo systemctl reload nginx
sudo certbot renew --dry-run

dry run 可验证 90 天后续期仍能成功,而届时您可能不会在线监控。它要求 80 端口可访问,因此需要配置那条 ufw 规则。

家庭端:以非特权服务运行 frpc

按照安装 frps 的方式,在家庭设备上安装 frpc。使用相同版本,并执行相同的校验和步骤。然后创建相同的 frp 用户和 /etc/frp 目录。写入 /etc/frp/frpc.toml

serverAddr = "vps.example.com"
serverPort = 7000

auth.method = "token"
auth.token = "PASTE_THE_SAME_TOKEN_HERE"

transport.tls.enable = true
loginFailExit = false

proxies = [
  { name = "home-app", type = "http", localIP = "127.0.0.1", localPort = 3000, customDomains = ["home.example.com"] }
]

此文件中的键顺序很重要,原因与格式无关。TOML 会将表头之后的所有键分配给该表。因此,如果将 serverAddr 这样的顶层设置写在代理表头之后,它就会悄悄变成代理设置,并被 frp 忽略。像上面这样将代理列表写成内联数组,可以避免这个问题:每个顶层键都能明确保持在顶层。

type = "http" 会通过 vhost 监听器转发此代理,而不是为其占用独立的公网 TCP 端口。这就是防火墙保持 4 条规则的原因。customDomains 必须包含 nginx 在 Host 标头中转发的主机名,因此应使用 home.example.com,不能使用 VPS 的 IP 地址。

loginFailExit = false 的作用比表面上更重要。默认值为 true,这会让 frpc 在第一次登录尝试失败时退出。家庭设备可能在 ISP 链路建立之前就完成启动。这样一来,服务会一直停止,直到你注意到问题为止。将其设置为 false 后,frpc 会持续重试,直到 VPS 响应。

写入 /etc/systemd/system/frpc.service

[Unit]
Description=frp reverse tunnel client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
Restart=always
RestartSec=10s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

[Install]
WantedBy=multi-user.target
# on the home box
sudo chown root:frp /etc/frp/frpc.toml
sudo chmod 640 /etc/frp/frpc.toml
sudo -u frp frpc verify -c /etc/frp/frpc.toml
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo journalctl -u frpc -n 20 --no-pager

成功连接的客户端会记录一个运行 ID:

login to server success, get run id [3a1f9c2b7d4e5f60]

在浏览器中打开 https://home.example.com,应能访问位于家庭端 127.0.0.1:3000 上的应用。客户端上的 Restart=always 是有意这样设置的:家庭网络连接可能中断,服务应在连接恢复后自动重新运行。

不要让控制面板暴露在公网接口上

使用 webServer.addr = "127.0.0.1" 后,控制面板只在 VPS 本机上响应。不要开放端口,而是通过本地转发从笔记本电脑访问:

# on your laptop
ssh -N -L 7500:127.0.0.1:7500 you@vps.example.com

打开 http://127.0.0.1:7500,然后使用 frps.toml 中的 webServer.userwebServer.password 登录。页面会列出每个已连接的客户端,以及每个代理的流量计数器。这是最快确认“家中的设备当前是否已连接”的方法。关闭 SSH 会话后,控制面板将再次无法访问。

隧道不负责什么

请将本部分阅读两遍,因为这里最容易造成安全问题。隧道会让私有服务可从公网访问,但不会对访问者进行身份验证。https://home.example.com解析后,扫描器会在数天内发现它;无论您是否告诉过别人这个名称,结果都一样。证书透明度日志会公开您为其签发证书的每个主机名,因此 certbot 成功后,该名称立即就是公开信息。

您暴露的任何服务都必须自行提供身份验证。如果应用具有真正的登录功能并实施速率限制,则没有问题。如果它使用一个共享密码登录,或者完全没有登录功能,请在 VPS 上将身份验证代理放在它前面。在应用前部署 oauth2-proxy 是通常的做法。它位于 nginx 和 frp vhost 之间,无需修改隧道两端。

frps.toml中的令牌用于保护隧道,而不是保护应用。它可以阻止陌生人在您的 VPS 上注册自己的代理,但无法处理发往 443 端口、且目标是您主动公开的主机名的请求。

以下两点应作为固定操作习惯。通过编辑两个文件并重启两个服务来轮换令牌,因为令牌不会自行过期。并保持 frp 为最新版本:该二进制程序是面向公网的入口,v0.71.0 的说明列出了一个由客户端发送的错误值触发服务器 panic 的问题。此类漏洞应及时修补,而不是自行分析其影响。

故障模式及对应的报错信息

客户端始终无法连接。 journalctl -u frpc 会重复输出 connect to server error:,随后出现拨号超时。没有任何流量到达端口 7000。先检查 VPS 上的 ufw,再检查控制面板中的服务商网络防火墙,最后使用 getent hosts vps.example.com 确认名称解析是否正常。

令牌错误。 客户端会明确报告这一点:

login to the server failed: token in login doesn't match token from configuration

再次复制令牌。末尾换行符,或未加引号的 shell 字符串中的 $ 在展开后变为空值,几乎都会导致此问题。因此,TOML 文件中的 openssl rand -base64 32 输出必须放在引号内。

隧道已建立,但浏览器只收到 404。 frpc 已记录登录成功,控制面板也列出了代理,但页面返回 404,且没有应用的样式。这表示 frp 找不到与此 Host 请求头匹配的代理。在 VPS 上直接测试虚拟主机,绕过 nginx 和 TLS:

# on the VPS
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: home.example.com' http://127.0.0.1:8080/

如果该命令返回 404,说明 customDomains 配置错误。返回其他状态码,则表示请求未从 nginx 获得正确的 Host

nginx 返回 502。 nginx 正在响应,但 frp 没有响应。VPS 上的 sudo ss -lntp | grep 8080 应显示 frps 正在监听 127.0.0.1:8080。输出为空表示 frps 已停止,或 vhostHTTPPort 未在 frps.toml 中设置。

应用认为所有访问者都在本地。 应用对每个请求都记录 127.0.0.1。frp 设置 X-Forwarded-For,nginx 会向其中追加内容,因此真实客户端地址位于该请求头中。配置应用,使其信任此请求头。如果应用按 IP 地址执行速率限制,不要跳过此步骤,因为当前互联网上的所有访问者共用同一个限制桶。

长请求在 60 秒后被中断。 上传或流式响应会中途停止。这是 nginx 的默认 proxy_read_timeout,与隧道无关。上面的配置块将其提高到 3600s。client_max_body_size 是对应的上传大小限制;其默认值为 1 MB,较大的请求体会被拒绝并返回 413。

一切正常,但路由器重启后服务停止。 frpc 单元中的 Restart=always 加上 loginFailExit = false 可解决此问题。使用 sudo systemctl is-enabled frpc 确认,该命令必须输出 enabled

FAQ

如何判断自己是否位于 CGNAT 后面?

将路由器管理页面中的 WAN 地址与同一网络内部 curl -4 -s https://ifconfig.me 报告的地址进行比较。如果两者不同,且路由器的 WAN 地址位于 100.64.0.0/10 中,说明 ISP 正在使用运营商级 NAT。该地址段是 RFC 6598 共享地址空间,专门用于此目的。有些 ISP 会在 WAN 侧使用 10.0.0.0/8,含义相同。如果两个地址一致,说明您拥有公网 IP:转发端口即可完成配置。

反向隧道需要域名吗?

对于本文介绍的 HTTPS 配置,需要。证书会签发给主机名,而 frp 会根据 Host 请求头路由请求,因此两端必须使用双方认可的名称。使用编号端口的原始 TCP 代理可以直接通过 VPS 的裸 IP 工作,完全不需要域名,但这样没有证书,也无法按主机名路由,因此一个公网端口只能服务一个应用。

在公网 VPS 上运行 frp 安全吗?

只要控制端口是唯一对外暴露的端口,并且已启用身份验证,就可以安全运行。请在两端将 auth.token 设置为随机值,并在服务器上设置 transport.tls.force = true。然后设置 proxyBindAddr = "127.0.0.1",确保 frp 为代理开放的端口不会面向互联网;将管理面板保留在 webServer.addr = "127.0.0.1",通过 SSH 本地转发访问。发布新版本后及时更新二进制文件,因为该进程正在监听公网地址。

为什么没人能访问我转发的 ssh -R 端口?

sshd 默认启用 GatewayPorts no,因此远程转发只会绑定到 VPS 的回环接口。在 VPS 本机运行的 curl 可以正常工作,而来自其他位置的 curl 会超时。正确的解决方法是让转发继续监听回环接口,再让 nginx 在 443 端口上位于其前面。设置 GatewayPorts yes 会发布一个没有证书、没有 TLS 的原始端口,这会引入比原问题更严重的风险。

应该使用 frp,还是使用 Tailscale 或 WireGuard 等组网 VPN?

如果只有您自己的设备需要访问,请使用组网 VPN,因为这样不会发布任何服务,也不会有可供他人扫描的公网主机名。如果需要一个任何浏览器都能访问的公网 HTTPS 地址,例如 Webhook 接收端,或需要与不愿安装 VPN 客户端的人员共享页面,请使用 frp。两者可以在同一台 VPS 上共存,分别使用不同端口,承担不同任务。

#frp#cgnat#nat#tunnel#reverse-proxy