这次排障从一个很普通的 Karing 报错开始:订阅链接导入失败,节点测速大片红。最后一路查到了云防火墙、订阅格式、AWS hostname、Cloudflare Tunnel、SSH 私钥迁移,以及一组不值得继续投入的 ShadowTLS 节点。

记录下来,是因为这类问题很容易让人误判。Karing 只是报错入口,真正的问题分散在云平台、VPS、订阅生成脚本和客户端兼容性之间。

FinalShell 中五台 VPS 已可连接,公网 IP 已打码

先说结论

这次最后留下的判断是:

  • Karing 订阅导入失败,不一定是 Karing 的格式问题,很多时候是订阅 URL 的 HTTP 连接没有完整返回。
  • 节点大面积红,先看云防火墙和安全组,再看 VPS 内部服务。
  • Karing 更适合导入脚本生成的 sing-box 订阅,而不是拿 v2rayn 链接硬试。
  • AWS 节点名显示成 ip-172-xx-xx-xx,是 EC2 默认 hostname 被写进了订阅 tag。
  • ShadowTLS 那两条红节点,本质是组合节点和内部承载节点的显示问题,暂时不值得修。
  • SSH 管理上,最好准备一个可迁移的登录资料包,但私钥要按敏感文件处理。

下面按时间线整理。

一、订阅导入失败:先判断 URL 是否真的能返回

Karing 一开始报:

1
2
download profile failed:
Connection closed before full header was received

这个提示的关键不是“订阅格式错了”,而是客户端连上后没拿到完整 HTTP 响应。也就是说,第一步应该检查订阅 URL 能不能从公网访问,而不是马上重装脚本。

我们在 VPS 本机测了订阅服务:

1
curl http://127.0.0.1:220/****/v2rayn

本机能返回内容,说明 VPS 内部的 nginxsing-box 大体是工作的。问题转到公网路径:云防火墙有没有放行 220,节点端口有没有放行,客户端是不是能打到这台机器。

这一步很重要。服务在本机活着,不等于公网能访问。

二、GCP 是云防火墙没放行

Google Cloud 那台 VPS 的情况比较典型。脚本已经在服务器里监听了订阅端口和节点端口,但 GCP VPC 防火墙没有放行完整端口。

最后放行的是这类端口组合:

1
2
TCP: 220, 8881, 8884, 8885, 8886, 8889, 8890, 8891, 8892
UDP: 8882, 8883, 8885, 8892

这里不放公网 IP 和订阅 UUID。关键是思路:脚本用到哪些入站端口,云厂商防火墙就要放哪些。GCP 默认的“允许 SSH/HTTP/HTTPS”并不覆盖这些自定义端口。

放行后,订阅能稳定导入,节点也恢复到大部分可用。

三、Cloudflare Tunnel 只是解决订阅下载,不代表直连节点通

中间用过 trycloudflare.com 的临时 tunnel 链接。这个链接能让 Karing 下载订阅,因为它走的是 Cloudflare Tunnel:

1
2
VPS -> Cloudflare
Karing -> Cloudflare URL

普通直连节点则是:

1
Karing -> VPS 公网 IP:888x

两条路径不一样。Tunnel 能用,只能说明订阅下载这条路暂时通了;节点直连是否可用,还要看云防火墙、安全组和 VPS 监听端口。

这个区别很容易被忽略。

四、Karing 订阅要用 sing-box 后缀

同一个脚本会生成多种订阅格式。Karing 里如果用 v2rayn 后缀,可能只导入部分节点,或者节点结构不完整。

后来统一改成:

1
http://x.x.x.x:220/****/sing-box

这样 Karing 能看到完整的 14 条节点。这个步骤应该写进自己的部署流程里,尤其是以后换 VPS、换客户端时,不要靠记忆。

五、AWS 节点名为什么都是 ip-172

AWS 的两台 VPS 导入后,节点名一开始是:

1
2
3
ip-172-31-xx-xx xtls-reality
ip-172-31-xx-xx hysteria2
...

这不是订阅链接写错,也不是 Karing 自己改名。根因是 AWS EC2 默认 hostname 就是这种内网 DNS 名:

1
2
hostname
# ip-172-31-xx-xx

fscarmen 的 sing-box 脚本生成订阅时,把系统 hostname 放进了节点 tag。GCP 那两台之所以好看,是因为 hostname 已经是自定义名称。

修复方式是把 AWS 的 hostname 改成 VPS 名称,并同步替换已生成的订阅文件:

1
2
3
4
hostnamectl set-hostname aws-***-vps-nv
echo aws-***-vps-nv > /etc/hostname
sed -i 's/ip-172-31-xx-xx/aws-***-vps-nv/g' /etc/hosts
find /etc/sing-box/subscribe -type f -maxdepth 1 -exec sed -i 's/ip-172-31-xx-xx/aws-***-vps-nv/g' {} +

操作前先备份 /etc/sing-box/subscribe。这样就算替换错了,也能回滚。

Karing 中 AWS 节点已从内网 hostname 改为 VPS 名称,侧边栏已打码

六、AWS 有一台最后选择重建

有一台 AWS VPS 的 SSH 登录入口丢了:端口能通,但私钥、密码、EC2 Instance Connect 都进不去。

尝试过通过 User Data 注入公钥,实例启动后依然无法登录。这个时候继续做 EBS 离线挂盘当然可以,但如果机器没有重要数据,重建更划算。

这次最后就是重建了那台 AWS,然后重新导入私钥,确认 Termius 和 FinalShell 都能登录。

这里的经验是:不要把“能不能修”当作唯一标准。个人 VPS 如果没有不可替代的数据,重建有时候是更干净的恢复路径。

七、做一个 VPS 登录迁移包

排障中还顺手整理了一个本地迁移包:

1
2
3
4
5
6
7
8
9
10
11
12
VPS登录/
README.md
PRIVATE-KEYS.md
hosts-template.csv
clients/
termius.md
finalshell.md
putty.md
openssh.md
keys/
aws-***.pem
aws-***.pem

里面记录每台 VPS 的名称、云厂商、登录用户名、端口、认证方式和对应私钥。真正的私钥放在 keys 目录,但这个文件夹从此就要按敏感资料处理,不能上传 GitHub,也不要丢进普通网盘。

FinalShell 最后五台都连通了。这个结果很实用:以后换电脑,直接按这份表导入 Host 和 Identity,不用再从聊天记录里翻 IP、用户名、私钥文件。

八、为什么 ShadowTLS 两条还是红

最后剩下一个现象:几乎所有订阅里都有两条 ShadowTLS 相关节点红。

查配置后发现,它不是普通单节点结构,而是组合结构:

1
2
3
4
5
6
7
8
ShadowTLS 节点
type = shadowsocks
detour = shadowtls-out

shadowtls-out
type = shadowtls
server = VPS
port = 8884

shadowtls-out 更像内部承载层,不应该被当成独立节点直接选择。Karing 把它显示出来并测速失败,不一定代表服务端坏了。

这件事暂时不修。原因很简单:其他 12 条节点已经稳定可用,ShadowTLS 不是刚需;强行改订阅生成逻辑,后面脚本更新还可能被覆盖。更稳的做法是把它当作“客户端显示层的小瑕疵”,先记录,不消耗时间。

排障时用到的判断顺序

以后再遇到类似问题,我会按这个顺序来:

1
2
3
4
5
6
7
1. 订阅 URL 能不能公网下载
2. VPS 本机 curl 是否能返回订阅
3. ss 查看服务是否监听
4. 云防火墙 / 安全组是否放行
5. 客户端订阅格式是否匹配,比如 Karing 用 sing-box
6. 节点名是否来自系统 hostname
7. 剩余失败节点是否真的值得修

这套顺序比“重启、重装、换客户端”省时间。

最后

这次排障最有价值的不是某条命令,而是把问题拆开了。

订阅下载是一条链路,节点连接是另一条链路;云防火墙是一层,VPS 内部服务又是一层;SSH 登录资料也不能只靠某个客户端保存。把这些边界分清以后,问题就不再混在一起。

最终结果是:五台 VPS 都能通过 FinalShell 登录,Karing 订阅能正常导入,AWS 节点名也改成了可识别的 VPS 名称。剩下的 ShadowTLS 两条红节点,先不处理。