一个卫星节点只要与主路由广播同一个 Wi-Fi 名称,就几乎说明不了它下面客户端的流量走向。在没有证据之前,它只是一台无线电加一座网桥。真正决定出口的是每个客户端拿到的默认网关,以及它前方节点的转发模式。按下面五项从客户端向外检查一遍,你会得到一个经得起推敲的结论,而不是测速软件留下的印象。

先看客户端实际拿到的网关

在客户端上打印路由表和邻居表。默认路由指出负责转发的地址,邻居表项指出该地址对应的 MAC。要用客户端查,而不是看路由器的设备列表,因为 设备列表只显示关联关系,不显示实际路径。

ip route show default
ip -6 route show default
ip neigh show

Windows 用另一种写法给出同样的事实:ipconfig /all 给出默认网关,arp -a 给出 MAC。在 macOS 上,route -n get default 与 arp -an 覆盖同样的内容。

把这个网关和你已经知道的两个地址对照:主路由的 LAN 地址,以及卫星节点的管理地址。如果网关是路由器的 LAN 地址,客户端就是桥接到路由器,路由器针对该网段的策略原样生效。如果网关是卫星节点自己的地址,说明节点在做路由,路由器根本看不到客户端的原始数据包,策略必须在节点上落实,否则就等于没做。

确认节点实际处在哪种模式

Mesh 产品常把三个词混着用,含义却各不相同,所以比起 App 里的标签,更该相信数据包的实际路径。桥接或接入点模式只转发帧。路由模式会终结一个子网并运行 DHCP。访客模式通常把客户端放进独立 VLAN,另有一套规则。路由器模式下的节点如果又接在另一台路由器后面,就形成双重 NAT,它的客户端到达 VPN 路由器时源地址已被改写,基于源地址的策略随之失效。

What you seeWhat it meansNext check
Gateway is the router's LAN address, one MAC for every nodeThe node bridges; the router owns the policyRouter policy for that LAN and VLAN
Gateway is the node's address and DHCP comes from the nodeThe node routes; double NATNode's own VPN client, or a static route plus policy on the router
Gateway is a different subnet on a guest SSIDGuest VLAN, often client-isolatedWhether that VLAN is inside the tunnel policy
Gateway changes when you walk into another roomRoaming across segmentsRepeat the check per node

要确认 MAC,请读节点上的标签,并与 ip neigh 的结果对照。厂商通常只印基础 MAC,各频段的 MAC 由递增一个字节得到,所以最后一位十六进制数会不同;比较前缀即可,不必比整个地址。如果网关的 MAC 属于路由器的 LAN 接口,节点就没有为这台客户端做路由。

在路由器上取证,而不是靠测速

只有路由器侧的状态才能显示地址改写。在 OpenWrt 上列出策略规则和路由表,再确认隧道的握手是新的:

ip rule show
ip route show table all | grep default
wg show

在 pfSense 或 OPNsense 上,同样的证据分别在 pfctl -sr 看规则、pfctl -ss 看活动状态,以及 WireGuard 状态页看对端计数,依据是 WireGuard 客户端文档。用客户端地址过滤状态表。如果状态显示客户端被改写成隧道地址,流量就在隧道里;如果显示的是 WAN 地址,那就不在,面板上亮什么灯都不算数。

从客户端做一次 traceroute,能补上状态表给不出的一项事实:第一跳。第一跳是路由器的 LAN 地址,说明客户端直接到达了路由器。第一跳是节点地址、后面还跟着另一个私有跳,说明你处在被路由的网段上,那第二跳才是必须承载策略的设备。

看看节点除了地址还发什么

DHCP 选项和租约一起下发,所以自带 DHCP 的节点也会一并下发自己的 DNS 和自己的 IPv6 路由通告。于是客户端可能一边走隧道,一边把查询发给节点上的解析器,或者拿到一个隧道策略从未覆盖的公网 IPv6 地址。在客户端上把两者都打印出来:

cat /etc/resolv.conf
ip -6 addr show scope global

如果解析器就是节点,而节点又把查询转给路由器,DNS 就跟着隧道走。如果节点本地解析,或指向运营商的解析器,那么即使 HTTP 走了隧道,查询也会漏在外面。IPv6 也值得同样检查:一个公网地址加上一条绕开隧道的默认路由就是泄漏,而 Mesh 固件往往让 IPv6 保持开启,VPN 策略却只覆盖 IPv4。

故意断开隧道,然后把结果记下来

把隧道放下,观察连接在该节点上的客户端,而不是坐在路由器旁边的客户端。ping 和一个 curl 配短超时就够了;要问的是流量会停下,还是回落到 WAN。用路由器自带的服务命令停隧道,例如 wg-quick down wg0 或停掉 OpenVPN 服务,并让测试保持简短。

如果客户端照常工作,说明节点或路由器在这个网段上是失败即放行,Mesh 已经悄悄废掉了终止开关。把隧道恢复,确认握手计数有变化,再重复第三步的状态表检查。

给每个节点记一行:标签、SSID、网关地址、MAC 前缀、出口是否确认、IPv6 是否覆盖,以及隧道断开时的表现。漫游才是答案会变的地方,所以要测你真正会走动的房间。当某一行和其余各行对不上时,要查的就是那个节点,修也该修在那台拥有该行网关的设备上。

相关文章