阿里云 CGNAT 地址与 Tailscale 的 DNS 冲突:一次真实的排查记录与可行方案
本文基于一次真实案例,记录一台阿里云 ECS 在启用 Tailscale 后突然失去外网访问能力的全过程,并给出五种经过验证的解决方案,帮助你在不牺牲功能的前提下优雅地规避冲突。
目录
-
问题现象:服务器突然“失联” -
初步排查:把嫌疑锁定在 DNS -
深入追踪:Tailscale 的防火墙规则 -
根源分析:RFC 6598 与阿里云 CGNAT 地址 -
五种可行方案与利弊对照 -
如何快速验证方案是否生效 -
小结与下一步建议
1. 问题现象:服务器突然“失联”
在阿里云(华北 2,VPC 网络)上运行的 Ubuntu 22.04 ECS,原本通过 Tailscale 与多台节点组成了一个虚拟子网。某天运维同事反馈:
-
☾ SSH 还能连上(走 Tailscale 虚拟网卡 tailscale0
)。 -
☾ 但服务器本身无法 curl https://example.com
,也无法apt update
。 -
☾ 重启 Tailscale 服务后短暂恢复,几分钟后再次失去外网。
2. 初步排查:把嫌疑锁定在 DNS
2.1 看网络通不通
IP 层没问题,继续看 DNS:
100.100.2.136 正是阿里云内网 DNS 的默认地址。DNS 解析失败,服务器自然“失联”。
2.2 怀疑 Magic DNS
Tailscale 的 Magic DNS 会把节点名解析为 100.x 地址。最初我们怀疑是 Magic DNS 把系统 /etc/resolv.conf
改坏了,于是关闭 Magic DNS:
重启 Tailscale,问题依旧。Magic DNS 并不是真凶。
3. 深入追踪:Tailscale 的防火墙规则
3.1 打印 iptables 日志
为了把包到底被哪条规则丢掉,我们在 filter
表上加 LOG:
复现问题后查看 /var/log/kern.log
,发现:
包被丢弃,但还不知道是哪条规则干的。
3.2 找到 Tailscale 注入的规则
这条由 tailscaled
自动插入的规则意思是:
-
☾ 源地址在 100.64.0.0/10
(即 CGNAT 段); -
☾ 不是从 tailscale0
网卡进来的包; -
☾ 直接丢弃。
阿里云内网 DNS 的地址 100.100.2.136
刚好落在这个段内,于是被误杀。
4. 根源分析:RFC 6598 与阿里云 CGNAT 地址
4.1 什么是 CGNAT
100.64.0.0/10
在 RFC 6598 中被保留为 运营商级 NAT (Carrier-Grade NAT) 地址段,用于 ISP 做 NAT 时避免与内网冲突。Tailscale 把它当成“只允许来自 Tailscale 接口的地址段”是符合规范的。
4.2 阿里云为何用 CGNAT 当内网 DNS
阿里云在 VPC 内把 100.100.2.136
、100.100.2.138
作为内网 DNS 服务地址,初衷是:
-
☾ 地址在公网不可路由,避免外泄; -
☾ 与经典网络互通时不会冲突。
但这与 RFC 6598 的本意并不完全一致,于是与 Tailscale 的默认防火墙策略产生了冲突。
5. 五种可行方案与利弊对照
下面给出五种经过验证的方案,按“侵入性”从低到高排序。你可以根据业务场景挑一条最合适的。
5.1 方案 ①:临时删除规则
验证:
能解析即成功。但重启 Tailscale 后规则会再次出现。
5.2 方案 ②:插入白名单
建议把这两条写进 /etc/rc.local
或 systemd service,确保开机后最早执行。
5.3 方案 ③:守护脚本
/usr/local/bin/fix-ts-dns.sh
配合 systemd service:
5.4 方案 ④:改用公共 DNS
如果你用 NetworkManager,把 DNS 改为 8.8.8.8,1.1.1.1
并重启连接即可。
注意:OSS、RDS、SLB 的内网域名将解析成公网地址,流量会走公网,可能 产生额外费用 或 性能下降。
5.5 方案 ⑤:关闭 Tailscale 防火墙
验证:
应无任何 ts-
链。副作用是:
-
☾ 不能通过 Tailscale 子网路由访问局域网; -
☾ 不能当 exit-node; -
☾ 不能限制来源流量。
6. 如何快速验证方案是否生效
-
DNS 测试
出现 IP 即成功。
-
外网连通性
-
Tailscale 功能
-
规则持久化
重启机器或systemctl restart tailscaled
后再次检查,确保规则仍在。
7. 小结与下一步建议
-
☾ 冲突本质:Tailscale 遵循 RFC 6598,阿里云把 CGNAT 段用作内网 DNS,二者目标不同导致“误伤”。 -
☾ 最稳妥方案:在 Tailscale 的 ts-input
链最前面插入两条白名单,配合 systemd 守护,兼顾功能与稳定。 -
☾ 长期展望:已向阿里云和 Tailscale 双方反馈,未来版本可能内置豁免逻辑,届时可移除临时脚本。
如果你在实施过程中遇到新的状况,欢迎在评论区留言,一起把踩过的坑补全,让更多运维同学少走弯路。