网络唤醒

出自 ArchWiki

网络唤醒 (WoL) 是一项通过网络开启计算机的功能。

硬件设置

网络唤醒只有在您满足以下先决条件时才有效

  1. 目标计算机的主板和网络接口控制器必须支持网络唤醒。
  2. 目标计算机必须物理连接(通过网线)到路由器或源计算机,网络唤醒才能正常工作,除非您的无线网卡支持无线唤醒 (WoWLAN 或 WoW)。

您必须在 BIOS/UEFI 中准备以下内容

  1. 启用网络唤醒功能。不同的主板制造商对此功能使用略有不同的措辞。查找诸如“PCI Power up”、“Allow PCI wake up event”或“Boot from PCI/PCI-E”之类的术语。
  2. (如果在 BIOS/UEFI 中可用)确保 ErP 处于禁用状态,否则您的以太网卡将不会通电,并且无法接收来自其他设备发送的任何唤醒数据包。
注意
  • 某些主板支持从断电状态进行网络唤醒,但有些主板仅支持从睡眠/挂起状态进行网络唤醒。
  • 某些主板受到一个错误的影响,该错误可能在启用 BIOS WoL 功能时导致立即或随机的#关机后唤醒

软件配置

在网络适配器上启用 WoL

根据硬件的不同,网络驱动程序可能默认关闭了 WoL。

要查询此状态或更改设置,请安装 ethtool,确定网络接口的名称,并使用以下命令查询它

# ethtool interface | grep Wake-on
Supports Wake-on: pumbag
Wake-on: d

Wake-on 值定义了什么活动触发唤醒:d(禁用)、p(PHY 活动)、u(单播活动)、m(多播活动)、b(广播活动)、a(ARP 活动)和 g(魔术封包活动)。值 g 是 WoL 工作所必需的,如果不是,则以下命令在驱动程序中启用 WoL 功能

# ethtool -s interface wol g
注意: 除了 g 之外,设置 umb 之一也可能是启用该功能所必需的。

此命令可能无法在下次重启后持续生效,在这种情况下,必须通过某种机制重复执行。以下小节列出了常见的解决方案。

使其持久化

systemd.link

可以通过 systemd.link 文件进行链路层配置。实际设置由 net_setup_link udev 内置程序执行。将 WakeOnLan 选项添加到网络链接文件

/etc/systemd/network/50-wired.link
[Match]
MACAddress=aa:bb:cc:dd:ee:ff

[Link]
NamePolicy=kernel database onboard slot path
MACAddressPolicy=persistent
WakeOnLan=magic

另请参阅 systemd.link(5) 以获取更多信息。

注意
  • 仅应用第一个匹配的文件。默认链接文件 /usr/lib/systemd/network/99-default.link 的内容随 systemd 一起提供,必须包含在内,否则接口可能会配置错误。
  • 要被考虑,文件名应按字母顺序排在默认文件 99-default.link 之前。例如,50-wired.link 可以工作。
  • 此配置仅适用于链路层,并且独立于网络层守护程序,例如 NetworkManagersystemd-networkd
  • Match 部分中,OriginalName= 也可以用于标识接口。

systemd 服务

这与之前的 systemd.link 选项等效,但使用独立的 systemd 服务。

/etc/systemd/system/wol@.service
[Unit]
Description=Wake-on-LAN for %i
Requires=network.target
After=network.target

[Service]
ExecStart=/usr/bin/ethtool -s %i wol g
Type=oneshot

[Install]
WantedBy=multi-user.target

或者,安装 wol-systemdAUR 软件包,然后通过启动 wol@interface.service 来激活此新服务。

udev

udev 能够在设备可见时立即运行任何命令。以下规则将为名称与 en* 匹配的所有网络接口启用 WOL。文件名很重要,并且必须以 81 到 99 之间的数字开头,以便它在 80-net-setup-link.rules 之后运行,后者使用可预测的名称重命名接口。否则,NAME 将未定义,并且该规则将不会运行。

/etc/udev/rules.d/81-wol.rules
ACTION=="add", SUBSYSTEM=="net", NAME=="en*", RUN+="/usr/bin/ethtool -s $name wol g"

$name 占位符将被匹配设备的 NAME 变量的值替换。

cron

可以使用 crontab 中的“@reboot”在每次计算机(重新)启动时运行命令。首先,确保 cron 已启用,然后为 root 用户编辑 crontab,其中包含以下行

@reboot /usr/bin/ethtool -s interface wol g

netctl

如果使用 netctl,则可以通过将以下内容添加到 netctl 配置文件中来使此设置持久化

/etc/netctl/profile
ExecUpPost='/usr/bin/ethtool -s interface wol g'

NetworkManager

NetworkManager 提供 Wake-on-LAN 以太网支持。通过魔术封包启用网络唤醒的一种方法是通过 nmcli

首先,搜索有线连接的名称

# nmcli con show
NAME    UUID                                  TYPE            DEVICE
wired1  612e300a-c047-4adb-91e2-12ea7bfe214e  802-3-ethernet  enp0s25

接下来,可以查看网络唤醒设置的当前状态

# nmcli c show "wired1" | grep 802-3-ethernet.wake-on-lan
802-3-ethernet.wake-on-lan:             default
802-3-ethernet.wake-on-lan-password:    --

在该连接上通过魔术封包启用网络唤醒

# nmcli c modify "wired1" 802-3-ethernet.wake-on-lan magic

然后重启,可能需要重启两次。要禁用网络唤醒,请将 magic 替换为 ignore

也可以使用 GUI 通过 nm-connection-editor 更改网络唤醒设置。

您可以通过添加专用配置文件来永久禁用所有连接的网络唤醒 

/etc/NetworkManager/conf.d/wake-on-lan.conf
[connection]
ethernet.wake-on-lan = ignore
wifi.wake-on-wlan = ignore

在 TLP 中启用 WoL

当使用 TLP 进行挂起/休眠时,应将 /etc/tlp.conf 中的 WOL_DISABLE 设置为 N,以允许使用 WoL 恢复计算机。

触发唤醒

要在目标计算机上触发 WoL,必须知道其 MAC 地址。要获取它,请从计算机执行以下命令

$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp1s0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether 48:05:ca:09:0e:6a brd ff:ff:ff:ff:ff:ff

这里的 MAC 地址是 48:05:ca:09:0e:6a

在其最简单的形式中,网络唤醒将魔术封包作为以太网帧广播,其中包含当前子网内的 MAC 地址,低于 IP 协议层。不需要知道目标计算机的 IP 地址,因为它在第 2 层(数据链路层)上运行。

如果用于在互联网上或在不同的子网中唤醒计算机,它通常依赖路由器来中继数据包并广播它。在这种情况下,必须知道路由器的外部 IP 地址。请记住,大多数路由器默认情况下不会中继子网定向广播,这是一种安全预防措施,需要明确告知路由器这样做。

能够发送网络唤醒魔术封包的应用程序

  • gWakeOnLAN — 用于通过网络唤醒功能唤醒已关闭计算机的 GTK 实用程序。
https://www.muflone.com/gwakeonlan/english/ || gwakeonlan
  • wol — 在小型程序中实现网络唤醒功能。它可以唤醒符合魔术封包标准的硬件。注意:此应用程序需要使用 -p 参数/标志将端口从默认端口 (40000) 更改为 9。
https://sourceforge.net/projects/wake-on-lan/ || wol
  • wol_qt — 具有集成 ARP 扫描功能的 Qt 实用程序,用于查找 MAC 地址和批量发送网络唤醒数据包。
https://github.com/stefmitropoulos/wol_qt || wol_qtAUR

在同一局域网内

如果您通过网线直接连接到另一台计算机,或者局域网内的流量未被防火墙阻止,那么使用网络唤醒应该很简单,因为无需担心端口重定向。

在最简单的情况下,使用默认广播地址 255.255.255.255

$ wol target_MAC_address

要仅向特定子网或主机广播魔术封包,请使用 -i 开关

$ wol -i target_IP target_MAC_address

跨互联网

当源计算机和目标计算机被 NAT 路由器分隔时,可以设想不同的解决方案

  • 如果路由器支持WoL,则可以依靠它将数据包正确广播到本地网络中。

否则,可以通过端口转发来实现网络唤醒。路由器需要使用以下两个选项之一进行配置

  • 将不同的端口转发到每台目标计算机。这要求任何目标计算机在其局域网上具有静态 IP 地址。
  • 将单个端口转发到广播地址。大多数路由器不允许转发到广播地址,但是如果您可以通过 telnet、ssh、串行电缆或其他方式获得路由器的 shell 访问权限,请运行以下命令
    $ ip neighbor add 192.168.1.254 lladdr FF:FF:FF:FF:FF:FF dev net0
    此示例假设网络为 192.168.1.0/24,并使用 net0 作为网络接口。现在,将 UDP 端口 9 转发到 192.168.1.254。此解决方案已在运行 Tomato 的 Linksys WRT54G 和 Verizon FIOS ActionTec 路由器上成功测试。有关如何在安装了 DD-WRT 固件的路由器上执行此操作的说明,请参阅本教程,有关安装了 OpenWrt 固件的路由器的说明,请参阅本教程

在任何情况下,从源计算机运行以下命令以触发唤醒

$ wol -p forwarded_port -i router_IP target_MAC_address

杂项

检查魔术封包的接收

为了确保 WoL 数据包到达目标计算机,可以侦听 UDP 端口(通常为端口 9)以查找魔术封包。预期的魔术封包帧包含 6 个字节的 FF,后跟目标计算机的 MAC 地址(每个 6 个字节)的 16 次重复,总共 102 个字节。

使用 netcat

这可以通过在目标计算机上安装 gnu-netcat 并使用以下命令来执行

# nc --udp --listen --local-port=9 --hexdump

或者,如果您使用的是 openbsd-netcat 变体

# nc -u -l 9 | xxd

然后等待传入的流量出现在 nc 终端中。

注意: 机器本身的防火墙不需要为网络唤醒工作而打开(接口的处理发生在 NIC 中,在防火墙之前)。但是,为了使用 netcat 进行调试,您仍然需要临时打开该端口。

使用 ngrep

在目标计算机上安装 ngrep 并键入以下命令

# ngrep '\xff{6}(.{6})\1{15}' -x port 9

WoL 脚本示例

这是一个脚本,说明了 wol 在不同机器上的使用

#!/bin/bash

# definition of MAC addresses
monster=01:12:46:82:ab:4f
ghost=01:1a:d2:56:6b:e6

echo "Which PC to wake?"
echo "m) monster"
echo "g) ghost"
echo "q) quit"
read input1
case $input1 in
  m)
    /usr/bin/wol $monster
    ;;
  g)
    # uses wol over the internet provided that port 9 is forwarded to ghost on ghost's router
    /usr/bin/wol --port=9 --host=ghost.mydomain.org $ghost
    ;;
  Q|q)
    break
    ;;
esac

故障排除

NetworkManager

关机后网络适配器仍然断电

如果通过 nmcli 配置了 WOL 并且关机后网络适配器仍然断电,则将自动协商设置为 yes 可能会有所帮助。

使用以下命令设置它

# nmcli c modify "wired1" 802-3-ethernet.auto-negotiate yes

关机后唤醒

众所周知,某些主板受到一个错误的影响,该错误可能在关机后,每当启用 BIOS WoL 功能时,导致立即或随机唤醒(例如,在此线程中讨论的那样)。

使用 BIOS 设置修复

BIOS 首选项中的以下操作可以解决某些主板上的此问题

  1. 禁用 USB 设置中对 xHCI 的所有引用(请注意,这也将在启动时禁用 USB 3.0)
  2. 如果 EuP 2013 显式是一个选项,则禁用它
  3. 可选地启用键盘操作唤醒
注意: 对于上面第 3 项的价值,存在不同的看法,并且它可能取决于主板。

通过内核怪癖修复

也可以通过添加以下内核启动参数来解决此问题:xhci_hcd.quirks=270336 这会激活以下怪癖

  • XHCI_SPURIOUS_REBOOT
  • XHCI_SPURIOUS_WAKEUP

电池耗尽问题

部分笔记本电脑在关机后存在电池耗尽问题 [1]。这可能是由启用的 WOL 引起的。要解决此问题,请如上所述使用 ethtool 禁用它。

# ethtool -s net0 wol d

Realtek

r8168

使用 Realtek 8168 8169 8101 8111(C) 系列网卡(独立网卡和板载网卡)的用户可能会注意到一个问题,即网卡在启动时似乎被禁用,并且没有链路指示灯。请参阅 网络配置/以太网#Realtek 无链路 / WOL 问题

如果网络交换机上的链路指示灯在电脑关机时亮起,但网络唤醒仍然无法工作,则至少启动一次使用 r8168AUR 内核模块的系统,然后切换回内核自带的 r8169 内核模块,据报告可以解决此问题。

对于 r8168 模块,您可能需要设置 s5wol=1 内核模块参数 以启用网络唤醒功能。

r8125

使用 Realtek 8125 网卡的用户报告称,无法使用 r8169 内核模块的网络唤醒功能。安装 r8125-dkmsAUR 可以启用此功能。

使用 lspci -k 确保使用了正确的内核驱动程序。如果不是,禁用 r8169 模块。

alx 驱动程序支持

对于某些较新的基于 Atheros 的网卡(例如 Atheros AR8161 和 Killer E2500),由于一个导致意外唤醒的错误,主线 alx 模块中禁用了 WOL 支持(请参阅 此补丁讨论)。可以应用一个补丁(或使用 alx-wol-dkmsAUR 软件包作为 dkms 模块安装),该补丁既恢复了 WOL 支持,又修复了底层错误,如 此线程 中所述。

另请参阅 [2] 中的预先打补丁的源代码。