ZeroTier 连到 LAN:该用 UFW 路由规则,而不是开放端口
在网关上放行一个端口,并不等于转发到它后面的主机。要设置托管路由、开启转发,并选定回程路径。
通过 ZeroTier 成员访问办公室 LAN 里的打印机,听起来只是一条规则,实际上是三个不同位置上的三个决定。叠加网络必须知道 LAN 在哪里,Linux 主机必须愿意转发数据包,而 LAN 必须知道如何把回包送回去。在网关上开一个端口的入站规则,这三件事一件都没碰到。这是把错误的工具用在了正确的主机上。
三件事,三个归属
托管路由属于 ZeroTier 的网络配置。它告诉成员:某个前缀可以通过某个特定的成员地址到达。
转发属于 Linux 内核,也属于掌握其防火墙策略的一方。它决定从叠加网络进来的数据包是否会再次从物理网卡出去。不转发的主机在接收之后会静默丢弃。发送方只看到超时,服务日志里什么也没有。
回程路径属于 LAN。它的主机和路由器必须知道叠加网络的前缀要经由你网关的 LAN 地址才能到达,否则就得有东西做地址转换,让这个问题根本不出现。
这三者可以各自正确,而另外两者失败;因此只 ping 网关的测试,不能证明它后面的服务是否可用。
把托管路由指向成员
为目标 LAN 前缀添加路由时,下一跳要用网关的叠加网络地址,而不是它的 LAN 地址。叠加网络地址是其他成员能到达的那个;LAN 地址只在线上有意义。
设计要生效,成员必须接受托管路由,而且它们各自的本地网络不能已经在用你通告的前缀。家里处在 192.168.60.0/24 的远程笔记本,也不能再把 192.168.60.0/24 经叠加网络路由出去。
通告的前缀要尽量窄,只覆盖任务需要。通告更大的聚合段来影响选路偏好,也可能顺带主张了不属于你的地址空间,由此产生的冲突会出现在同时连两个网络的设备上。它还可能让成员偏好一条走不通的路径。让路由保持诚实,剩下的交给策略。
把前缀和成员地址,与防火墙规则写在同一份记录里,因为最常见的故障就是路由指向了错误的成员。
在内核里开启转发
改动之前先读当前生效的转发值,然后用系统本来就在用的机制把设置持久化,而不是用一条重启后就消失的一次性命令。
如果策略由 UFW 掌管,它的路由规则表达的是一组源、目的和网卡的转发关系。它们和那些在网关本机开放服务的入站规则是两回事:
sysctl net.ipv4.ip_forward
sudo ufw route allow in on zt3f2a1c9d out on eth0 proto tcp to 192.168.60.20 port 443
sudo ufw status verbose
网卡名是那台主机上真实的叠加网络设备,可以从 ip link 读出来;它在不同安装里并不是固定字符串。如果主机默认就转发,而 UFW 又不在路径上,那么路由规则会被忽略,起作用的是内核参数。
选择回包怎么回来
保留源地址时,LAN 上的服务看到的是真实的叠加网络地址,并往那里回包。这要求 LAN 主机或它的路由器上有一条把前缀指向你网关的路由,而这是 Linux 机器之外的改动。
加不了那条路由时,限定范围的源地址转换会让请求看起来来自 LAN 上的网关。于是回包在本地就能返回,不需要改 LAN 的路由,代价是服务日志里丢掉了原始来源。
转换要限定在叠加网络的源和特定的 LAN 目的上。把从 LAN 网卡出去的一切都转换,是范围过大的做法,日后读规则的人会被它惊到,而且它还会把本该被挡掉的流量藏起来。
两个选择都不会让 LAN 反向获得访问任意叠加网络成员的、未经请求的权限。真需要的话,那是另一条规则,要单独评审。
从真实成员上测试
从另一个成员连接,而不是从网关,请求一个允许的服务。然后试一个应当保持关闭的服务,并在重连之后、网关重启之后把两个测试都重做一遍。
报告 ONLINE 的成员,或者能 ping 通网关叠加网络地址,都不能验证路由、转发规则或回程路径:
zerotier-cli listnetworks
ip -4 route get 192.168.60.20
sudo ufw status numbered
第二条命令看的是数据包去 LAN 主机会走哪张网卡,第三条看的是路由规则是否以你想要的形式存在。两条都看着对、服务却仍然超时,那么剩下的可疑对象就是回程路径。