quinta-feira, 29 de abril de 2010

Wake on Lan em Python

Como alguns amigos meus sabem, eu tenho a pretensão de montar um sistema semi-inteligente na minha casa. Leitor biométrico na porta, algumas câmeras móveis, acesso remoto, centro de mídia, entre outras coisas. Para isso, eu pensei em uma estrutura de algumas máquinas. Uma máquina de baixo consumo de energia (provavelmente uma Via Pico-ITX) pra ficar ligada direta baixando arquivos, controlar as câmeras e a biometria, ligar as outras máquinas e... ligar as outras máquinas?

Foi exatamente essa pergunta que um amigo meu me fez, ao interromper minha descrição animada da minha futura "Casa Inteligente". Ele me perguntou como eu faria pra ligar a máquina para poder acessar remotamente. Eu falei que usaria um recurso chamado "Wake on Lan", que inicia a máquina sem precisar de nenhum outro mecanismo que não seja a rede. Na realidade, ele não conhecia o conceito (apesar de ser técnico de manutenção de longa data) e achava que eu usaria algum tipo de switch ou interruptor pra ligar a máquina.

Bem, o conceito não é novo. Desde o surgimento das especificação ATX de placas mãe, o suporte a múltiplos estados de energização proporcionou a criação do recurso de poder ligar a máquina a partir de algum sinal de entrada. Muitos já usam algo do tipo, como o Wake on Keyboard, onde você aperta o Power do teclado e o PC liga. O conceito é parecido.




Wake on Lan

Se a sua placa-mãe suportar, o seu computador poderá ser ligado ao receber um pacote especial (chamado de Magic Packet). O pacote deve conter uma sequência de bits predefinida seguida do endereço MAC da sua placa de rede repetida três vezes. Ao reconhecer um pacote com esse formato chegando, a placa de rede acionará um dispositivo da sua placa-mãe e inicializará o computador. Cabe lembrar que a placa de rede não fica efetivamente ligada. Ela simplesmente espera por um pacote padronizado, sem ativar os outros circuitos dela mesma enquanto o computador está desligado, e só responde a esse magic packet.

O processo funciona assim:

Quando o PC é desligado, a placa de rede continua energizada e se mantêm escutando a rede pelo Magic Packet. Este pacote pode estar dentro de qualquer outro tipo de pacote (IPX, UDP, IP, whatever, por isso o nome de Magic Packet).

Um exemplo de como seria um pacote UDP com a sequência seria o seguinte:

[Cabeçalho Ethernet][Cabaçalho IP][Cabeçalho UDP][Sequência Mágica][CRC]

Claro que a placa de rede só interpretará a Sequência determinada, mas é necessário usar alguma forma de transmissão para que a sequência trafegue na rede. Por isso o pacote que está sendo usado é irrelevante.

Sequência de "Wake up"

Para evitar que outros pacotes que estejam trafegando na rede possam ligar indevidamente a máquina, a sequência segue um padrão. Primeiramente, a sequência começa com um preâmbulo de sincronização de 6 bytes, com o valor hexa FFh. Em seguida, o endereço MAC da placa de rede é repetido 16 vezes. Se nossa placa de rede tiver, por exemplo, o MAC 12:34:56:78:9A:BC, a placa de rede estará esperando o seguinte pacote:

FFFFFFFFFFFF123456789ABC123456789ABC123456789ABC123456789ABC
123456789ABC123456789ABC123456789ABC123456789ABC123456789ABC
123456789ABC123456789ABC123456789ABC123456789ABC123456789ABC
123456789ABC123456789ABC


Como disse anteriormente, não importa qual o empacotamento que esteja sendo utilizado, desde que a sequência possa caber inteira em um único datagrama. Caso estejamos no mesmo subdomínio, você poderia enviar simplesmente um pacote ARP com a sequência. No entanto, para aproveitar melhor as características das redes atuais, o mais interessante é usar um pacote UDP para enviar a sequência, já que o mesmo pode ser enviado de outra máquina de fora da rede, desde que o roteador esteja devidamente configurado para reenviar o pacote para dentro da rede. Como falei pro meu amigo, simplificar as coisas é essencial!

Implementando um cliente Wake on Lan em Python

Como dito antes, é necessário colocar uma sequẽncia específica dentro de um pacote e enviá-lo para a máquina para ligá-la, certo? E como criar esse pacote, você (e meu amigo) perguntaram? Bom, existem na internet dezenas de soluções diferentes para dar conta da tarefa de gerar o pacote nos mais diversos formatos e enviá-lo para a máquina alvo.

Esse não é meu objetivo. Como sou programador, eu mesmo pensei em implementar minha própria solução, que você pode encontrar no link abaixo:

Código: Wol em Python

O código é simples e auto-explicativo. Espero que gostem.

Flws povo, até a próxima semana!

Fontes:

Wake on Lan
Wikipédia
Ferramentas para Wake on Lan
Wake on Lan com Python