I have noticed that even though I've optimized my server to the point where its pulling around 60w it is still wasting energy by running all the damn time when its not being used. I estimate that there is only about 5 hours of actual usage a day on it, that means I'm losing big when it comes to my energy bill. The problem with that 5 hours of usage is that it comes at random times when either someone else or I decides to access one of the many services that it serves up. I could be watching a TV show i recorded from my couch or my roommate could be streaming an episode to their phone on the other side of the country. So how do I manage to get the server to stay asleep and wake up at a moments notice based on a request that could come from 1 room away or across the country?
WOL of course! It might not be used how it was intended but it works like a charm. Here is what you need:
Alright with that out of the way here is how to go about doing this.
Follow this guide to move the server to its own dedicated VLAN: Located here.
Add the iptables rules to allow for communication between the VLANs by adding it to the firewall commands on the DD-WRT web GUI under Administration > Commands > Save Firewall. Of course i would advise trying these commands out by hand before committing them.
iptables -I FORWARD -i vlan+ -o vlan2 -j ACCEPT
Now that you have a working network connection for the server again you can proceed on to the WOL feature. Modify these iptables commands to your liking and add them to the Save Firewall noted above to set up log rules so that when the router sees and incoming valid request it gets logged so the WOL script can act on it.
iptables -I FORWARD -o vlan3 -p tcp --syn --dport 22 -m limit --limit 1/min -j LOG --log-level 7 --log-prefix 'local ' iptables -I FORWARD -o vlan3 -p tcp --syn --dport 443 -m limit --limit 1/min -j LOG --log-level 7 --log-prefix 'local ' iptables -I FORWARD -o vlan3 -p tcp --syn --dport 139 -m limit --limit 1/min -j LOG --log-level 7 --log-prefix 'local ' iptables -I FORWARD -o vlan3 -p tcp --syn --dport 548 -m limit --limit 1/min -j LOG --log-level 7 --log-prefix 'local ' iptables -I FORWARD -o vlan3 -p tcp --syn --dport 3240 -m limit --limit 1/min -j LOG --log-level 7 --log-prefix 'local ' iptables -I FORWARD -o vlan3 -p tcp --syn --dport 45631 -m limit --limit 1/min -j LOG --log-level 7 --log-prefix 'local '
Let me break down these commands.
After running these commands /var/log/messages now has entries like these when you make a connection with the server from inside the local network or outside.
local IN=br0 OUT=vlan3 SRC=10.0.1.34 DST=10.0.10.145 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=27548 DF PROTO=TCP SPT=54171 DPT=443 WINDOW=65535 RES=0x00 SYN URGP=0
For me /var/log/messages also had a butt load of other iptables log messages that i didn't need and subsequently caused issues with the WOL script. There are two solutions to this. Either append the commands above to log the requests into a different log file or disable all the existing extra logging. I choose the second route because I didn't want to handle setting up a new log file that rotates so my flash dive doesn't get filled up.
Now for me after these two steps the log was clean enough to use for the script. I put the script under /opt/etc/wol but it really doesn't matter where it goes as long as its executable. Just plop this script somewhere and have it start automatically when the router boots. I've seen people have issues with the startup commands not running under Administration > Commands . So its possible to use their solution ( Forum link here ) or just create a service to start it.
#!/bin/sh #Enable JFFS2 and place script in /jffs/ then run on startup in web interface. #You can check the log from http://192.168.1.1/user/wol.html INTERVAL=5 NUMP=2 OLD="" WOLPORT=9 TARGET=10.0.10.145 BROADCAST=10.0.10.255 MAC=6C:F0:49:02:0B:7D WOL=/usr/sbin/wol LOGFILE="/tmp/www/wol.html" echo "<meta http-equiv=\"refresh\" content=\"10\">" > $LOGFILE echo "["`date`"] AUTO WOL Script started. <br>" >> $LOGFILE while sleep $INTERVAL;do NEW=`dmesg | awk -F'[=| ]' '/local/ {print $19}' | tail -1` SRC=`dmesg | awk -F'[=| ]' '/local/ {print $7}' | tail -1` if [ "$NEW" != "" -a "$NEW" != "$OLD" ]; then if ping -qc $NUMP $TARGET >/dev/null; then echo "["`date`"] NOWAKE $TARGET was accessed by $SRC and is already alive. <br>">> $LOGFILE else echo "["`date`"] WAKE $SRC causes wake on lan. <br>">> $LOGFILE `$WOL -i $BROADCAST -p $WOLPORT $MAC >> $LOGFILE` echo "<br>" >> $LOGFILE sleep 5 fi OLD=$NEW fi done
This is a modification of the webserver wakeup script from the dd-wrt wiki and it is pretty much the same that they have there. I just changed the commands around for better logging and stripped out any extra code. It basically checks the dmesg log to see if a new entry has come in and if there has and the server is not pingable then it sends the WOL command. I have it checking the log every 5 seconds because most of the services I use have a long timeout period but it can be adjusted to happen more often. I also had a problem with pinging my server and it turned out to be a UFW rule that is enabled by default, here is how to allow ICMP pings.
That's it, the router will now be sending WOL magic packets when ever a valid service tries to contact the server. I haven't gotten to the point where the server puts itself to sleep so I can't really describe that in detail just yet. My next step is to move the services that require the server to be constantly running over to the router and to use a pound to proxy the HTTP services so that only authenticated requests cause the server to wake up and start slinging content.