本文所有 IP、域名均已脱敏。这不是一篇「我解决了一个难题」的爽文,而是一篇反面教材——记录一个排障者如何用一连串"看起来合理"的推断,把一个重启就能解决的问题,搞成了持续几小时的连环事故。
症状
那天在改自己的 PT 工具,改完要 scp 到 NAS 部署。忽然:
$ ssh [email protected]
Connection closed by 100.x.x.x port 22
同时:
pingNAS 通,0.3msnc -z探测 22 端口 通(TCP 能握手)- 但任何 TCP 连接(SSH、HTTP)都在精确 5 秒后被切断
- 而走 Cloudflare 隧道的公网域名访问 NAS 上的服务,一切正常
一个"网络通、端口开、但连接全废"的诡异局面。下面是我依次给出的五个结论,以及每一个错在哪。
误判一:「下载器把我的 IP 封了」
排查中确实发现 qBittorrent 返回了:
身份认证失败次数过多,您的 IP 地址已被封禁。
这条是真的,而且原因也确实是我的锅——我的程序没做连接复用,每推一个种子就重新登录一次,几千次错误登录触发了防爆破。
但它和 SSH 连不上没有因果关系。 我却把它当成了"整台机器出问题"的第一块拼图,开始沿着"NAS 出事了"这条路往下走。
教训:找到一个真问题 ≠ 找到了这个问题的原因。要问自己:它能解释我看到的全部症状吗? 显然不能——qb 封禁解释不了 SSH。
误判二:「sshd 挂了」
ssh -vv 显示断在:
debug1: Connection established.
kex_exchange_identification: Connection closed by remote host
连密钥交换都没开始就被掐。我据此断定:sshd 进程虽然"开关是开的",但实际没在服务。
于是让对方重启了 SSH 服务,没用;又重启了整台 NAS,还是没用。
错在哪:kex_exchange_identification 阶段被切,确实可能是服务端拒绝,但也可能是链路本身传不了数据。我把"可能"当成了"必然",而且没做任何能区分两者的实验就让人重启了设备。
误判三:「NAS 负载太高」
我 curl 面板域名,响应要 6.8 秒。“果然是 NAS 被压垮了”——毕竟当时后台确实在跑一个几千种子的批量任务。
错在哪:那 6.8 秒根本不是 NAS 慢,是我自己这台机器的网络绕了远路。我拿着一个受污染的指标当证据,还反过来"印证"了前面的错误结论。多个错误结论互相印证,会产生极强的虚假确信。
误判四:「防火墙把我拉黑了」
这个推断有一条"漂亮"的证据链:
- 从我这台机器过去,NAS 的所有端口(22 / 面板 / 后台)全部哑火
- 但走 Cloudflare 隧道访问同一个服务,完全正常
- 差别在于:隧道流量是 NAS 主动往外建立的,不经过我的入站 IP
推理很顺:一定是我之前十几次重试 SSH,触发了 NAS 的自动封锁,把我的 IP 拉黑了。我甚至查出了自己两个 IP,让对方去后台解封。
对方回:“我防火墙都没开啊。”
错在哪:我把"从我这里过去全废、从别的路径过去正常"解读成了"我被针对了"。但同样的现象还有一个更简单的解释——我这条路本身就是坏的。我选了一个需要对方配合、且不可证伪的解释,而不是先去检验自己脚下的路。
最致命的一条:测试路径本身就是假的
真正让我全程被带偏的是这个。我一直有两条"独立"的验证路径:
- 走 Tailscale 的地址
100.x.x.x - 走"局域网"地址
192.168.1.x
两条都失败,报错一模一样。我据此得出:「两条独立路径都失败 → 问题必然在服务端」。
直到很晚我才查了一下自己的网卡:
$ ipconfig getifaddr en0
10.228.120.96 ← 我的机器在 10.228.x 网段
$ route -n get 192.168.1.x
gateway: 10.228.120.72 ← 走本地网关出去了
我根本不在 NAS 所在的局域网里。 所谓"局域网直连",实际上是把包丢给了当前网络的网关;那个 ping 得通的 0.3ms,应答的是这边网络里的另一台设备,压根不是我的 NAS。
所谓"两条独立路径",其实是同一条路径(Tailscale),外加一个完全虚假的对照组。整个推理链的地基是空的。
教训:做对照实验前,先证明对照组本身成立。ping 通不代表你 ping 的是你以为的那台机器。
真正有用的两条命令
绕了这么久,真正给出答案的是这两条:
tailscale netcheck
* IPv4: yes, 1.2.3.4:34194 ← 出口 IP 是我代理服务器的地址(在美国)
* Nearest DERP: Dallas ← 我人在国内,最近中继却是达拉斯
* DERP latency: 全部 873~973ms ← 连东京节点都要 948ms
* MappingVariesByDestIP: true ← 严格 NAT,打洞无望
tailscale status --json
LastHandshake: 0001-01-01T00:00:00Z ← WireGuard 从未握手成功
RxBytes / TxBytes: 0 / 0 ← 一个字节都没通过
至此症状全部对上了:加密隧道从未建立,所以 TCP 连接被本地组件乐观接受、5 秒后因为对端无响应而关闭;而 ping 走的是控制层探测,不需要数据隧道,所以"能通"。
一句话总结这个陷阱:ping 通只能证明控制层活着,证明不了数据能流。
误判五:「代理规则劫持了 Tailscale」
有了 netcheck 的数据,我给出了第五个结论:代理软件把 Tailscale 的传输流量也接管了,甩去了大洋彼岸,900ms 的往返让握手必然超时。
这次方向是对的,数据也硬。我于是动手:从官方拉取中继服务器列表,给几十个网段加上"直连"规则。效果立竿见影——出口 IP 变回真实宽带、延迟从 900ms 降到 200 多毫秒、握手成功了。
但 TCP 依然不通。于是我继续折腾,反复用命令行强停强启 VPN,想"刷新"连接状态。
结果:把 Tailscale 的守护进程搞挂了。
$ pgrep tailscaled
(空)
对方那边的现象变成了:点"连接",立刻自动断开。**原本只是连不上,现在变成了彻底起不来。**我从排障者变成了故障源。
真凶
最后的解法是:重启电脑。
重启后,用完全没有改动过的原始代理配置:
* IPv4: yes, <真实宽带 IP>
* DERP latency: 205ms
$ ssh [email protected]
✅ 通了(代理同时开着)
真正的根因是 macOS 的网络扩展卡在了异常状态。它不会报错,只会让隧道静默失效。而我之前所有"精妙"的分析,分析的都是这个异常状态的下游表现。
更讽刺的是:我中途加的那几十条规则,虽然当时确实改善了延迟,但根本不必要——已经全部还原,系统照样正常。
复盘:错误是怎么滚起来的
发现一个真问题(下载器封禁)
└→ 当成了另一个问题的原因
└→ 推断"服务端挂了" → 让人重启服务、重启整机(无效)
└→ 拿被污染的延迟数据当"高负载"证据(互相印证,确信度飙升)
└→ 用虚假的对照组得出"两条路都断" → 断定被防火墙拉黑
└→ 反复重试 SSH / 反复切 VPN
└→ 把守护进程搞挂 = 制造了新故障
每一步单看都"合理",连起来就是一场灾难。错误推理的代价不是原地踏步,而是负数——它让人执行了无效的破坏性操作,还制造了新的故障来污染现场。
给未来的检查清单
如果你也遇到"网络通但连接全废",按这个顺序来:
- 先检验你的测试路径。
ping通的真是目标机器吗?你和它在同一个网段吗?route -n get <IP>看看包到底往哪走。 - 区分控制层和数据层。ICMP / 心跳能通,不代表隧道能传数据。对 Tailscale 就看
LastHandshake和RxBytes。 - 一个假设要能解释全部症状。解释不了的,就不是根因,顶多是并发的另一个问题。
- **优先"重启进程 / 重启机器"**这类低成本、可逆、能一次性清空状态的手段,再去改配置。顺序反了,你会在错误的状态上叠加错误的改动。
- 同一个失败动作不要反复重试。重试很少能救你,却经常触发防爆破、把服务搞卡死——制造二次故障,让现场更难读。
- 改配置前先备份,一次只改一个变量。否则你分不清是哪一下起了作用,也退不回去。
- 对别人说话时,分清"已验证的事实"和"我的猜测"。让人重启设备、改配置之前,证据的硬度要配得上代价。
尾声
这次的教训用一句话讲完就是:别盲目操作,多想一步。
排障的本质是做实验:提出假设 → 设计一个能证伪它的实验 → 再下结论。而我做的是:提出假设 → 找到一条支持它的现象 → 当作结论 → 让别人付出代价。
差别就在中间那一步。写下来,提醒自己。