To enable wake-on-LAN over the Internet, the open hardware platform Arduino is used.
Not all routers support wake-on-LAN from the Internet to LAN. This depends on whether you can configure the ARP cache and send or forward a WOL broadcast package.
To support WOL, in this case on an Apple TimeCapsule, an Arduino Ethernet Pro board is used. Thus having a low-power device (Arduino) listening for WOL.
Both the Arduino board and machine to wake-up are connected via Ethernet to the TimeCapsule. The Arduino is powered using the TimeCapsule USB port.
The Arduino is programmed to listen for wake-up packets and, if any received, send a broadcast wake-up packet.
Here a Perl CGI script is used to first send a WOL packet to the Arduino and then redirect to the domain of the server just woken up. Of course, this assumes the script to be on an other, on-line, server. For other applications, e.g. remote desktop, you can just send the WOL packet from a terminal session.
The following code is run on the Arduino:
/*
* WakeUpCube
*
* 2011-07-28 JvO, New sketch
*
* Reference links:
* http://arduino.cc/en/Reference/ServerConstructor
* http://arduino.cc/forum/index.php?topic=62185.0
*
* Derived from Arduino WakeMyPc
* Ricardo Dias
* http://ricardo-dias.com/
*
* This sketch sends the "magic packet" to wake up
* a PC on Local Area Network [when a push-button
* is pressed.]
*/
#include <SPI.h> // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <Udp.h> // UDP library from: bjoern@cs.stanford.edu 12/30/2008
// Arduino configuration
byte arduinoMAC[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Ethernet shield MAC address
byte arduinoIP[] = { 10, 0, 1, 203 };
byte gatewayIP[] = { 10, 0, 1, 1 };
byte subnetMask[] = { 255, 255, 255, 0 };
unsigned int localPort = 9; // local port to listen on
// the IP broadcast and wake-up target MAC address
byte targetIp[] = { 10, 0, 1, 255 }; // LAN broadcast address 10.0.1.255
int targetPort = 9;
byte targetMAC[] = { 0x00,0x12,0x34,0x56,0x78,0x90 }; // MAC address of the machine to wake-up
// these two variables are set when a packet is received
byte remoteIp[4]; // holds received packet's originating IP
unsigned int remotePort; // holds received packet's originating port
// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet,
char replyBuffer[] = "acknowledged"; // a string to send back
// serial connection speed
const int serialBaudRate = 9600;
// Initialisation
void setup() {
// initialize the ethernet device
Ethernet.begin( arduinoMAC, arduinoIP, gatewayIP, subnetMask );
// initialize server
Udp.begin( localPort );
}
// Main LOOP
void loop() {
delay(1000);
// if there's data available, read a packet
int packetSize = Udp.available(); // note that this includes the UDP header
if(packetSize) {
packetSize = packetSize - 8; // subtract the 8 byte header
// read the packet into packetBufffer and get the senders IP address and Port number
Udp.readPacket( packetBuffer, UDP_TX_PACKET_MAX_SIZE, remoteIp, remotePort );
// send the wake-up packet
sendPkt();
}
}
// Send the wake-up on LAN message (aka magic packet)
void sendPkt() {
byte all[102];
int i, c1, j=0;
// the 'magic packet' consists of 6 times 0xFF followed
// by 16 times the hardware address (MAC)
for( i = 0; i < 6; i++, j++ ) {
all[j] = 0xFF;
}
for( i = 0; i < 16; i++ ) {
for( c1 = 0; c1 < 6; c1++, j++ ) {
all[j] = targetMAC[c1];
}
}
Udp.sendPacket( all, 102, targetIp, targetPort );
} |
The Perl CGI script to send the WOL package and redirect to the server:
#!/usr/bin/perl ################################################### # Send Wakeup On LAN broadcast message and redirect # # usage: http://yourURL/cgi/wakeup.cgi # test: http://yourURL/cgi/wakeup.cgi?test=1 # # 25 july 2011, JvO, New script version 0.1 ################################################### use CGI; use CGI::Carp qw( fatalsToBrowser ); # pass errors to the browser use Socket; use POSIX; $query = CGI::new(); &getParms; # Get parameters &sendWOL; # Send Wakeup on LAN &returnHtml; # Return result page # # Set params # sub getParms { $destAddr = "192.168.10.20"; # Destination IP Adres $destMAC = "de:ad:be:ef:fe:ed"; # Ethernet Pro MAC address $hostURL = "http://your.url.here"; # the URL to redirect to $port = 9; # Remove colons $destMAC =~ tr/://d; $test = $query->param("test"); } # # Return HTML page # sub returnHtml { # redirect to the Cube print "Content-type: text/htmlnn"; if ($test) { print "<html><head><title>Wake on LAN</title></head>n"; print "<body bgcolor="#CCCCCC">n"; print "<hr size=5 width=75%><p>n"; print "<center><h1>Server at IP adres "$destAddr" has been sent a wakeup msg</h1></center>n"; print "<hr size=5 width=75%>n"; print "</body></html>n"; } else { print "<meta HTTP-EQUIV="REFRESH" content="2; url=$hostURL/gallery3">n"; print "<html><body>You are being redirected to $hostURL...</body></html>n"; } } sub sendWOL { # Magic packet is 6 bytes of FF followed by the MAC address 16 times my $magic = ("xff" x 6) . (pack('H12', $destMAC) x 16); # create socket handle and connect socket($sh, PF_INET, SOCK_DGRAM, getprotobyname('udp')) or die "Socket could not be created. Reason: $!n"; connect($sh, sockaddr_in($port, inet_aton($destAddr))) or die print $runlog "Socket connect failed: $! host: $destAddr port: $portn"; # send the wakeup packet print $sh $magic; close($sh); } |
The TimeCapsule is set to forward WOL packages, using the Airport configuration program “Advanced” option (sorry for the screenprint being in Dutch):

