The 2 AM Problem: Your Server Is Off and You’re Not There
It happened on a Tuesday. A power blip at the office tripped the UPS, and when power came back, one of the bare-metal servers didn’t come back with it. The machine had auto-shutdown enabled but no auto-power-on. It was 2:47 AM, I was 40 kilometers away, and someone needed a database restore by 6 AM.
That night I drove in. The next morning, I set up Wake-on-LAN on every physical machine I managed. I’ve since used it across several production environments — waking machines over NAT from a mobile phone on the other side of the city, without a single failure once the setup was solid.
If you run Linux servers or a home lab, remote WoL is the kind of 20-minute setup that earns its keep the first time power goes sideways at 3 AM.
What Wake-on-LAN Actually Does
Wake-on-LAN sends a specially crafted UDP broadcast packet — called a Magic Packet — to a machine’s network card. The NIC stays powered in a low-power state even when the machine is off (as long as it’s plugged in), listening for that packet. When it arrives, the NIC signals the motherboard to power on.
The Magic Packet structure is dead simple: 6 bytes of 0xFF, followed by the target MAC address repeated 16 times — 102 bytes total. No IP header awareness. No TCP handshake. Just raw UDP on port 9 or 7.
The catch: broadcast packets don’t cross routers by default. Getting a WoL packet from the internet to a machine behind NAT requires either a relay or a directed broadcast. That’s where router config comes in.
Prerequisites
- A Linux machine with a NIC that supports WoL (most do, but BIOS must have it enabled)
- The machine connected via Ethernet — WoL does not work over Wi-Fi in most cases
- Router access for port forwarding and optionally subnet-directed broadcast
- Something to send the Magic Packet from remotely: another server, a VPS, or a mobile app
Step 1: Enable WoL in BIOS/UEFI
Before touching the OS, reboot into BIOS and look for settings labeled:
- Wake on LAN
- Power On By PCI-E / PCI
- Resume By LAN
Enable it. Save and exit. Skip this step and you’ll spend an hour staring at ethtool output wondering why nothing works.
Step 2: Configure WoL on Linux
Check whether your NIC supports Wake-on-LAN:
sudo ethtool eth0 | grep -i wake
You’re looking for output like this:
Supports Wake-on: pumbg
Wake-on: d
The letter g in Supports Wake-on confirms Magic Packet support. The d in Wake-on means it’s currently disabled. Enable it:
sudo ethtool -s eth0 wol g
Verify:
sudo ethtool eth0 | grep 'Wake-on'
Expected output:
Wake-on: g
One problem: this resets on every reboot. Persist it.
Persist WoL With systemd (Modern Systems)
Create a oneshot service that runs ethtool on boot:
sudo nano /etc/systemd/system/wol.service
[Unit]
Description=Enable Wake-on-LAN on eth0
After=network.target
[Service]
Type=oneshot
ExecStart=/sbin/ethtool -s eth0 wol g
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable wol.service
sudo systemctl start wol.service
Replace eth0 with your actual interface name. Run ip link if you’re not sure what it is.
Alternative: NetworkManager (Ubuntu/Fedora Desktops)
If the machine runs NetworkManager, set WoL per-connection instead:
nmcli connection modify "Wired connection 1" 802-3-ethernet.wake-on-lan magic
Step 3: Note the MAC Address
Grab the MAC address now — you’ll need it to build the Magic Packet later:
ip link show eth0 | grep ether
Example output:
link/ether b8:27:eb:a1:2c:44 brd ff:ff:ff:ff:ff:ff
Write it down somewhere you’ll find it at 2 AM.
Step 4: Router Configuration for Remote Wake
Here’s what most tutorials skip. Waking a machine over the internet gives you two paths:
Option A: Port Forward UDP to the Broadcast Address
On most consumer routers (OpenWrt, pfSense, ASUS, TP-Link):
- Open Port Forwarding or Virtual Server settings
- Create a rule: external UDP port 9 → internal IP
192.168.1.255(subnet broadcast), port 9 - If your router blocks forwarding to broadcast addresses, forward directly to the machine’s static IP instead
Give the target machine a static IP or a DHCP reservation by MAC address. A machine that changes IP on reboot will be unreachable when you need it most.
Option B: Use a VPS or Relay Server
Router won’t forward to a broadcast address? Use a relay. A cheap $5/month VPS works, and so does a Raspberry Pi sitting on the LAN. SSH into the relay, then send the packet from inside the network.
Install wakeonlan on the relay:
# Debian/Ubuntu
sudo apt install wakeonlan
# RHEL/Fedora
sudo dnf install wol
Send the packet from the relay:
wakeonlan b8:27:eb:a1:2c:44
Or specify broadcast and port explicitly:
wakeonlan -i 192.168.1.255 -p 9 b8:27:eb:a1:2c:44
Step 5: Testing the Wake Sequence
Power off the target machine. From another machine on the same LAN, send the packet:
wakeonlan b8:27:eb:a1:2c:44
Wait 15–30 seconds, then ping or SSH in. If it wakes, LAN-side WoL is confirmed working.
Now test from outside. Use a VPS or switch your phone to LTE — anything definitively off your local network. Send the packet to your router’s public IP:
wakeonlan -i YOUR.PUBLIC.IP -p 9 b8:27:eb:a1:2c:44
Prefer scripting it? Here’s a Python version that constructs the packet directly:
import socket
def send_magic_packet(mac: str, broadcast_ip: str = '255.255.255.255', port: int = 9):
mac_clean = mac.replace(':', '').replace('-', '')
if len(mac_clean) != 12:
raise ValueError(f"Invalid MAC address: {mac}")
payload = bytes.fromhex('FF' * 6 + mac_clean * 16)
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(payload, (broadcast_ip, port))
print(f"Magic packet sent to {mac} via {broadcast_ip}:{port}")
send_magic_packet('b8:27:eb:a1:2c:44', broadcast_ip='YOUR.PUBLIC.IP')
Troubleshooting Common Issues
- Packet arrives but machine doesn’t wake: Start with BIOS. Then check
ethtool eth0 | grep 'Wake-on'— the setting may have reset todafter a reboot. - Works on LAN, fails from the internet: Your router is probably dropping the UDP packet. Try port 7 as an alternative. Some ISPs also block UDP on non-standard ports.
- ARP cache issue: After the machine has been off long enough, the router drops its ARP entry and won’t forward packets to that IP. Targeting the broadcast address (
192.168.1.255) bypasses this completely — no ARP lookup required. - Machine wakes then immediately shuts off: This is a BIOS power state issue. Look for a setting around S4/S5 power states in the power management section and adjust accordingly.
Security Considerations
Exposing UDP for WoL is low-risk by itself — the worst outcome is an attacker turning your machine on. But an powered-on machine is an attack surface, so a few basic precautions are worth it:
- Use a non-standard external port (e.g., forward 19872/UDP externally → 9/UDP internally)
- Lock the forwarding rule to a specific source IP if your WAN address is static
- Make sure SSH on the target uses key-based auth — no password logins
One More Trick: Scripting the Full Wake+Wait+SSH Flow
Once WoL is stable, glue the whole sequence together into one script:
#!/bin/bash
MAC="b8:27:eb:a1:2c:44"
HOST="192.168.1.50"
USER="admin"
echo "Sending magic packet..."
wakeonlan $MAC
echo "Waiting for machine to come online..."
for i in $(seq 1 12); do
sleep 5
if ping -c1 -W1 $HOST &>/dev/null; then
echo "Machine is up. Connecting..."
ssh ${USER}@${HOST}
exit 0
fi
echo "Still waiting... (${i}/12)"
done
echo "Machine did not respond after 60 seconds."
exit 1
That’s the Setup
WoL is a background tool — invisible until the moment a machine goes dark at the worst possible time. The setup is about 20 minutes: ethtool config, a systemd service, and one port forwarding rule. After that, you can reach any physical machine you manage from anywhere, any hour.
The 40-kilometer drive at 3 AM was the last one I made for a power issue. That’s a good outcome.

