异地组网实战:从 frp 中转到 Tailscale 直连,SSH 延迟 410ms → 29ms

场景:目标服务器在学校内网,人在校外访问。原有方案 frp + 公网 VPS 中转,本文记录迁移到 Tailscale 的完整过程:怎么装、怎么判断打洞成败、打洞失败后如何用 Peer Relay 兜底,以及最后拿到直连的全过程。所有数据均为实测。

一、frp 的结构性问题

frp 的原理是把内网端口逐条映射到公网 VPS 上:

复制代码
Mac ──→ VPS(frps) ──frp隧道──→ 校内服务器(frpc)

这个架构有两个绕不开的代价:

  1. 所有流量过 VPS。带宽上限 = VPS 带宽,传文件、跑 Jupyter 全被卡死;VPS 流量费也跟着涨。
  2. 每个服务一条规则 。想 SSH 加一条,想 Web 再加一条,端口开多了维护成本直线上升。

frp 适合的场景是"临时对外暴露一两个端口"。要的是组网------设备之间任意互访------就该换思路。

二、方案选型

方案 原理 需要公网IP 速度 维护成本
frp 端口转发 需要 VPS 受限于 VPS 每服务一条规则
WireGuard 自建 加密隧道 需要 VPS 配置文件手写
Tailscale WireGuard + 自动打洞 不需要 直连=裸链路 几乎为零
ZeroTier P2P 虚拟局域网 不需要 同上 略高于 TS

选 Tailscale:底层就是 WireGuard,控制面托管,装上登录即用。它的核心逻辑是:能 P2P 直连就直连(流量不过任何第三方),打洞失败才回落到官方 DERP 中继

关键认知:DERP 节点大多在境外(离我最近的是香港),中继模式下速度和延迟都可能不如国内 VPS 中转。所以用 Tailscale 的成败,完全取决于能不能打通直连。下文的重心就在这。

三、安装与登录

校内服务器(Ubuntu)

bash 复制代码
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

tailscale up 会打印一个 https://login.tailscale.com/a/xxxx 授权链接,复制到本地浏览器打开,用 GitHub/Google 账号登录。登录后拿到虚拟 IP:

bash 复制代码
$ tailscale ip -4
100.80.171.73

确认开机自启(官方脚本默认已注册 systemd 服务):

bash 复制代码
systemctl is-enabled tailscaled   # 期望 enabled

顺手到管理后台(login.tailscale.com → Machines)把这台服务器 Disable key expiry。否则约 180 天后节点密钥过期,无头服务器会掉线且需要重新浏览器认证,很烦。

Mac

App Store 装 Tailscale,或 brew install --cask tailscale,菜单栏登录同一账号。

注意 Mac 版命令行路径特殊(后面反复用到,建议加 alias):

bash 复制代码
echo "alias tsping='/Applications/Tailscale.app/Contents/MacOS/Tailscale ping'" >> ~/.zshrc && source ~/.zshrc

四、核心技能:怎么判断 Tailscale 能不能成

这是本文最重要的部分。很多人装完发现慢就弃坑,其实慢的原因 99% 是在走 DERP 中继,而这是可以提前诊断的。

1. netcheck:网络体检

两端各跑一次:

bash 复制代码
tailscale netcheck

只看三个字段:

复制代码
* UDP: true                        ← false = 出站UDP被封,直接判死
* MappingVariesByDestIP: false     ← true = 对称NAT,打洞基本没戏
* Nearest DERP: Hong Kong          ← 中继兜底位置,顺带看延迟

MappingVariesByDestIP 是重点:false 表示 NAT 对不同目标使用相同的外部映射(cone 型),对端可以预测你的端口洞在哪,打洞希望大。

2. tailscale ping:看流量实际走哪条路

普通 ping 走 ICMP,看不出路径。必须用 tailscale ping

bash 复制代码
tsping 100.80.171.73

两种输出,天壤之别:

复制代码
pong from ... via DERP(hkg) in 424ms        ← 走香港中继,慢
pong from ... via 223.100.xxx.xxx:41641 in 29ms   ← 直连,快

判读规则:

  • 前 1~2 发走 DERP 是正常的 ------那是协商阶段,打洞完成后会升级成 via <公网IP>:<端口>
  • 连续多发全是 via DERP(xxx) 且末尾出现 direct connection not established,才是真的打洞失败;
  • tailscale ping --c 20 <IP> 多打几发再下结论,有些 NAT 组合要几十秒才完成协商。

五、实战记录:打洞失败与排查

装好后的第一次测试就不顺利。校内端 netcheck 很健康:

复制代码
* UDP: true
* IPv4: yes, 223.100.xxx.xxx:xxxxx  ← 学校出口NAT
* MappingVariesByDestIP: false       ← cone型,理想情况

Mac 端同样健康(北京家宽,出口 222.130.x.x):

复制代码
* UDP: true
* MappingVariesByDestIP: false
* Nearest DERP: Hong Kong (124.2ms)

两端都是教科书级的"好 NAT",理论上必通。实际结果:

复制代码
$ tsping --c 20 100.80.171.73
pong from titan (100.80.171.73) via DERP(hkg) in 414ms
pong from titan (100.80.171.73) via DERP(hkg) in 413ms
...(20发全部如此)
2026/08/24 03:10:08 direct connection not established

20 发全走香港中继,延迟稳定在 410ms 左右,SSH 卡得没法用。

此时体感对比:frp 反而更快(我的 VPS 在国内,链路是两段短程;DERP 绕香港还叠加共享限速)。

诊断结论:netcheck 只测出站映射的规律性,测不出"入站包能否到达你"。家宽运营商 CGNAT 会过滤入站 UDP,校园网防火墙也可能拦入站方向------两边都拦,STUN 打洞的双向探测就永远碰不上。纸面参数全好但打洞失败,基本就是这个原因。

六、解法:Peer Relay,把中继搬回国内

打洞失败不等于放弃。Tailscale 从 1.86 开始支持 Peer Relay:把自己 tailnet 里的某台机器指定为中继节点,打洞失败时流量优先走它,而不是境外 DERP。

我的 frp VPS(华为云北京)正好是现成的中继位。配完后链路变成:

复制代码
Mac ──→ 国内VPS(peer relay) ──→ 校内服务器     ← 与frp同路径,但全端口通用
Mac ══════════════════════════→ 校内服务器     ← 哪天能直连则自动升级

优先级自动排序:直连 > peer relay > DERP,无需手动切换。

配置步骤(VPS 上三条命令)

bash 复制代码
# 1. 安装并登录同一账号
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

# 2. 指定为 relay 节点,监听 UDP 40000
sudo tailscale set --relay-server-port=40000

# 3. 云厂商安全组放行 UDP 40000 入站(控制台操作)

ACL 授权

管理后台 → Access controls,JSON 里加一条 grant(dst 必须填完整的 MagicDNS 域名或 Tailscale IP,裸短主机名会报 invalid address):

json 复制代码
{
  "grants": [
    {
      "src": ["autogroup:member"],
      "dst": ["100.127.83.114"],
      "app": { "tailscale.com/cap/relay": [] }
    }
  ]
}
  • src: ["autogroup:member"] = 我名下所有设备都可使用 relay。官方不建议写 "*"(会把 tailnet 里所有设备包括未来新加入的都压到这台 VPS 上);
  • dst 填 VPS 的 Tailscale IP(VPS 上 tailscale whoami 查看);
  • 保存即生效,客户端几十秒内拉取新策略,不用重启。

验证

bash 复制代码
$ tsping 100.80.171.73
pong from ... via peer-relay(100.127.83.114:40000:vni:619) in ~xx ms   ← 生效

也可以 tailscale status | grep peer-relay 检查连接类型。

七、结果:意外之喜,直连成功

ACL 保存后再测,惊喜来了:

复制代码
$ tsping 100.80.171.73
pong from school-244 (100.80.171.73) via 223.100.xxx.xxx:41641 in 29ms

直接打到学校出口的公网端口------直连,29ms。 比 DERP 的 410ms 快了 14 倍。

推测是 VPS 加入 tailnet 后触发两端重新交换端点信息,凑齐了此前缺失的打洞条件(也可能是时间差让某端 NAT 映射刚好可用)。不管具体机制如何,结论是:别在第一次打洞失败时就弃坑,把基础设施(relay 节点、ACL)铺好,多给几次协商机会。

最终形态:

指标 frp Tailscale (DERP) Tailscale (直连)
SSH RTT 两跳国内 ~410ms 29ms
带宽上限 VPS带宽 共享限速 两端裸带宽
新增服务 加规则 无需配置 无需配置

iperf3 实测方法(服务器起 iperf3 -s,Mac 上):

bash 复制代码
iperf3 -c 100.80.171.73 -t 10 -P 4      # 上行
iperf3 -c 100.80.171.73 -t 10 -P 4 -R   # 下行

测速时务必另开终端跑 tsping 确认当前是 via IP:port 还是 via DERP------前者才是有效数据。

八、避坑清单

  1. Mac 没有 tailscale 裸命令 ,CLI 在 /Applications/Tailscale.app/Contents/MacOS/Tailscale,先加 alias。
  2. tailscale pingping。判断路径只能用前者。
  3. 服务器记得 Disable key expiry,否则 180 天后掉线。
  4. Peer Relay 要求三端 Tailscale ≥ 1.86 ,老版本先 sudo tailscale update
  5. ACL 里 dst 不认短主机名 ,报 invalid address 就换成完整 MagicDNS 名或 100.x IP。
  6. netcheck 参数好≠打洞必成,CGNAT 过滤入站是 netcheck 看不见的。失败时别急着换工具。
  7. /var/lib/tailscale/ 别删 ,登录凭据都在 tailscaled.state 里,删了要重新认证。
  8. iOS/Android 不能当 relay 节点,但可以作为使用者。

九、总结

  • frp 解决的是"暴露端口",异地组网该用的是"虚拟局域网",两者不是竞品而是不同抽象层。
  • Tailscale 的体验取决于打洞是否成功,netcheck + tailscale ping 两个命令即可完成全链路诊断。
  • 打洞失败时的正确姿势不是退回 frp,而是自建中继:Peer Relay 把境外 DERP 换成自己的国内 VPS,速度下限追平 frp,上限是直连裸带宽。
  • 我的案例最终以 29ms 直连收尾,frp 退役。

环境备注:Ubuntu 22.04(校内 Dell 机架服务器)/ macOS + Tailscale App / 华为云北京轻量服务器作 relay / 三端版本 1.86+。

相关推荐
FIT2CLOUD飞致云12 小时前
GPU监控支持华为昇腾设备,防火墙管理焕新,虚拟机管理下放至专业版,1Panel v2.3.0版本发布
运维·ai·开源·1panel·运维面板
一只小李郁vickie12 小时前
Redis 集群部署手册(3主3从)
运维·redis
牢姐与蒯12 小时前
Linux文件(三).Ext系列文件系统
linux·运维·服务器
懂软件的胡子个哥12 小时前
微信工单系统如何基于 WechatApi 做消息分流和状态流转
运维·分布式·微信·架构·企业微信
进击的荆棘13 小时前
Linux系统——进程控制(下)
linux·运维·服务器·进程
优化Henry14 小时前
学习笔记之关于MME不通问题归纳
运维·网络·学习·5g·信息与通信
考虑考虑20 小时前
数据库中的EXISTS
运维·数据库·后端
天远数科1 天前
零信任架构实战:基于天远全能消金报告构建自动化信贷评估网关
运维·人工智能·架构·自动化
网硕互联的小客服1 天前
各个版本的Linux系统如何修改远程端口ssh端口?
linux·运维·服务器·网络
Mr小林1 天前
Docker 安装教程(在线 + 离线)
运维·docker·容器