Saturday, February 17, 2007

Auto WOL on DD-WRT on Linksys WRT54GL

I am running a webserver on my desktop, to host a website from home. One of the problems I faced, is that I have to now leave my desktop "on" all the time. Between the higher electricity bill and depreciation on the desktop, I wondered if I was saving much hosting from home.

So when I bought the Linksys WRT54GL and installed DD-WRT on it recently, I thought I would try to set it up to wake up the computer on a Port 80 (http) access if it was in "sleep" mode.

For DD-WRT and Linksys routers, see http://www.dd-wrt.com/

DD-WRT allows you to write shell scripts on the router and I thought I would use this facility and use the builtin commands. Ideally I would want a trigger on a port 80 access on the router, but this might be a little inefficient since it would happen on every port 80 access and I could not find a way to trigger a script in DD-WRT.

So I thought instead that I would parse the syslog to detect port 80 activity. I could then control things like how often I check for activity etc. Here is the script I came up with

#!/bin/sh

INTERVAL=5
NUMP=3
OLD=""
WOL=/usr/sbin/wol
TARGET=192.168.1.100
MAC=00:00:00:00:00:00
logfile="/tmp/www/wol.log"

while sleep $INTERVAL
do
NEW=`cat /var/log/messages | grep ACCEPT | grep "DST=$TARGET" | grep "DPT=80" | tail -1 | awk '{print $3}'`
SRC=`cat /var/log/messages | grep ACCEPT | grep "DST=$TARGET" | grep "DPT=80" | tail -1 | awk '{print $10}' | sed -e "s/SRC=//g"`
LINE=`cat /var/log/messages | grep ACCEPT | grep "DST=$TARGET" | grep "DPT=80" | tail -1 `
if [ "$NEW" != "" -a "$NEW" != "$OLD" ]; then
echo "$SRC $LINE" >> $logfile
RET=`ping -c $NUMP $TARGET 2> /dev/null | awk '/packets received/ {print $4}'`
if [ "$RET" -ne "$NUMP" ]; then
echo "$SRC causes WOL at" `date` >> $logfile
$WOL -i 192.168.1.255 -p 7 $MAC >> $logfile
sleep 5
fi
OLD=$NEW
fi
done


TARGET is the LAN IP of your webserving machine, and MAC is its MAC Address. INTERVAL is how often you want to check for a transaction. To get the syslog in /var/log/messages, enable syslogd in DD-WRT with an empty field for IP address. I also had to set the log level to High and at least log all ACCEPT s in the log settings.

I create a logfile in /tmp/www to debug the script, the logfile references can be deleted if you want to make the script smaller to fit in nvram. The script does not send a WOL if the webserving machine is not in "sleep" mode. I use the built in WOL command on DD-WRT.

For more on DD-WRT scripts check http://www.dd-wrt.com/wiki/index.php/Index:Scripting

There is a lag now, when the computer is asleep to access a page on the computer. However I find that in most cases, the browser timeout is long enough to wake the computer up and deliver the webpage.

Comments and improvement suggestions are welcome.

23 comments:

Dan said...

How do I enable logsysd?
I'm trying your script with my Media Center PC, so that when I turn my Media Center Extender on, it will wake up the PC...

CB said...

To enable syslogd on the dd-wrt, go to Administration->Service, enable syslogd on that page and leave the "remote server" field empty.
Also in Administration-> Log enable the log with Log Level = "High" and in the Options, turn "Accepted" = "On".

Hope this helps,
-cb

stew said...

I tried your script: it doesn't work (for me).
I'm running a March 2007 beta of v24 6107M.
Wonder if something changed?
I put your script at http://www.dd-wrt.com/wiki/index.php/Useful_Scripts#Web_Server_Wake-Up

stew said...

linked to the wiki page

CB said...

s2s2 ...

Do you see the accepted messages in /var/log/messages ?

How about the scripts output in /tmp/www/wol.log . Do you see the script trying to wake the machine up?

-cb

stew said...

I'll check.

stew said...

Ah, okay. I am using HTTPS !
Since the web traffic is encrypted, does the script need to be modified to look for different connection activity in the log?

I -can- get the desktop webserver to wake up, using the GUI Web interface of DD-WRT, WOL is not a problem.

stew said...

okay, scratch that.

I see the log file just logs basic TCPIP connectivity, nothing higher level. IP from, to, port, etc.

Though, doing as you've said, and having a friend connect from outside the subnet, nothing ends up in the log. When I use the Web GUI, nothing ends up in the Incoming Log. The Outgoing Log is full of activity, though.

I have log level set high, Accept Enabled, and syslogd enabled.

Weird.

stew said...

Got it. I think.

V24RC4, the current version at writing, is also on my router. The logging function is really broken, which is the reason why nothing incoming is going into the Incoming section on the GUI, or /tmp/var/log in the command line.

Other people are having problems with logging. Bugtracker: http://www.dd-wrt.com/dd-wrtv2/bugtracker/view.php?id=2567

What revision of the router firmware are you using?

CB said...

I am using v23sp2.

Dr. Ongo said...

Yuk, never use cat and grep together, it is pointless. See streamlined script here: DD-WRT Wiki. This uses two instead of up to seven(!) processes per line.

Unknown said...

Where did you place the script?

PasKa said...

I've enabled syslog from Services->Service. I save settings and go to Administration and there is no tab "Log". Why could that be?

CB said...

@DrOngo

Thanks for the improvements.

@Anders

The script is in the DDWRT useful scripts section currently at
http://www.dd-wrt.com/wiki/index.php/Useful_Scripts#Web_Server_Wake-up

@PasKa

On v24-sp2 I see it on the Security Page, Firewall Tab, Log management. Enable log, and a few more options show up.

-cb

Unknown said...

Thanks for this info - could be really useful for me. I'm trying to figure out if I can serve a simple web page on my router which I can give to my users for my server so they can go to this web page as a 'portal' for the server. This web page will consist of a button of link which they click which will run the WOL command, then wait a few seconds, then redirect them to the server log in page.

I'm pretty sure all of this is possible with DD-WRT and the work you have done here.

Unknown said...

Any ideas for how can do this please do email me: sam.manley@gmail.com

Unknown said...

Just to say I have started a thread over at DD WRT trying to achieve my aim: http://www.dd-wrt.com/phpBB2/viewtopic.php?p=558964&sid=778fd813f177a22099ea1812371611a2#558964

CB said...

@PhotoCider

It might be difficult to install a webserver on the router, and maybe insecure too.

It might be easier to host that startup page elsewhere on one of the free hosting sites, and have the startmyserver button/link access a url, say /startserver. With some javascript you can probably wait and redirect the page.

Then modify the script on the router to check for that url in the log and do a wol only if it sees a "startserver" url.

Unknown said...

Pretty good post. I just stumbled upon your blog and wanted to say that I have really enjoyed reading your blog post.


linksys

inf3rno said...

Is it possible to validate the request somehow, so bots won't be able to wake up the server? I'd like to share my local network via VPN when I am not home for days maybe weeks.

How do you send the server to sleep? Do you write your applications to expose their busy/idle state somehow?

cb said...

@inf3rno

Oh boy ! It has been years since I wrote this. My Mac Mini home server does not work anymore :)

Instead of validating the request it might be easier to use a "secret" port to wake your server up. Say port 8087. Then you could access port 8087 remotely and the script would look for port 8087 in the log instead of port 80 to wake the server up. This would only let you wake the server up (and maybe some portscanners) You could even have prevent that by using two ports in some sequence.

If you want to put more intelligence into the parsing it might be better to use a simple computer like a raspberry pi running all the time (its only 3W) as a gateway to your network and using that to inspect the payload and decide if it is a bot (awstats figures out bots from apache logs)

In my case I just let the server idle into sleep once I woke it up. There was no "sleep on lan" command.

inf3rno said...

Meanwhile I thought of that too. I mean buying a small SBC to wake up the server, store the drive encryption keys in memory, be a TCP-UDP proxy, defer the packets until the server wakes up and do the VPN server stuff. All of that sounds fun, but I think it would be a lot of extra work for too little gain. At least in my case.

I built my microserver in August, so when I posted my previous comment I had no clue how much power it will consume. I decided to buy a relative recent CPU (Xeon e3-1230v5 s1151). It is strong enough, but it consumes less power than the cheap old technology (s1150 or s1366 Xeons), so I did not have to buy an SBC to sleep proxy it. The machine consumes 32W idle, and I could take it down maybe to 20W by underclocking it and setting up the fan curves properly, but I am satisfied with it in its current form. I calculated that I would win at most 50$ annual with a sleep proxy, which is not much and I am working on other hobby projects right now. :-)

Unknown said...

I created a similar solution, but using the NFQUEUE target instead of the LOG target. If of interest, you can have a look here:

https://github.com/mister-benjamin/etherwake-nfqueue