一次 Tailscale + Clash Party 排障复盘:别被 nslookup 带偏
一次 Tailscale + Clash Party 排障复盘:别被 nslookup 带偏
日期:2026-05-23 场景:本地开着 Clash / Mihomo,访问 Tailscale 内网域名
*.ts.net症状:nslookup返回NXDOMAIN,代理转发访问失败
背景
这次问题表面上很简单:
1
nslookup pi5-memect-dev.tail9733c5.ts.net
返回:
1
server can't find pi5-memect-dev.tail9733c5.ts.net: NXDOMAIN
第一眼很容易得出结论:Tailscale 的 MagicDNS 挂了,或者 Clash 把系统 DNS 搞坏了。
但这次真正有价值的地方,不是把问题修掉,而是把排障路径复盘清楚。因为中间有几次判断差点把人带进错误方向。
先说结论
最后确认的问题根因不是单一故障,而是两层问题叠在一起:
nslookup本身会绕过 macOS 的 split DNS,直接走公共 DNS,所以它对*.ts.net的报错有误导性。- Clash Party / mihomo 内部 DNS 确实没有正确为 Tailscale 域名做分流,导致代理场景下解析失败。
最终修复点是:
1
2
3
nameserver-policy:
"+.ts.net": "100.100.100.100"
"+.tailscale.net": "100.100.100.100"
重点不是 100.100.100.100 这个地址本身,而是:
- 要把 Tailscale 域名交给它自己的 DNS 解析器
- 模式必须用
+.ts.net - 不能写成
*.ts.net
排障过程里最重要的几个转折
1. 不要只盯着 nslookup
一开始看到 NXDOMAIN,最自然的推断是:
- Clash 接管了 DNS
*.ts.net被发给了 8.8.8.8- 公共 DNS 不认识 Tailscale 域名
这个方向不算错,但不完整。
后面继续看系统 DNS 配置时,发现 macOS 的 resolver 里其实已经存在针对 tail9733c5.ts.net 的专用解析器,nameserver 正是 100.100.100.100。这说明:
- Tailscale 自己的 split DNS 是正常的
- 系统级解析能力并没有坏
nslookup只是没有按我们以为的那样走系统 resolver
这一步的经验非常关键:
nslookup 只能说明某个 DNS server 的结果,不等于说明系统真实访问路径。
排障时至少要把下面几类验证分开看:
- 工具层验证:
nslookup/dig - 系统层验证:
scutil --dns、系统 resolver - 真实业务验证:
curl、ssh、浏览器、WebSocket
2. 真实流量比配置文件更能说明问题
后面做了一次关键验证:
- 直接访问目标服务,WebSocket 可以
101 Switching Protocols - 通过 Clash 代理访问时,TLS 握手阶段报
SSL_ERROR_SYSCALL
这说明:
- 服务端没挂
- Tailscale 网络本身没挂
- 问题发生在代理链路内部
很多时候我们喜欢围着配置文件打转,但更有效的方式其实是先判断:
失败发生在“解析前、连接前、TLS 阶段,还是应用层”。
这次就是因为真实流量验证把范围快速缩小到了 Clash 内部 DNS。
3. 改“运行时文件”不等于真正修好
中间还踩了一个很常见的坑:找到运行中的生成配置,直接改,表面上看也改成功了,但 reload 后不生效,或者一重启就被覆盖。
这类代理工具通常会有几层配置:
- 持久化基础配置
- 订阅合并后的运行时配置
- 内核当前已加载配置
如果只改了运行时产物,结论往往是不稳定的。
这次后面真正有效的做法,是去找 持久化的基础配置入口,而不是盯着临时生成文件。
经验是:
看到 “Generated by …” 之类的文件时,先别急着改,先确认它是不是最终可持续的配置源。
4. *.ts.net 和 +.ts.net 不是一回事
这是本次排障里最值钱的细节。
一开始写的是:
1
2
nameserver-policy:
"*.ts.net": "100.100.100.100"
看起来很合理,但对 pi5-memect-dev.tail9733c5.ts.net 这种域名并没有匹配成功。
原因是它不是简单的一层子域名,而是更深层级。对 mihomo 来说,这里要用 +.ts.net。
准确写法是:
1
2
3
nameserver-policy:
"+.ts.net": "100.100.100.100"
"+.tailscale.net": "100.100.100.100"
这一步之后,再 reload 并重新走代理链路,TLS 握手才恢复正常。
这类问题的经验不是“记住某个语法”,而是:
域名匹配规则必须拿真实目标域名去验证,不要凭感觉。
这次排障值得固化的工作方法
如果以后再遇到“代理 + 内网域名 + DNS 解析异常”,我会按这个顺序处理:
1. 先分层,不要混着看
- 系统 resolver 是否正常
- 目标服务是否正常
- 代理内核是否能独立解析该域名
- 代理后的真实请求是否成功
2. 不要把 nslookup 当成最终证据
尤其在 macOS、Tailscale、split DNS、企业 VPN 这类场景下,nslookup 很容易误导。
3. 优先做端到端验证
比起“配置看起来对了”,我更信:
curl能不能通- WebSocket 能不能
101 - 代理后的 TLS 握手能不能完整走完
4. 先找到持久化配置入口
不要只改生成产物,不然很容易出现:
- reload 不生效
- 重启丢配置
- 订阅一更新又回滚
5. 域名规则必须用真实样本验证
像 *.ts.net 和 +.ts.net 这种差异,单看配置很难一眼看出,必须用真实域名验证命中情况。
最后总结成一句话
这次排障最值得记住的,不是 “给 Tailscale 配一个 nameserver-policy”,而是:
当系统里同时存在 split DNS、代理 DNS、生成配置和运行时内核时,任何单点工具输出都不该被直接当成结论。
真正有效的排障,不是更快地下判断,而是更早地把“哪一层在失败”分清楚。
这也是 AI Agent 协作里很有意思的一点:Agent 可以很快帮你做搜索、改配置、反复验证,但人还是要盯住判断框架,否则很容易被一个看似合理的中间结论带偏。