Setting up and using Wake-on-LAN on Linux (2020 edition)
Contents
Introduction to Wake-on-LAN
This week I decided to see if I could get Wake-on-LAN (WoL) working. I’ve tried a couple of times in the past with no success.
Wake-on-LAN is a protocol for turning on a computer that is (mostly) powered off by sending a “magic packet” over the local area network. Refer to the Wikipedia article for a full description.
The computer’s on-board network interface and BIOS have to support it. The WoL
Magic Packet technique, where the computer wakes up when the network interface
sees FFFF FFFF FFFF
followed by 16 repetitions of its MAC address, was defined
twenty years ago, so even most older computers support it.
But you can’t simply set the BIOS to start the computer on WoL and expect it to work. The WoL feature has to be enabled in the network interface every time the system is restarted. If that’s not done there’s a good chance the card’s firmware will turn off the interface altogether when the system is shut down, so it can’t listen for the magic packet. That’s why my earlier attempts to use Wake-on-LAN failed.
Getting Linux to set the Wake-on-Lan feature on system restart has been the
topic of many blog posts over the years. However, systems descended from Red
Hat, including Fedora and CentOS, changed how they configure the network
interface starting with Red Hat Enterprise Linux version 6. Prior to that the
best practice was to add a line to /etc/sysconfig/network-scripts/ifcfg-ethX
.
That can still be done, but it also requires having to configure a startup
feature that was deprecated by systemd.
So now the hest practice for setting the network interface to watch for the WoL magic packet is to use a tecnhique that Debian and Ubuntu systems have been using for a while: set up a little systemd target to do the work.
Getting Linux to set the network interface for WoL at startup
First determine which network interfaces you have in the system and determine their names and MAC addresses.
[user@host ~]$ ip addr | egrep '^ *([0-9]:|link/ether|inet )' 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 inet 127.0.0.1/8 scope host lo 2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:19:21:4c:51:f1 brd ff:ff:ff:ff:ff:ff inet 192.168.1.238/24 brd 192.168.1.255 scope global noprefixroute dynamic enp3s0 3: wlp4s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 00:26:82:31:68:54 brd ff:ff:ff:ff:ff:ff inet 192.168.1.229/24 brd 192.168.1.255 scope global noprefixroute dynamic wlp4s0
In the example above, the primary interface is enp3s0
. (wlp4s0
is a wireless card.)
Next use ethtool
to determine if the interface supports Wake-on-LAN. In my
limited experience ethtool
is installed by default on systems descended from
Red Hat but not on Debian or Ubuntu. (In that case, run sudo ap-get install -y
ethtool
to set it up.)
[user@host ~]$ sudo ethtool enp3s0 Settings for enp3s0: Supported ports: [ TP ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Half 1000baseT/Full Supported pause frame use: No Supports auto-negotiation: Yes Supported FEC modes: Not reported Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Half 1000baseT/Full Advertised pause frame use: No Advertised auto-negotiation: No Advertised FEC modes: Not reported Speed: 10Mb/s Duplex: Half Port: Twisted Pair PHYAD: 0 Transceiver: internal Auto-negotiation: on MDI-X: Unknown Supports Wake-on: pg Wake-on: g Current message level: 0x000000ff (255) drv probe link timer ifdown ifup rx_err tx_err Link detected: yes
The critical line in the above text is Supports Wake-on:
with a g
(magic packet)
parameter.
Next use ethtool
to set the card to watch for the magic packet:
[user@host]$ sudo ethtool -s enp3s0 wol g
Now you need to set up the systemd service
file. In the line below, replace
EDIT
with the name of your preferred text editor (vi, vim, emacs, nano, cat, ed,
teco, oowriter 😊 …)
[user@host ~]$ sudo EDIT /etc/systemd/system/wol.service
Put the following text into the file. Remember to replace INTERFACE
with
the name of the ethernet device.
[Unit] Description=Configure Wake On LAN [Service] Type=oneshot ExecStart=/sbin/ethtool -s INTERFACE wol g [Install] WantedBy=basic.target
Finally, issue the following three commands to enable the wol
service:
sudo systemctl daemon-reload
sudo systemctl enable wol
sudo systemctl start wol
Waking up systems using Wake-on-LAN
For systems descended from Red Hat, you have two options:
-
ether-wake,
installed as part ofethttols
on Red Hat based systems- Must run as root
- Can wake up only one host at a time
- By default,
ether-wake
sends the magic packet out on all interfaces. If an interface is down the program will issue an error message. You can restrict the program to using only one interface with the-i
option.
-
wol
, available as an installable package- Does not need to be run as root
- Can wake up multiple hosts by specifying their MAC addresses on the command
line. The magic packets are transmitted to the broadcast address
255.255.255.255
and are seen by all hosts on the network - Can also wake up hosts specified in a file containing lines in the following
format (
port
andpassword
are optional):
xx:xx:xx:xx:xx:xx hostname port password
The magic packets are sent directly to the hostname.
For Debian and Ubuntu based systems, the program wakeonlan
is available. It’s
not installed by default, so you’ll need to do that yourself. Of the three
Wake-on-LAN utilities reviewed here, this is the most capable.
- Does not need to be run as root
- Typically sends UDP packets to port 9 on the broadcast address
255.255.255.255
, but that can be overridden on the command line - Can wake up multiple hosts by specifying their MAC addresses on the command
line. If
/etc/ethers
exists, host names can be specified as well, and the program searches it for a MAC address. - Similar to
wol
, can also wake up hosts specified in a file containing lines in the following format (port
andpassword
are optional):
xx:xx:xx:xx:xx:xx port password
ip-address port password
hostname port password
The magic packets are sent to the broadcast address255.255.255.255
Here’s the wakeonlan source code.
The $Id
line says 2005, but it was actually last updated in 2012 to use
/etc/ethers
. This file is identical to the Debian source with the execption
it’s encoded using UTF-8 for the benefit of the blog software instead of
ISO-8859-1.