起因
在我部署完自己的 Headscale 之后,有个朋友和我说 Tailscale 这玩意路由配置有点坑,有个朋友就是因为这个问题而放弃了 Tailscale 选择了 Netbrid,问题就是会强制路由 100.64.0.0/10 网段到 Tailscale,即使使用 Headscale 分配其他网段也是一样会吃
复现
由于这个问题不是我发现的,但是由于我自己用的就是 Tailscale,并且这个网段也的确很有可能后面会在内网用到,尤其是运营商,所以还是选择去尝试解决一下
要复现其实很简单,PING 100.64.0.0/10 网段内的任一 IP 即可,由于我本地没有用到这个网段,所以想了一下,可以通过 PING 阿里云的内网DNS(100.100.2.148 - mirrors.cloud.aliyuncs.com)来测试

(刚好用带学生300优惠券用36R白嫖了一台阿里云HK轻量一年)
排查
由于朋友他们已经抓过包确定排除掉了很多问题,并且确定就是 Tailscale 吃的,所以直接看看 Tailscale 在本地都干了什么,目标很明确
DNS?
由于不只是域名不通,连 IP 也不通所以,不考虑是 DNS 的问题
路由表?
一开始想的可能是 Tailscale 路由了整个 100.64.0.0/10,毕竟我当时给 Headscale 分配的是 100.100.0.0/16,/16依然是/10范围内的,有没有可能是整段都吃了,但

能看到 100.100.0.*/32 的路由,分配的都是/32的单设备地址,不可能把整个/10吃掉,所以路由表也是正常的
而且通过get命令也能看出路由是正常的

防火墙?
另一个对数据包产生影响的可能就是防火墙了,所以喵了一眼防火墙的规则

由于我使用的是 Alpine v3.22,所以防火墙是 nftables,如果是 iptables 把nft改为iptables即可
在这里看到了一个关键的规则:
iifname != "tailscale0*" ip saddr 100.64.0.0/10 counter packets 6 bytes 568 drop
在iptables应该是-A ts-input -s 100.64.0.0/10 ! -i tailscale0 -j DROP
这条规则丢弃了整个 100.64.0.0/10 的数据包,通过nft delete删除规则就通了,但这是治标不治本
解决
知道了问题根源后,我就开始了查找资料,在github的issue那边有看到有人也反馈过:
Tailscale iptables rules blocks any non-tailscale IP on 100.64.0.0/10 from working
解决起来不难,全局设置 Tailscale 的 netfilter 为 off/nodiver,或者在启动时加上即可
# 全局设置
sudo tailscale set --netfilter-mode=nodivert
#非全局设置 其他参数自行补充
sudo tailscale up --netfilter-mode=nodivert对于netfilter-mode官方的解释如下(GPT翻译):
--netfilter-mode(仅限 Linux)
这是一个高级功能,用于控制 Tailscale 对防火墙的自动配置程度。
- 可选值:
off、nodivert或on。 - 默认值为
on(除了 Synology,默认是off)。
各选项说明:
off- 禁用所有 netfilter(iptables/nftables)管理。
- 意味着 Tailscale 不会自动配置防火墙,完全由管理员负责。
nodivert- 创建并管理 Tailscale 的子链(sub-chains),
- 但 调用这些子链的工作由管理员自己负责。
- 简单说,规则存在,但不会自动生效,需你手动把它们挂到主链上。
on- 完全管理 Tailscale 的防火墙规则。
- Tailscale 会自动创建子链、挂载到主链,并管理允许的流量。
注意:
如果你设置为off或nodivert,你需要自己 确保防火墙安全地允许 Tailscale 流量。
官方推荐 以--netfilter-mode=on安装的规则为起点,再根据需要修改。
结论
所以说,引起这个问题的是 Tailscale 设置的一条防火墙规则,但是为什么要设置这个呢?
官方提到是为了防止 VPN 流量从错误的接口泄露,例如 CVE-2019-14899 漏洞,由于tailscale的网段是100.64.0.0/10,所以它选择了强行让所有这个网段的流量都只能走 tailscale0 这个接口
但是 Tailscale用的网段 100.64.0.0/10 同时也是 运营商级NAT(Carrier Grade NAT, CGNAT),它是假设不会被私有网络使用的,一旦内网里面的服务也用了这个网段,就会出现不通的问题,所以我后面也换用了更不容易冲突的 10.12.12.0/23
最后,问题虽然解决了,但是也留下了安全隐患,如果你实在是担心这个漏洞的攻击会影响到你,你可以不设置成 off 而是 nodivert 然后手动按需调用
2 条评论
我喜欢你
能掌控复杂系统、能搞清楚原理,总是让人心潮澎湃
我喜欢你