路由表显示一条经 ZeroTier 接口的默认路由,网络报告在线,浏览器却仍从本地 ISP 地址出去。这种组合很常见,也不是客户端的缺陷。默认路由只说明数据包该往哪里走;另一端必须有东西把它们转发并转换出去。出口节点要工作,三个独立部分必须同时成立。

路由存在,但没有任何流量出去

先检查客户端的路由表。像 default via 10.147.20.5 dev zt0 这样的行只能证明路由已安装,不能证明目标会接受流量。下一跳必须是愿意并且能够转发它的成员。

如果同一请求仍从物理接口出去,说明客户端没有安装该路由,或安装后其度量值输给了本地默认路由。如果安装路由后请求消失,说明出口成员收到了数据包,却无法转发或转换它们。保留物理默认路由的客户端根本不会向出口发送任何数据包。

这一区别决定了该在哪里动手。在改动前后比较公网地址,可以把从未使用过的路由与用过又被丢弃的路由区分开,而且只需一条命令,不必通读整个配置。请在改动其他任何东西之前先做比较,让两次结果出自同一初始状态。

三个必须同时成立的部分

出口是一条链,最弱的一环决定症状。下表按常见失效顺序列出各环节。

PartWhere it livesWhat a failure looks like
Forwarding and NATExit node kernel and firewallTraffic arrives, no reply
Managed default routeZeroTier network controllerNo default via the tunnel on the member
Client acceptanceMember's per-network settingRoute offered but not installed
DNS behaviorClient resolver configurationPages fail by name, IP works

第一行正是选项名称所掩盖的部分。只有当成员的内核在 ZeroTier 接口与面向互联网的接口之间转发数据包,并把回程路径转换回隧道时,它才是出口。没有这种转发,成员只是对等节点,不是网关。

控制器的这一行属于授权,而不是配置。通过成员宣告 0.0.0.0/0 只是告诉每个客户端出口在哪里,并不会让该成员有能力承载流量,也不验证成员到互联网是否有可用路径。ZeroTier 的出口节点文档同样区分节点、路由和客户端三件事。

配置出口节点进行转发和转换

持久启用 IPv4 转发,然后为离开 WAN 接口的流量添加源地址 NAT。过滤规则必须双向允许被转发的流,因为转发和转换与许可本身是两回事:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i zt0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o zt0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

把 zt0 和 eth0 换成主机上真实的接口名;为示例接口保存的规则不会跟着真实接口上的数据包走。要通过拥有这些规则的防火墙管理器让改动持久化,因为交互式 shell 里的命令会在下次重启时消失。

如果主机运行 UFW 或 firewalld 之类的防火墙管理器,应通过该管理器添加规则,而不是在它旁边再堆一层 iptables 行。两个所有者编辑同一批链,会得到依赖启动顺序的策略。管理器自行生成链时顺序很重要。要在重新加载管理器之后从客户端测试,而不是之前。

宣告路由并在客户端上接受它

在网络控制器上为 0.0.0.0/0 添加一条受管路由,其下一跳是出口成员的 ZeroTier 地址。然后在应当使用它的成员上,允许该网络的覆盖设置。这项许可是本地的:它不会重新配置其他成员,也不会改变控制器。

zerotier-cli listnetworks
zerotier-cli set <network-id> allowDefault=1
ip route get 1.1.1.1

最后一条命令应报告 ZeroTier 接口和出口成员的地址。如果它仍报告物理接口,说明路由缺失,或存在度量值更优的竞争默认路由。

把设置限制在真正需要它的网络上。全局启用默认路由接受,或在只应提供私有子网的网络上启用,会让流量走一个从未按此规模设计的出口。

验证出口并检查其他地址族

向能报告来源的服务请求公网地址,并与出口节点的 WAN 地址比较。然后按名称加载一个站点,确认 DNS 仍能解析,并测试一个真正重要的应用,而不只是浏览器。

双栈客户端在 IPv4 经 ZeroTier 出去的同时,仍可继续使用原生 IPv6 路径。如果目标是隐藏或控制全部流量,就需要单独的 ::/0 路由以及出口上的 IPv6 转发,而 IPv4 测试对此毫无说明。

Linux 的反向路径过滤也可能在客户端上丢弃有效的出口流量。ZeroTier 文档提到参与成员需要考虑 rp_filter;请有意地修改该设置,并且只在确认路由和 NAT 之后再改,不要把它当作第一个试验。

如果需求只是访问一台 NAS 或一个办公子网,为那个前缀添加受管路由,比做完整出口更小也更安全。把全部浏览都经另一台设备送出,与访问一个私有资源是两回事,值得单独评审。

相关文章