Remoto, remoto, remoto! Nella gestione del nostro parco macchine ai primissimi posti dei must have troviamo sicuramente la configurazione dell’accesso remoto no?
RDP, SSH, WinRM, insomma opzioni ne abbiamo ma potremmo avere un problemino, che fare se la macchina è spenta?
Puoi scegliere tra chiamare qualcuno in loco per l’accensione, recarti personalmente sul posto, fare tutto in autonomia dalla tua scrivania con WOL.
Cosa scegli?
Direi che WOL vince a mani basse!

Cos’è il Wake-on-LAN (WOL)?

Wake on LAN (WoL) è uno standard appartenente al livello data-link che consente di avviare un computer da una postazione remota, a patto di conoscerne l’indirizzo MAC.
I pacchetti Ethernet che attivano la “sveglia” sono detti Magic Packet (“pacchetti magici”).

Il Magic Packet è in sostanza un frame broadcast, composto da una prima parte di sincronizzazione costituita da sei bytes di valore FF esadecimale, seguiti dall’Indirizzo MAC del nodo bersaglio ripetuto 16 volte, per un totale di 96 bytes, e da un campo password opzionale che può essere assente, lungo 4 bytes o 6 bytes (fonte Wikipedia ).
Ok va bene la teoria, ma dimmi come metterla in pratica…

Come inviare Wake-on-LAN (WOL) magic packet con PowerShell

Lo script di base è questo insieme ai commenti esplicativi:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#Definiamo indirizzo MAC target,
# può contenere i separatori ":" o "-" oppure la sola stringa esadecimale
$MAC = "1A:2B:3C:4D:5E:6F"
#Convertiamo l'indirizzo MAC in un array di byte
$ByteArray = $MAC -replace "[:\-]" -split "(..)" -ne '' | ForEach-Object { [Byte] "0x$_"}
#Creiamo il Magic Packet secondo le specifiche WOL
[Byte[]] $MagicPacket = (,0xFF * 6) + ($ByteArray * 16)
#Utilizziamo metodo .NET per creare un oggetto UdpClient
$Client = New-Object System.Net.Sockets.UdpClient
#Settiamo la destinazione del Magic Packet verso l'indirizzo di broadcast della nostra rete sulla porta 7
$Client.Connect(([System.Net.IPAddress]::Broadcast),7)
#Inviamo il Magic Packet
$Client.Send($MagicPacket,$MagicPacket.Length)
#Terminiamo UdpClient
$Client.Close()

Questo script ovviamente vale solo per macchine target presenti sulla nostra stessa rete, come facciamo se invece il target è su un’altra rete?

In questo caso dovremo affidarci ad una macchina “ponte”, un host che risiede sulla rete target.

Volendo, abilitando WinRM sulla macchina ponte, possiamo modificare lo script come segue:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$MAC = "1A:2B:3C:4D:5E:6F"
$BRIDGE_HOST = "[HOST_DNS_NAME|HOST_IP]"
$script = {
	$ByteArray = $Using:MAC -replace "[:\-]" -split "(..)" -ne '' | ForEach-Object { [Byte] "0x$_"}
	[Byte[]] $MagicPacket = (,0xFF * 6) + ($ByteArray * 16)
	$Client = New-Object System.Net.Sockets.UdpClient
	$Client.Connect(([System.Net.IPAddress]::Broadcast),7)
	$Client.Send($MagicPacket,$MagicPacket.Length)
	$Client.Close()
}
Invoke-Command -ComputerName $BRIDGE_HOST -ScriptBlock $script -Credential (Get-Credential)

In questo caso lo script, da lanciare comunque in locale sulla nostra macchina, oltre alla variabile $MAC avrà anche $BRIDGE_HOST da customizzare con indirizzo IP oppure nome DNS della macchina ponte, Invoke-Command eseguirà il codice $script sulla macchina ponte dopo averci richiesto le credenziali di accesso con (Get-Credential).

wol powershell script

Conclusioni

Sebbene nel web possiamo trovare diversi programmi per il Wake-on-LAN già pronti, una soluzione nativa Windows ci permette una flessibilità maggiore.
Potremo sempre personalizzarla secondo le nostre esigenze senza particolari difficoltà, inoltre ci permette di integrare il WOL in flussi di lavoro preesistenti o semplicemente aggiungere funzionalità alla nostra collezione di script preferita. Che ne dite?