Wake-on-LAN (WoL) is a networking standard that uses magic packets to turn on or wake locally networked computers. Sysadmins have used WoL for years to help them manage their IT environments and drastically reduce their step counts. But if you’re looking to get a bit more functionality from Wake-on-LAN, it might be time to make your own magic packet using PowerShell.
Why use PowerShell for Wake-on-LAN?
Most people use a dedicated WoL application or a management suite that includes WoL functionality. These solutions are great, but you’re limited to the feature set provided by the software. With PowerShell, you’re only limited by your imagination (or skill set, in my case) and the inherent limitations of WoL.
Here are just a couple reasons you might want to use PowerShell for Wake-on-LAN.
Automations: PowerShell was designed with automations in mind. If you need to automate your WoL processes, PowerShell is the answer. It turns out automation isn’t just a buzzword.
Deployments: Wake-on-LAN is often limited in use because magic packets aren’t routable. They are limited to their local area networks (hence the name Wake-on-LAN). There are a few ways around this limitation, but deploying a WoL PowerShell script on a remote device is one of the easiest workarounds.
What is a magic packet?
A Wake-on-LAN (WoL) magic packet is a byte array with 6 bytes of value 255 (0xFF) and 16 repetitions of a target machine’s 48-bit (6-byte) MAC address. Magic packets are broadcast to the local network, and typically aren’t routed past a given subnet. Though magical in name, there’s not much magic behind the scenes beyond some pretty standard networking wizardry.
How to create a Wake-on-LAN magic packet with PowerShell
Creating our WoL magic packet with PowerShell is easy enough because we know the structure of the frame. We’ll start by adding 6 bytes of 255 (0xFF), followed by the device MAC address repeated 16 times. Completely written out and with a target MAC address of 1A:2B:3C:4D:5E:6F, our byte array would look like this:
[Byte[]] $ByteArray =
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F,
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F
I don’t know about you, but to me this looks like someone just fell asleep on their keyboard. Plus, entering the MAC address 16 times drastically increases the likelihood that I’ll fat-finger the input. Instead, let’s have PowerShell repeat the input for us.
$Mac = "1A:2B:3C:4D:5E:6F"
$MacByteArray = $Mac -split "[:-]" | ForEach-Object { [Byte] "0x$_"}
[Byte[]] $MagicPacket = (,0xFF * 6) + ($MacByteArray * 16)
With this new syntax, we enter the MAC address once and assign it to the $Mac
variable. Next, we convert the MAC address to the proper format, add it to the byte array, and ensure that the values are added the appropriate number of times. The results are much prettier and not nearly as vulnerable to a missed keyboard press.
Now that we’ve got our magic packet array configured, the last thing we need is to broadcast it to our subnet to wake up the appropriate target machine. To do that, we’ll use .NET to create a UdpClient object to find the broadcast address and send our magic packet. Here’s what the final Wake-on-LAN PowerShell script looks like.
$Mac = "1A:2B:3C:4D:5E:6F"
$MacByteArray = $Mac -split "[:-]" | ForEach-Object { [Byte] "0x$_"}
[Byte[]] $MagicPacket = (,0xFF * 6) + ($MacByteArray * 16)
$UdpClient = New-Object System.Net.Sockets.UdpClient
$UdpClient.Connect(([System.Net.IPAddress]::Broadcast),7)
$UdpClient.Send($MagicPacket,$MagicPacket.Length)
$UdpClient.Close()
When you’re ready to run the command, simply replace the MAC address in the script with the MAC address of the target computer. Keep in mind that this WoL command is a broadcast and does not traverse subnets. If you run the script from your computer, the message only broadcasts to your local subnet. But there is something we can do to get around this limitation.
How to send a Wake-on-LAN packet across networks
To get around the local limitations of Wake-on-LAN, we can run a magic packet PowerShell command on a remote computer that is on the same local network as the targeted device using the Invoke-Command cmdlet.
Here’s a modified version of the WoL script that prompts you for a remote computer to run the command on and the target MAC address.
$RemoteComputer = Read-Host -Prompt "Input the name of the device to send the Wake-on-LAN command"
$Mac = Read-Host -Prompt "Input the target MAC address"
Write-Verbose -Message "Converting MAC address $($Mac) to a byte array" -Verbose
$MacByteArray = $Mac -split "[:-]" | ForEach-Object { [Byte] "0x$_"}
[Byte[]] $MagicPacket = (,0xFF * 6) + ($MacByteArray * 16)
Write-Verbose -Message "Sending Wake-on-LAN command to $($RemoteComputer)." -Verbose
Invoke-Command -ComputerName $RemoteComputer -ScriptBlock {
$UdpClient = New-Object System.Net.Sockets.UdpClient
$UdpClient.Connect(([System.Net.IPAddress]::Broadcast),7)
$UdpClient.Send($using:MagicPacket,$using:MagicPacket.Length)
$UdpClient.Close()
}
In this variation of the script, the byte array is created locally and then passed to the remote device, which sends a magic packet broadcast.
How to turn on remote devices with magic packets
Even after adding the functionality to run the Wake-on-LAN script across your network, it still won’t be able to target truly remote devices. However, PDQ Connect makes it possible to turn on remote devices with WoL. Keep in mind that you need to have a second device that is turned on and located on the same network as the targeted device. And if you’re not already using PDQ Connect, try it out for free and see how it can help you manage all your remote computers.