Generating The Wake On Lan Magic Packet

2006-02-06 SRIV I've always wondered how to utilize the Wake On Lan feature of modern computers, especially since last night when I had to halt a machine 200 miles away and I had no one there to power it back up.

After you enable WOL in your motherboard's BIOS, boot into your OS. I typically use Linux. In order for the halt command to power down the computer you must have the apm module loaded first. Now, issue the halt command, and the computer should turn off, but, the LAN jack indicator LEDs should still be lit.

Run this script, passing the IP Address and MAC address of the computer's NIC on the command line:

  wakeonlan.tcl 192.168.0.55 00:40:63:D5:2A:B9

and you will note that the computer will power on. You'll need to obtain the tcludp extension as well. I packaged a udp.kit for Linux/Windows/OSX here [L1 ]. Download udp.kit somewhere in your path. On Linux and OSX, chmod +x udp.kit to make it executable. On Windows, just copy it to c:\windows .


Tested on Linux, Windows and OSX

  # wakeonlan.tcl -  Steve Redler IV
  #
  # Create and send the magic packet needed to wake a halted
  # computer over the internet via broadcast UDP socket.
  #

  source [auto_execok udp.kit]
  package require udp 1.0.8

  # Select the ipaddress and the port number.
  set ipaddress [lindex $argv 0]
  set port   32767

  # Create a broadcast sending udp socket.
  set s [udp_open $port]
  fconfigure $s -buffering none -blocking 0 -translation binary
  fconfigure $s -broadcast 1 -remote [list $ipaddress $port]


  # Generate and send the magic packet
  set hw_addr [binary format H* [string map {: ""} [lindex $argv 1]]]
  set msg "\xff\xff\xff\xff\xff\xff[string repeat $hw_addr 16]"
  # Lets send it 4 times to be safe
  for {set a 0} {$a < 4} {incr a} {
    puts -nonewline $s $msg
    after 100
  }

  exit

The above requires a close $s if it is to be reused in a program rather than a one time with an exit. Otherwise it will get an error on failing to bind socket to port. This occurred on using this on androwish.


2006-02-08 You'd better send this to the subnet broadcast IP address 192.168.0.255 - JR SRIV Indeed, if you are sending the packet to a machine on your local lan segment, you should send it to the broadcast address. When you are sending it over the internet, then you will send the packet to the remote router/firewall, which needs to forward the packet to the broadcast address on the private network side. I've read that this is tricky when using a iptables based firewall/router. On my Belkin router at home, I was able to forward incoming port 32767 to 192.168.0.255 on the private net side, and all worked well.


2006-02-09 SRIV Searching the net, I found the solution to forwarding the incoming packet to the internal broadcast address using iptables:

  EXT_IF=eth0  the internet
  INT_IF=eth1  the private network
  iptables -A FORWARD -i $EXT_IF -p udp --dport 32767 -j ACCEPT
  iptables -A PREROUTING -t nat -i ! $INT_IF -p udp --dport 32767 -j DNAT --to 192.168.0.254:32767
  ip neigh change 192.168.0.254 lladdr ff:ff:ff:ff:ff:ff nud permanent dev $INT_IF

Basically you forward to an unused private address, in this example 192.168.0.254, then the ip neigh command assigns the broadcast mac a permanent arp table entry.


AMG: Instead of port forwarding, you could run a server that listens for instructions on an Internet-facing TCP (or UDP) port and (perhaps among other things, use your imagination) will, on command, send the WOL packet to your local LAN.