前情提要:使用99计划的阿里云ECS部署相关服务,并接入到Tailscale网络中,使得本机可以通过Tailscale访问ECS服务且无需在ECS安全组做放行操作

问题产生

  在执行完Tailscale的部署操作后,本地电脑可以正常访问Tailscale分配给ECS的100.xx.xx.xx的网络服务。但是次日发现,ECS的Debian无法进行apt更新操作,提示无法解析mirrors.cloud.aliyuncs.com。并且在尝试ping该域名也无法正确解析到该域名的ip。尝试nslookup mirrors.cloud.aliyuncs.com,提示communications error to 100.100.2.136#53: timed out

问题排查

1.怀疑DNS问题
  首先,我想到的是会不会Tailscale的Magic DNS影响到了ECS的内网DNS,虽然在检查了/etc/resolv.conf确定nameserver配置没有问题,但不确定Tailscale会不会通过其他方式覆盖本机的DNS。所以我关闭了Tailscale控制台的MagicDNS,以及取消掉Global nameservers的Override local DNS选项。ECS客户端加上不使用tailscale DNS的参数sudo tailscale up --accept-dns=false。 但是从结果上来看,依然无法解析域名,且根据nslookup的报错,貌似ECS还是使用的内网DNS,并没有被覆盖。在尝试ping后发现,内网DNS是不通的。

2.怀疑阿里云内网DNS出现问题
  其实现在想想,还是应该充分分析一下,确定不是自己的这边的问题后再考虑是不是平台的问题,例如暂时把最近新部署的东西都停掉,做一下对照实验等。但因为问题产生于2024年6月9日,这个时间段确实比较特殊,所以不得不怀疑是不是阿里云那边在改什么东西影响到我这边的内网DNS解析了。提交工单后,得到的结果是内网DNS解析正常。

PS: 有个小插曲,就是阿里的工程师帮我查看故障的时候,我的Tailscale还在运行,他那边疯狂的排查我的ECS的DNS,然后改nameserver。最后发现,他最开始给我反馈的所谓正常的apt源地址打错了,直接解析到美国去了。后来我这边把Tailscale关掉了,解析也正常了。

3.怀疑网段冲突
  在确定阿里那边没有问题之后,又回到了Tailscale这里。开始怀疑网段的问题,因为这个问题我在另一台JD轻量云和我自己的主服Vultr上做了对照实验,均没有发现这个问题。那么唯一的变量就是阿里的内网DNS网段比较特殊,是运营商NAT保留地址100.64.0.0/10,同时也是Tailscale默认的地址池。那么这就可能存在网段冲突、路由等一系列问题。

sudo ip route list table all | grep 100
# ip为100开头的ip路由表
100.xxx.0.1 dev tailscale0 table 52
100.xxx.0.2 dev tailscale0 table 52
100.xxx.0.3 dev tailscale0 table 52
100.xxx.0.4 dev tailscale0 table 52
100.xxx.0.5 dev tailscale0 table 52
100.xxx.0.6 dev tailscale0 table 52
100.xxx.0.10 dev tailscale0 table 52
100.xxx.0.93 dev tailscale0 table 52
100.100.100.100 dev tailscale0 table 52
100.100.2.136 via 172.xxx.xxx.xxx dev eth0 proto dhcp src 172.xxx.xxx.xxx metric 100
100.100.2.138 via 172.xxx.xxx.xxx dev eth0 proto dhcp src 172.xxx.xxx.xxx metric 100

  根据路由表显示的结果来看,Tailscale只是路由了他分配的地址,且阿里的内网DNS路由到正确的eth0,没有问题。

4.怀疑防火墙规则
  也是我个人经验不足,应该很早想到这个问题。因为Firewalld用的多了,就忽略了iptables(主要也确实没想到Tailscale会给防火墙做规则)在Bing了一下关于Tailscale与阿里云ECS的相关关键字后,发现不只是我一个人遇到了这个问题。
  查询参考了以下大佬的文章:Tailscale出口节点无网络问题的调试与分析 Tailscale 与阿里云八字不合的解决方法,发现Tailscale默认会增加iptables规则。

sudo iptables -S | grep -i tailscale0
# 防火墙规则
-A ts-forward -i tailscale0 -j MARK --set-xmark 0x40000/0xff0000
-A ts-forward -s 100.64.0.0/10 -o tailscale0 -j DROP
-A ts-forward -o tailscale0 -j ACCEPT
-A ts-input -s 100.115.92.0/23 ! -i tailscale0 -j RETURN
-A ts-input -s 100.64.0.0/10 ! -i tailscale0 -j DROP
-A ts-input -i tailscale0 -j ACCEPT

问题产生结论

  基于以上对iptables防火墙规则的分析,-A ts-input -s 100.64.0.0/10 ! -i tailscale0 -j DROP-A ts-forward -s 100.64.0.0/10 -o tailscale0 -j DROP所丢弃的网段正好包含阿里内网相关服务的网段100.100.xxx.xxx,从而导致相关内网服务数据包全部被iptables丢弃,最终ECS无法获取通过内网DNS返回的域名解析信息,以及其他内网相关服务。而对于其他云平台没有使用NAT保留地址,则不会受到该防火墙规则的影响。
  Tailscale增加这些防火墙规则推测主要是缓解CVE-2019-14899这个漏洞劫持VPN隧道TCP连接。

解决方案

  在启用Tailscale或者全局设置Tailscale的netfilter模式为off或nodivert

# 全局设置netfilter模式为nodivert,将创建和管理Tailscale子链,但将这些链的调用留给管理员。
# 全局设置Tailscale客户端接受Tailscale admin设置的dns
sudo tailscale set --netfilter-mode=nodivert --accept-dns=true
sudo tailscale up
# 非全局设置,仅限启用Tailscale时生效
sudo tailscale up --netfilter-mode=nodivert --accept-dns=true

PS: 对于--netfilter-mode参数,官方文档解释如下:

--netfilter-mode (Linux only) Advanced feature for controlling the degree of automatic firewall configuration. Values are either "off", "nodivert", or "on". Defaults to "on", except for Synology which defaults to "off". Setting this flag to "off" disables all management of netfilter. Setting to "nodivert" creates and manages Tailscale sub-chains, but leaves the calling of those chains up to the administrator. Setting to "on" means using full management of Tailscale's rules. Note that if you set --netfilter-mode to "off" or "nodivert", it is your responsibility to configure the firewall securely for Tailscale traffic. We recommend using the rules installed by --netfilter-mode=on as a starting point.

--netfilter-mode(仅限 Linux)用于控制防火墙自动配置程度的高级功能。值为“off”、“nodivert”或“on”。默认为“on”,但 Synology 除外,其默认为“off”。将此标志设置为“off”将禁用所有 netfilter 管理。设置为“nodivert”将创建和管理 Tailscale 子链,但将这些链的调用留给管理员。设置为“on”意味着使用 Tailscale 规则的完全管理。请注意,如果您将 --netfilter-mode 设置为“off”或“nodivert”,则您有责任为 Tailscale 流量安全地配置防火墙。我们建议使用通过 --netfilter-mode=on 安装的规则作为起点。

对于--accept-dns参数,官方文档解释如下:
--accept-dns Accept DNS configuration from the admin console. Defaults to accepting DNS settings.
--accept-dns 从管理控制台接受 DNS 配置。默认接受 DNS 设置。