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:

  1. ether-wake, installed as part of ethttols 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.
  2. 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 and password 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 and password 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 address 255.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.