У администраторов, часто бывают ситуации, когда надо включить компьютер, а физического доступа к нему нет. Например чтобы проводить в не рабочее время обновления системы или провести очередную проверку на наличие вирусов.
Сначала немного о Wake-on-LAN:
Wake-on-LAN — технология позволяющая включить компьютер, с помощью сетевой карты.
Для того, что бы это удалось сетевая карта данного компьютера должна получить «Magic packet».
На практике для этого компьютер должен удовлетворять следующим требованиям:
Блок питания должен соответствовать стандарту ATX 2.01
Материнская плата должна поддерживать Wake-on-LAN
Сетевая плата должна поддерживать Wake-on-LAN, если сетевая плата внешняя и не соответствует стандарту PCI 2.2 то необходим специальный трёхжильный кабель, для соединения разъёмов Wake-on-LAN на материнской плате и на сетевой карте.
Так же соответствующие настройки должны быть включены, как в биосе материнской платы, так и в драйверах сетевой карты.
На практике все современные компьютеры поддерживают эти технологии. Поэтому вопрос может возникнуть о включении Wake-on-LAN для этого рекомендую почитать инструкцию к материнской плате.
Так же следует учесть, что сетевая карта должна «слушать» сеть в ожидании «Magic packet». Для этого интерфейс ACPI не должен переходить в состояние G3, то есть в механическое выключение системы. Это может произойти при сбое питания компьютера.
Например:
Выключение компьютера из «розетки».
Аварийное выключение (зажатие кнопки питания на 10 секунд).
Выключение компьютера с блоком питания AT.
Что же такое Magic packet?
Это 6 байт забитых «0xFF» — называемые цепочкой синхронизации.
И дальше 96 байт, в которых mac адрес включаемого компьютера повторяется 16 раз.
Всё это можно упаковать в UDP или IPX пакет. Обычно используется UDP.
Следовательно, если компьютер с которого отсылается «Magic packet» и компьютер который мы хотим включить по Wake-on-LAN находится в одной подсети. То нам надо знать mac адрес сетевой карты включаемого компьютера.
Если нам надо разбудить компьютер в другой подсети, то нам так же надо знать ip адрес который может переслать broadcast в подсеть с включаемым компьютером. В качестве такого ip может выступать ip самого включаемого компьютера, тогда UDP пакет уйдёт к нужному компьютеру. Однако у меня этот вариант не сработал из за частой очистки ARM таблицы на маршрутизаторах. Это выглядело так, что через некоторое время компьютер переставал включаться.
И так все технические моменты решены и нам надо сформировать «Magic packet».
Сформировать «Magic packet» можно следующим скриптом на Powershell:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$Mac='01-2C-34-4C-1C-12' $BroadcastProxy=[System.Net.IPAddress]::Broadcast $Ports = 0,7,9 $synchronization = [byte[]](,0xFF * 6) $bmac = $Mac -Split '-' | ForEach-Object { [byte]('0x' + $_) } $packet = $synchronization + $bmac * 16 $UdpClient = New-Object System.Net.Sockets.UdpClient ForEach ($port in $Ports) {$UdpClient.Connect($BroadcastProxy, $port) $UdpClient.Send($packet, $packet.Length) | Out-Null} $UdpClient.Close() |
Разберём данный скрипт:
1 |
$Mac='01-2C-34-4C-1C-12' |
Здесь мы в переменную заносим мак адрес включаемого компьютера. Разделителем указываем «-»
2 |
$BroadcastProxy=[System.Net.IPAddress]::Broadcast |
Указываем ip адрес который сможет доставить наш пакет до сетевого интерфейса нашего компьютера если компьютеры находятся в одной подсети, то это может быть ip адрес broadcast настроенный на сетевой карте текущего компьютера ([System.Net.IPAddress]::Broadcast). Если же компьютеры находятся в разных подсетях, то указываем либо ip адрес компьютера который надо включить, либо ip адрес через который можно переслать broadcast в другую подсеть.
3 |
$Ports = 0,7,9 |
Указываем порт(группу портов) по которому будет пересылаться пакет, в нашем варианте пакеты будут отсылаться через порт 0, порт 7 и порт 9.
5 |
$synchronization = [byte[]](,0xFF * 6) |
Создаём цепочку синхронизации «Magic packet»
6 |
$bmac = $Mac -Split '-' | ForEach-Object { [byte]('0x' + $_) } |
Преобразовываем mac адрес в тип [byte], если вы хотите изменить разделитель в mac адресе, например на ‘:’, то следует изменить ‘-‘ на ‘:’ то есть данная строчка будет выглядеть следующим образом:
6 |
$bmac = $Mac -Split ':' | ForEach-Object { [byte]('0x' + $_) } |
7 |
$packet = $synchronization + $bmac * 16 |
Формируем пакет данных, где в начале идёт цепочка синхронизации, а потом 16 раз повторяется мак адрес.
9 |
$UdpClient = New-Object System.Net.Sockets.UdpClient |
Запускаем конструктор класса UdpClient
11 12 |
ForEach ($port in $Ports) {$UdpClient.Connect($BroadcastProxy, $port) $UdpClient.Send($packet, $packet.Length) | Out-Null} |
Для каждого из портов, устанавливаем соединение с ip $BroadcastProxy и портом $port, дале отправляем данные из $packet количеством байт $packet.Length. Сообщение с результатом функции .Send не показываются (отсылаются в Out-Null).
13 |
$UdpClient.Close() |
Закрываем соединение.
Спасибо, работает.
Если же компьютеры находятся в разных подсетях, то указываем либо ip адрес компьютера который надо включить, либо ip адрес через который можно переслать broadcast в другую подсеть.
Каким образом прописывать конкретный ip? Просто присвоить переменной значение ip-адреса? Пытался, не помогает
Добрый день. А как добавить несколько mac адресов, чтобы включить сразу несколько ПК?
Можно завернуть в функцию. Но к сожалению под рукой нет винды писал в блокноте:
function Up-Computer {param ( [Parameter(Mandatory,ValueFromPipeline)]$Mac='01-2C-34-4C-1C-12' $BroadcastProxy=[System.Net.IPAddress]::Broadcast $Ports = 0,7,9 ) $synchronization = [byte[]](,0xFF * 6) $bmac = $Mac -Split '-' | ForEach-Object { [byte]('0x' + $_) } $packet = $synchronization + $bmac * 16 $UdpClient = New-Object System.Net.Sockets.UdpClient ForEach ($port in $Ports) {$UdpClient.Connect($BroadcastProxy, $port) $UdpClient.Send($packet, $packet.Length) | Out-Null} $UdpClient.Close()}@('01-2C-34-4C-1C-12','01-2C-34-4C-1C-12','01-2C-34-4C-1C-12')|Up-Computer
что то типо того.