背景

  1. 在火山引擎云服务器上安装好了 OpenClaw,并且按照官方文档安装 Tailscale 并启用 MagicDNS 后,再执行 apt 安装其他软件的时候失败
  2. 检查公网的 DNS 解析也发现出现超时(通过 nslookup zhenxxin.com) :
    ;; communications error to 127.0.0.53#53: timed out
    ;; communications error to 127.0.0.53#53: timed out
  3. 网络搜索一番可以确信是 Tailscale 的 MagicDNS 影响了我们机器的 DNS 解析。但是呢,又不想直接放弃 MagicDNS 这个有用的东西一禁了之(即启动时加上 --accept-dns=false)。因此我们有了如下目标:让服务器同时满足以下三点:
    • 能解析火山引擎内网服务(依赖内网 DNS)
    • 能使用 Tailscale MagicDNS(*.ts.net 域名)
    • 能正常解析公网域名

第一步:切换 resolv.conf 为 stub 模式

初始状态:/etc/resolv.conf -> /var/run/systemd/resolve/resolv.conf,内容为真实上游 DNS IP,DNS 请求绕过了 systemd-resolved 的 stub listener,导致 Tailscale 注入的 MagicDNS 规则完全不生效。

resolv.conf 切换为 stub 模式,让所有 DNS 请求走 127.0.0.53,再由 systemd-resolved 统一转发:

sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

同时将上游 DNS 写入 resolved 配置:

sudo mkdir -p /etc/systemd/resolved.conf.d/
sudo tee /etc/systemd/resolved.conf.d/upstream.conf << EOF
[Resolve]
DNS=100.96.0.2 100.96.0.3
FallbackDNS=1.1.1.1
DNSStubListener=yes
EOF

sudo systemctl restart systemd-resolved

重新执行 tailscale up --accept-dns 后,resolvectl status 已正确显示 MagicDNS 接管了 tailscale0 接口:

resolvectl status

第二步:定位真正的超时原因

切换后 nslookup 依然超时,查看 systemd-resolved 状态:

systemctl status systemd-resolved
systemd-resolved 日志不断报错

日志中反复出现:

Using degraded feature set TCP instead of UDP for DNS server 100.96.0.2
Using degraded feature set UDP instead of TCP for DNS server 100.96.0.2

说明 stub listener 正常,但它联系不上上游 DNS 100.96.0.2/3,在 TCP/UDP 之间反复重试导致超时。


第三步:确认上游 DNS 不可达

ip route get 100.96.0.2
ping -c 3 100.96.0.2
ip route show
路由表与 ping 结果

路由表显示 100.96.0.2 走 eth0,但 ping 100% 丢包

根因:火山引擎的 DNS IP 100.96.0.2/3 恰好落在 100.64.0.0/10 这个 CGNAT 地址段内,而 Tailscale 会无差别拦截这整个网段的所有流量。


第四步:找到 Tailscale 的拦截机制

查看策略路由:

ip rule show
ip rule show 输出

注意到 5270: from all lookup 52,这是 Tailscale 的私有路由表,优先级高于 main 表(32766)。

查看表 52 内容:

ip route show table 52

输出:

100.79.205.86 dev tailscale0
100.100.100.100 dev tailscale0
100.103.212.87 dev tailscale0
100.123.222.99 dev tailscale0

表 52 里并没有 100.96.0.x 的路由,说明问题不在路由层,继续排查 iptables:

iptables -L ts-input -n -v

ts-input 链中发现关键规则:

DROP  all  -- !tailscale0  *  100.64.0.0/10  0.0.0.0/0

所有从非 tailscale0 接口进来的 100.64.0.0/10 流量全部被 DROP,已命中 661 个包。这就是根因。


第五步:在 DROP 规则之前插入豁免规则

观察 ts-input 链中已有一条对 100.115.92.0/23 的 RETURN 豁免,照此模式为我们的 DNS IP 添加豁免,插在 DROP 规则之前:

iptables -I ts-input 2 -s 100.96.0.2/32 ! -i tailscale0 -j RETURN
iptables -I ts-input 3 -s 100.96.0.3/32 ! -i tailscale0 -j RETURN

测试:

ping -c 3 100.96.0.2   # 通了
nslookup zhenxxin.com      # 正常解析

第六步:持久化规则

由于系统 iptables 后端是 nftables:

iptables --version
# iptables v1.8.10 (nf_tables)

ts-input 链是 Tailscale 每次启动时动态创建的,重启后规则会丢失。因此最可靠的方式是通过 systemd drop-in,让规则在 Tailscale 启动后自动补充:

sudo mkdir -p /etc/systemd/system/tailscaled.service.d/
sudo tee /etc/systemd/system/tailscaled.service.d/dns-bypass.conf << 'EOF'
[Service]
ExecStartPost=/bin/sh -c 'sleep 2 && \
  iptables -I ts-input 2 -s 100.96.0.2/32 ! -i tailscale0 -j RETURN && \
  iptables -I ts-input 3 -s 100.96.0.3/32 ! -i tailscale0 -j RETURN'
EOF

sudo systemctl daemon-reload

验证:

sudo systemctl restart tailscaled
sleep 3
iptables -L ts-input -n -v | grep 100.96
ping -c 3 100.96.0.2
nslookup zhenxxin.com

重启整机后规则依然生效。


最终架构

应用程序
    │
    ▼
127.0.0.53  ← stub listener (systemd-resolved)
    │
    ├─── *.ts.net / MagicDNS 域 ──→ 100.100.100.100 (走 tailscale0)
    │
    └─── 公网 / 内网域名 ──────────→ 100.96.0.2 / 100.96.0.3
                                      (iptables 豁免,走 eth0)

踩坑总结

现象原因
nslookup 超时resolv.conf 未走 stub,MagicDNS 规则不生效
resolved 日志 TCP/UDP 反复切换上游 DNS 被 Tailscale iptables 拦截不可达
ping 100.96.0.2 路由正确但丢包ts-input 链 DROP 了整个 100.64.0.0/10 段
nftables 持久化报错iptables-nft 管理的表不能直接用 nft 保存
规则重启丢失ts-input 链由 Tailscale 动态创建,需 systemd drop-in 补救

参考信息

  1. 在 VPS 上部署 OpenClaw:Docker Compose + Tailscale 远程访问
  2. PVE安装Tailscale的一些问题
  3. 阿里云服务器安装 Tailscale 后 DNS 故障排查与解决
  4. Tailscale 与阿里云八字不合的解决方法(上):治标
  5. Tailscale 与阿里云八字不合的解决方法(下):寻根
  6. 解决 CentOS中因 Tailscale 引起的 DNS 解析问题
  7. < OS 有关 > 阿里云:轻量应用服务器 的使用 安装 Tailscale 后DNS 出错, 修复并替换 apt 数据源

发表评论

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理