Wake-On-WAN, The Long Road Of The Magic Packet

How to setup wake-on-WAN, using a machine on the LAN to broadcast the magic packet.

Introduction

Maybe you already heard about Wake-on-LAN (or wol), which is the ability to wake-up a computer on the LAN (Local Area Network) by sending it a "magic" network message. Wake-on-WAN (or wow) is roughly the same thing, except that you don't send the message from inside the LAN, but from the outside world: the WAN (Wide Area Network).

It sounds easy at first, a simple NAT rule should do, right? Actually, it's much more complicated, due to the fact that we need to broadcast the wake-up message on the LAN.

If your router allows that, you just need to configure it, and you're done. But if it doesn't, it becomes a complicated story, that I'm gonna relate in this post.

My personal use-case

Just to provide some background: I have a QNAP NAS that I use mainly to backup stuff. This NAS is at the other end of the world. I don't want to have it powered on all the time, because it costs electricity. And I don't want to have my backup online all the time, it's an useless risk.

Fortunately, the NAS comes with the wake-on-LAN feature, and I make a good use of it.

So my NAS is turned off 99% of the time. When I need it, I wake it up by sending it the "magic packet". And I can do that from whatever place of the world I am, which is great. Then, I do my stuff, and send the NAS back to sleep.

It sound very simple, but is quite a pain in the ass to achieve...

Enabling wake-on-LAN on your device

You need a device that supports the wake-on-LAN standard, and you need to be sure that the feature is enabled. The procedure depends on your device, of course. So here I'll just describe the steps involved for my use-case. My NAS is a QNAP NAS TS-219P II, and it runs Debian.

To enable the wake-on-LAN feature, just a few commands:

ethtool -s eth0 wol g
qcontrol wol on

If you want to keep it enabled, you should run this commands at each startup. A good place to put that is in the /etc/network/interfaces file, in the post-up rules. It looks like that on my config:

allow-hotplug eth0
face eth0 inet dhcp
   post-up /sbin/ethtool -s $IFACE wol g
   post-up /usr/sbin/qcontrol wol on

If you want to read more, this is the definitive piece of information about Debian on QNAP devices:
http://www.cyrius.com/debian/kirkwood/qnap/ts-119/

And more specifically, stuff about wake-on-LAN with Debian on QNAP device:
http://michael.stapelberg.de/Artikel/qnap_ts119_wol/

Testing wake-on-LAN

On your workstation, you must install wakeonlan.

apt-get install wakeonlan

To wake-up your device, just issue this simple command:

wakeonlan de:ad:be:ef:ca:fe

We assume that:

wakeonlan is a simple command that sends the "magic packet" as defined by the standard. You can also tell it on which address you want to send the packet, for example, assuming your sub-network is 192.168.1.0:

wakeonlan -i 192.168.1.255 de:ad:be:ef:ca:fe

Now, let me warn you about one thing. You MUST use a broadcast address. You may think that you can use the IP address of the device (assuming it's a static address). And indeed, if you just powered off your device and try to wake it up using its IP address, it may work. But this is only due to some cache effects, probably in the ARP cache somewhere but I'm not so sure so I won't tell. If you wait more time after your device is powered off, you will see that using the IP address of the device doesn't work at all. So just broadcast.

The power failure issue

One of the first thing to understand is that the wake-on-LAN feature works only if the device has been shut down properly.

Actually, what happens when you shutdown your device (and assuming you enabled the wake-on-LAN feature) is that the Ethernet card will just go into a shallow sleep. It's not completely dead, it's still powered on, and it still receives packet. And when the "magic packet" arrives, the Ethernet card will turn on the whole device. The device in itself was not sleeping, it was really off. Only the Ethernet card was sleeping.

Now, what happens if you disconnect the power plug of your device while it's in this state? Well, the Ethernet card is powered off for real this time, not sleeping anymore. And now, if you connect the power plug again, what happens? Nothing. The whole device is plugged to AC, but it's completely off, including the Ethernet card. You can send the "magic packet" now, it's useless, the Ethernet card is off.

So what does that mean? It means that if there's a power cut, you're screwed. If someone unplug the power cable, you're screwed. It means that your device, when powered off in this "wake-on-LAN fashion", is in a weak position, and you won't be able to wake it up 100% of the time. Except if you take great care that it's never powered off.

The easier solution for that: you can plug your device to an UPS.

Second solution, your device may have an automatic power on feature. It means that, if there's a power cut, the device turns on itself after power recovery. My NAS has this feature, and that's what I use. It works great, but it involves more configuration on your device...

Wake-on-WAN, can your router do that?

OK, now let's start the interesting part of this post. Waking a device from the WAN.

At first, you must know the public IP address of your router, the one that allows your NAS to be online. If it's a static IP address, just write it down and you're OK. If it's dynamic, you will have to setup a dynamic DNS account and enable that on your router. Then you will use the dynamic DNS to reach your router.

With the wakeonlan command, you can send the magic packet out on the WAN, this is not an issue. The issue lies on the receiving side. How to handle the incoming packet, and how to broadcast it on the LAN?

Your router may have this feature built-in, and in this case it's easy, you can stop reading :). However, my router has no such thing, so I had to keep on digging...

The first idea I had was simply to add a NAT rule to my router, that handles the incoming packet and broadcasts it on the LAN. Easy, right? If you're used to network configuration, you already had the same idea. Well, try it, why not? If it works, congratulations, you're done!

Unfortunately for me, my router doesn't allow that, for security reason they say, but most likely because they didn't bother implementing it. And I don't have root access on the router, so I'm a little bit stuck here.

However, I have a Raspberry Pi 2 (RPi2) on the LAN, running Debian. This little RPi2 is supposed to be alive all the time, so I thought I could use it as a middleman to broadcast the "magic packet".

Wake-on-WAN using a middleman to broadcast the packet

OK, so the first thing to do is to add a NAT rule to the router, to redirect the incoming packet to the RPi2.

Then, I thought I was done. I thought I just had to setup a NAT rule with iptables on my RPi2, to broadcast the magic packet. Easy... Alas! I was terribly wrong!

It turns out that broadcasting a packet with iptables is not possible. If you don't believe me, just try it and tell me if you succeed. I'm not an expert here, so I may be wrong. But I tried hard, and stumbled on this StackExchange post, which is worth reading:
http://unix.stackexchange.com/q/77874/105794

One of the guys answering there gives a pretty good explanation, and concludes that "Broadcast packets are not routed/forwarded by design".

Thinking of it, I believe that's why most routers don't allow to broadcast an incoming packet using NAT rules. Under the hood, most routers run Linux, and install NAT rules with iptables. That's as simple as that.

Anyway! The same post provides also the solution, using the socat command. It's a little bit cryptic at first sight, but if you spend a little bit of time reading the manual it becomes clearer.

My socat command looks like that:

socat -u -T1 UDP-LISTEN:9,fork UDP-DATAGRAM:192.168.1.255:9,broadcast

I run that on my RPi2 and it works! At last!!

Of course, such command must be running all the time, so I just add it to my /etc/rc.local file.

The final picture

Here is a summary of what happens when I wake up the NAS:

In the end, you can see that it was not straight-forward at all...

Furthermore, to handle the power cut problem described above, I had to enable the autopoweron feature of the NAS, then write an autopoweroff script, and run it in the background. The autopoweroff script turns off the NAS when there's nothing happening. It's not so complicated to write, but it takes a little bit of care and time.

But this is a must-have, if you're in the same situation as me, you have to go through that. Autopoweron without autopoweroff makes no sense.

More readings