Wake on Lan

Wake on Lan - theory

Wake-on-LAN (WoL) is a networking standard that allows a computer to be powered on remotely by sending a special network packet called a Magic Packet. This (usually) UDP packet contains the MAC address of the target device and is broadcast over the local network.

For WoL to work:

  1. The computer must have WoL enabled in its BIOS/UEFI and network adapter settings.
  2. The network card must remain partially powered to listen for the Magic Packet even when the computer is off.
  3. The Magic Packet is typically sent using tools like ether-wake or wol from another device on the same local network or via a VPN for remote access.

The Magic Packet - theory

The Magic Packet used for Wake-on-LAN (WoL) is not strictly tied to a specific protocol like TCP or UDP. While it is commonly sent over UDP, especially to port 7 (Echo) or 9 (Discard), it can also be transmitted using other methods:

  1. UDP: This is the most typical method, as UDP packets are easy to broadcast to the local network.
  2. Ethernet (Layer 2): Magic Packets can also be sent directly over Ethernet without encapsulating them in a UDP or IP packet. These are true broadcast frames, intended for local networks.
  3. TCP: In some setups, especially with routers or managed environments, Magic Packets can be sent via TCP.
  4. HTTP/HTTPS: Some modern devices and network management tools encapsulate WoL functionality into web-based APIs.

The key is that the Magic Packet contains the target device’s MAC address repeated 16 times in a specific format and must reach the network adapter of the target system. The choice of protocol depends on the network configuration and tools in use.

Wake on Lan in practice - hardware setup

First of all the question is - does your hardware support it? In my case I was lucky - HP-T620 and HP-T630 terminals do support WOL (an easy BIOS setup) as well as the NIC adapter, which is integrated into the motherboard.

Wake on Lan in practice - software setup

When WOL is enabled on the hardware side of things, we need to make sure that it is also enabled on the Linux side of things. Assuming, that your network interface is named enp1s0, just run: ethtool enp1s0 | grep 'Wake-on:'.

You may get:

Supports Wake-on: pumbg
Wake-on: d

Flags meaning:

  • p: Magic Packet
  • u: Unicast Packet
  • m: Multicast Packet
  • b: Broadcast Packet
  • g: Magic Packet over SecureOn

So the above "d" means, that WOL is disabled on the NIC. Let's enable it:

ethtool -s enp1s0 wol g

And remember about the persistence of this after the reboot. I use a simple systemd service for this, which I deploy with Ansible. Here're tasks:

  - name: Enable WOL on enp1s0
    copy:
      dest: /etc/systemd/system/wol.service
      content: |
        [Unit]
        Description=Enable Wake-on-LAN on enp1s0
        After=network.target network-online.target
        Wants=network-online.target

        [Service]
        Type=oneshot
        ExecStart=/usr/sbin/ethtool -s enp1s0 wol g
        RemainAfterExit=yes
        Restart=on-failure
        RestartSec=15s
        StartLimitInterval=0
        Retries=5
        TimeoutStartSec=0

        [Install]
        WantedBy=multi-user.target
      owner: root
      group: root
      mode: '0644'
  - name: Enable and start the Wake-on-LAN systemd service
    ansible.builtin.systemd:
      name: wol.service
      enabled: yes
      state: started
      daemon_reload: yes

Now just reboot the machine, run again ethtool enp1s0 | grep 'Wake-on:' and see, if the output is correct.

Wake on Lan in practice - script

Let's run a simple test. We will try to send this Magic Packet to our server.

Since, this is a scratch-building series, we won't use any ether-wake or wol binaries, just prepare our own. I have created a simple go binary for that - you make fetch it here: https://github.com/docent-net/utilities/tree/main/wol

Having the binary built (go build -o wol main.go), we may test it. Log into the target server (it may be actually turned on) and catch and display all UDP packets sent to it on 9/UDP port:

$ tcpdump -i enp1s0 udp port 9 -X

And from another machine in the same network, run the binary (just adjust the MAC and broadcast addr):

$ ./wol 00:8c:fa:d1:28:5e 10.20.33.255
Magic packet sent successfully.

Shortly afterwards, you should see this packet arriving on the tcpdump output. If not -> you will need to debug. Make sure, that the broadcast address is correct, and that the MAC address is reachable in this very network.

Wake on lan in practice - debugging issues

If you cannot receive Magic Packet on the tcpdump side of things, there may be various reasons behind that.

One of most common ones is that the target device is in another network. Crossing network boundaries with a broadcast packet is tricky.

Most routers drop broadcast packets by default. To enable WoL across networks, the router must support and allow directed broadcasts. A directed broadcast is sent to a specific subnet's broadcast address (e.g., 10.20.33.255 for the 10.20.33.0/24 subnet).

You may need to enable a feature called Enable Directed Broadcast or Allow Broadcast Forwarding (names vary by router model).

Also, to wake up a device from a different network, you need to forward UDP packets to the broadcast address of the target subnet. This usually takes two steps on router:

  1. Add a Port Forwarding Rule - forward UDP traffic on a specific port (commonly 9 or 7) to the broadcast address of the target subnet (e.g., 192.168.1.255).
  2. Set the Forwarding to Use Broadcast - some routers allow forwarding directly to a broadcast address; others might require manual configuration.

Comments