Wake-on-LAN (WOL) es un estándar pensado para encender remotamente un ordenador por medio de un mensaje de red. Básicamente consiste en enviar a toda la red local un paquete de datos (conocido como "Magic Packet") que contiene la MAC del equipo que queremos encender. Cuando la tarjeta de red detecta un paquete con su MAC da la orden de encendido del resto del equipo.
Hasta aquí todo es muy sencillo, este paquete lo podemos enviar por UDP a la dirección 255.255.255.255 de tal manera que llegue a toda nuestra red local, o a una dirección del tipo 192.168.1.255 si queremos afinar un poco más. El problema surge cuando queremos enviar este paquete desde internet, desde un móvil por ejemplo, para encender un equipo de nuestra casa. La mayoría de los router caseros no permiten hacer redirecciones de este tipo, es decir recibir un paquete UDP por un puerto y redirigirlo a una dirección del tipo 192.168.1.255, y dirigirlo a la ip del equipo tampoco tiene sentido porque recordemos que el equipo esta apagado, por lo que no esta haciendo uso de ninguna ip en ese momento.
La solución que se me ocurrió en mi caso fue utilizar una placa Raspberry Pi, un minúsculo ordenador que funciona con linux, como repetidor del "Magic Packet", de tal manera que cuando le llega el mensaje de arranque a un puerto UDP determinado el lo reenvía a toda la red local, encendiendo de este modo el equipo que corresponda. Os preguntareis que ganamos con esto, ya que seguimos teniendo que tener un ordenador, en este caso el Raspberry, continuamente encendido, la respuesta es que este pequeñisimo ordenador consume muy poco, menos de 5W frente a los mas de 200w que puede consumir un ordenador normal en reposo, ademas de no tener ningún molesto ventilador girando constantemente. Por otro lado podemos utilizar el Raspberry para un montón de aplicación más, por lo que no solo lo tendríamos encendido por este motivo.
Para montar el repetidor primero tenemos que instalar xinetd, que es el que se va a encargar de "escuchar" por el puerto UDP y va a ejecutar nuestro programa cuando reciba un paquete.
sudo apt-get install xinetd
Ahora creamos en el directorio /etc/xinetd.d un fichero llamado wolrelay con lo siguiente:
service wolrelay { log_type = FILE /var/log/wolrelay log_on_success = HOST PID EXIT disable = no port = 1999 socket_type = dgram protocol = udp wait = yes user = pi nice = 10 type = UNLISTED server = /usr/bin/wolrelay server_args = 192.168.1.255 9 }
La ruta del ejecutable y la IP pueden variar dependiendo de donde guardes el ejecutable una vez compilado, y del rango de tu red.
El siguiente paso es crear el ejecutable, el código es el siguiente:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/select.h> int main(int argc, char *argv[]) { int i, sock; struct { char header[6]; char mac[16][6]; } packet; struct sockaddr_in address; // Comprobamos los parametros if (argc != 3) return 1; // Leemos el paquete, y comprobamos su tamaño if (fread(&packet, 1, sizeof(packet), stdin)==sizeof(packet)) { // Comprobamos la cabecera del paquete if (strncmp(packet.header,"\xFF\xFF\xFF\xFF\xFF\xFF",6)!=0) return 3; // Comprobamos que las 16 repetciones de la MAC son iguales for (i=1;i<16;i++) { if (strncmp(packet.mac[0],packet.mac[i],6)!=0) return 4; } // Creamos un socket para reenviar el paquete sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) return 5; i=1; // Configuramos el socket para que pueda hacer broadcast if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (void *) &i, sizeof(i)) != 0) { // Si no podemos configurar el socket lo cerramos y salimos close(sock); return 6; } // Configuramos la direccion y puerto de envio address.sin_family = AF_INET; address.sin_port = htons(atoi(argv[2])); if (inet_aton(argv[1], &address.sin_addr) == 0) { // Si la direccion no es correcta, cerramos el socket y salimos close(sock); return 7; } // Reenviamos el paquete recibido a la direccion de envio if (sendto(sock, &packet, sizeof(packet), 0, (struct sockaddr *) &address, sizeof(address)) < 0) { // Si el envio no es correcto, cerramos el socket y salimos close(sock); return 8; } // Cerramos el socket y salimos sin errores close(sock); return 0; } else return 2; }
Ahora solo hay que copiar el nuevo ejecutable a su nueva ubicación y reiniciar xinetd
sudo cp wolrelay /usr/bin sudo /etc/init.d/xinetd restart
Hay que recordar también abrir un puerto UDP en el router y dirigirlo hacia el Rasberry.
Enlaces de interes:
http://es.wikipedia.org/wiki/Raspberry_Pi
http://www.linuxfocus.org/English/November2000/article175.shtml
Comentarios
Interesante, gracias por la
Interesante.
Gracias por la información.
hola
hola
mi pregunta es donde o con que programa creas el ejecutable?
saludos!
Pues con el gcc:
Pues con el gcc: