你让办公室的机器进入睡眠,从家里拨上 VPN,它却仍然关机。隧道是通的,文件共享有响应,路由器的 wake-on-LAN 页面也报告已发出请求。所有可见信号都说网络正常,而这正是这件事令人困惑的原因:本该唤醒机器的帧,从来没有到达它所在的网段。

症状指向网段,而不是隧道

ping 睡眠中的主机失败,这一部分是正常现象。待机中的机器没有运行的 IP 协议栈,因此无法应答 ARP 或 ICMP,再怎么调整隧道配置也改变不了。有用的测试是同一 LAN 上的第二台机器能否被唤醒,以及路由器自己的唤醒页面对接在其上的主机是否有效。

一旦同网段的测试通过,问题就在作用域上。你使用的发送端位于 VPN 接口上,它构造的包是面向本地链路的广播,所以要么从错误的接口出去,要么根本没有出去。隧道没有坏,它承载的是错误类型的流量。在改动任何一个路由器设置之前,先弄清发送端选择的是哪个接口。

magic packet 是一个帧,不是一种服务

载荷以 六字节的固定头 0xFF 开头,随后是目标网卡的硬件地址重复十六次,最后是可选的四字节 SecureOn 口令。发送端通常把它封进 UDP 发往端口 7 或端口 9,但端口号只是发送端与网卡之间的约定,并不是可以连接的监听服务。没有东西在监听,也没有东西会回应。

唤醒机器的是网络接口,它在系统其余部分断电时,仍由待机供电轨维持一小部分电路。所以这个设置必须同时经得起完全断电和睡眠:关机时切断待机供电的主板,已经没有网卡可以接收任何东西了。

为什么路由式隧道送不过去

路由式 VPN 接口是两条隧道地址之间的点对点 IP 链路。它为承载发往对端的包而存在,所以 ping、SSH 和文件共享在其上表现正常。广播帧并不是发给那个对端的,而受限广播地址路由器通常不会转发。

转发指向子网的广播是路由器的刻意功能,多数默认配置把它关掉了,而且即便打开,它也只是送到那个子网,而不是送到某一张正在睡眠的网卡。睡眠中的主机同样无法应答 ARP,因此试图在转发前解析目标地址的路由器,会在等待一个永远不会来的应答时丢掉这个帧。静态绑定条目修好了这一部分,而广播作用域的问题依旧存在。于是这是两个彼此独立的限制,解决一个对另一个毫无帮助。

真正能到达网卡的三种放置方式

每种可行的安排都把帧放到目标所在的网段,区别在于对网络的干扰有多大:

  1. 在目标网段放一台常开设备。一台不断电的路由器、NAS 或小型 Linux 盒子,只要你能通过隧道连上它,就能在本地发出这个帧,而 VPN 那边什么都不用改。
  2. 让路由器自己发帧。许多固件提供从 LAN 网桥发送的唤醒页面,只要目标就在那个网桥上、而不是在第二台路由器后面,就有效。
  3. 当广播确实必须跨越时,用 TAP 式隧道把两个站点桥接起来。这会把两个广播域合并,随之而来的是广播风暴、单一地址规划和每个发现协议同时看到两个站点。

对单台机器来说,第一种才是应该优先选的。第三种是带持续成本的网络设计决定,应当按这个分量对待,而不是当成某台台式机的应急修补。

记下是哪个助手发出这个帧、它位于哪个网桥或 VLAN 上。从错误接口发出的助手会给出完美的抓包,以及一台永远醒不来的机器,而这一组合会白白耗掉一个下午。

在责怪客户端之前先验证发送

先检查目标网卡,因为没有任何发送端能唤醒一张没准备好的网卡。下面的命令会读取支持的与当前的唤醒模式,当前值为 g 表示 magic packet 已启用:

ethtool enp3s0 | grep -A1 'Wake-on'
ip neigh show 192.168.1.50
tcpdump -ni br0 -e 'ether broadcast and udp dst port 9'
etherwake -i br0 3c:7c:3f:00:11:22

在发送发生时于助手上抓包,并且去读它,而不是假定成功。只有带着广播目的 MAC 从正确网桥离开的帧,才是发送成功的证据;如果抓包为空,就是发送端选了另一个接口,后面的测试也就没有意义。构造裸帧而不是 UDP 数据报的发送端不会命中这个过滤器,所以在断定什么都没发出之前,先确认你的工具用的是哪种形式。

在 Windows 上等效的网卡检查是 powercfg /devicequery wake_armed,它列出被允许唤醒系统的设备。不在该列表中的网络适配器会忽略发给它的每一个包,无论帧在线路上看起来多么正确。

然后确认唤醒本身以及后续。能开机但按名字仍然不可达的机器需要静态地址和 DNS 记录,因为靠广播的名字解析仍然过不了隧道。无线唤醒是一项独立且远不如有线可靠的能力,所以在把 VPN 牵扯进来之前,先在同一个网段里测试它。把接口名和助手主机写进工单,因为下一次故障通常还是这两件事。

相关文章