Находясь далеко от консоли, часто возникает необходимость в удаленном управлении машиной. Посмотреть работающие процессы, завершить сеанс пользователя, перезапустить зависший демон, запустить скрипт или перезагрузить хост. Для удаленного управления форточками на сегодня существует стандартное подключение к удаленному рабочему столу по протоколу RDP и множество ПО от сторонних производителей. Однако эти способы требуют отдельного подключения к каждому управляемому объекту, а также установки на них серверных частей, что зачастую блокируется антивирусным ПО (впрочем, о чем это я, ведь мы планируем управлять исключительно своей личной машиной?).

Но при подключении к своему компьютеру с помощью публичной точки доступа вероятен облом — некоторые порты TCP могут быть запрещены. Выход из этой ситуации я нашел в решении построить web-сайт, который будет размещен либо на управляемой машине, либо на любой машине домена, на которой запущен сервер с админскими правами.

Естественно, доступ к сайту ограничим паролем, а подключаться к нему будем по протоколу SSL.

 

К делу!

В качестве web-сервера применяется сборка "Денвер" (джентльменский набор web-разработчика) с PHP интерпретатором версии 5.2. Развернем web-сервер на управляемой машине, либо на любой машине домена под учеткой с административными правами доменного админа.

Денвер устанавливается крайне просто — на сайте разработчика есть подробная инструкция. В моём случае я просто установил диск с папками web-сервера как диск A, подключающийся при старте системы (флоппи-дисковода у меня нет и в BIOS он отключен). Каталог www, показанный на рисунке "Содержимое нашего каталога", будет содержать файлы (php-скрипты) нашей системы удаленного управления.

Для обеспечения безопасности доступа к сайту управления необходимо в каталоге WWW разместить файлы .htaccess и .htpasswd со следующим содержимым (для .htaccess):

<Files .htpasswd>
deny from all
</Files>
AuthType Basic
AuthName "Private zone. Only for Administrators!"
AuthUserFile a:homelocalhostwww.htpasswd
require valid-user

Здесь мы прописываем тип аутентификации (базовая) и путь к файлу с паролями.

Файл .htpasswd содержит зашифрованные пароли пользователей (файл создается с помощью утилиты htpasswd.exe из комплекта дистрибутива WEB-сервера Apache), вот пример его содержимого:

wmimin:$apr1$gg1.....$Si…p0RHtOvEsQzAkg3Y0
wmioper:$apr1$JxT6./..$X…WF94oRqOlKXRKsKrU0

У меня используются два юзера — в дальнейшем первый имеет право на перезагрузку и отключение машин, а второй — не имеет.

Если у тебя нет фиксированного IP-адреса, то для того, чтобы наш сайт управления был виден извне, необходимо зарегистрироваться на dyndns.com (либо аналогичном сайте, предоставляющем услугу динамического DNS), а затем в настройках маршрутизатора (например, для DLink при ADSL подключении) прописать полученный логин и пароль.

Для доступа снаружи на наш web-сервер необходимо также добавить IP-машины с сайтом в DMZ-зоне.

 

Разбираем принцип работы

Теперь расскажу о том, как осуществляется мониторинг либо управление машинами через наш сайт. Для этого мы используем подключение из PHP к подсистеме WMI виндовых машин посредством создания новых COM-объектов.

WMI (инструментарий управления осями Windows) предоставляет нам возможность подключаться к следующим провайдерам:

  • Dsprov.dll, провайдер каталога Active Directory (Active Directory provider), позволяет обращаться к Active Directory как к объекту WMI;
  • Ntevt.dll, провайдер журнала событий (Event Log provider), дает возможность управлять журналом событий;
  • Wbemperf.dll, провайдер системных счетчиков (Perfomance Counter provider) — обеспечивает доступ к счетчикам произоводительности;
  • Stdprov.dll, провайдер реестра (Registry provider), позволяет осуществлять чтение и изменение реестра;
  • Snmpincl.dll, провайдер SNMP-устройств (SNMP provider), открывает шлюз доступа к SNMP (Simple Network Management Protocol);
  • Wmiprov.dll, провайдер драйверов устройств (WDM provider), дает возможность получать информацию низкого уровня о драйверах устройств Windows Driver Model (WDM);
  • Cimwin32.dll, провайдер подсистемы Win32 (Win32 provider), обеспечивает доступ к информации о компьютере, ОС, подсистеме безопасности, дисках, периферийных устройствах, файловых системах, файлах, папках, сетевых ресурсах, принтерах, процесах, сервисах и так далее;
  • Msiprov.dll, провайдер установленного ПО (Windows Installer provider) — позволяет получать информацию об установленном ПО.

Для вывода на web-страницу информации о текущем состоянии машины (память, процессы, службы), а также для выполнения некоторых административных действий необходимо написать функции, которые будут вызываться с параметрами (имя машины или IP-адрес), а затем выводить результат своей работы в соответствующее поле web-страницы. Самые интересные и используемые в рамках нашего проекта функции будут требовать обращения к провайдерам подсистемы Win32 и провайдеру реестра.

 

Работаем с реестром удаленно

На сегодня у меня реализованы как мониторинговые, так и управляющие функции. Из мониторинговых стоит выделить функцию получения и вывода информации о версии BIOS, производителе и модели материнской платы. Данный функционал реализуется с помощью создания нового COM-объекта подключением к провайдеру StdRegProv подсистемы WMI. Все рассмотренные функции вызываются с переменной $server, которая содержит имя управляемой удаленной машины в локальной сети либо ее IP-адрес:

$obj = new COM('winmgmts:{impersonationLevel=impersonate}//'
.$server.'/root/default:StdRegProv’);
$obj->getStringValue(HKLM,$keypath1,$keyvalue_def,$key);
echo "BIOS release date: ".$key."rn";
$obj->getStringValue(HKLM, $keypath2,$keyvalue_mb_model, $key);
echo "Mainboard model: ".$key ."rn";

Таким образом, после создания нового COM-объекта методом getStringValue мы читаем раздел реестра HKLM (выбор раздела реестра задается константой, в нашем случае — объявлением define('HKLM',0x80000002);). При необходимости читать другие разделы реестра указываем другие константы:

Const HKEY_CLASSES_ROOT = 0x80000000
Const HKEY_CURRENT_USER = 0x80000001
Const HKEY_LOCAL_MACHINE = 0x80000002
Const HKEY_USERS = 0x80000003
Const HKEY_CURRENT_CONFIG = 0x80000005

В результате работы скрипт выводит нам следующие данные (в моем случае):

BIOS release date: 04/30/10
Mainboard manufacturer: Gigabyte Technology Co., Ltd.
Mainboard model: G31M-ES2L

Кроме используемого метода getStringValue существуют дополнительные методы работы с провайдером StdRegProv, среди них:

  • GetBinaryValue — чтение значений типа BINARY;
  • GetDWORDValue — чтение значений типа DWORD;
  • GetExpandedStringValue — чтение значений типа EXPANDED STRING;
  • GetMultiStringValue — чтение значений типа MULTI STRING;
  • CreateKey — создание ключа реестра;
  • SetBinaryValue — запись значения типа BINARY;
  • SetDWORDValue — запись значения типа DWORD;
  • SetExpandedStringValue — запись значения типа EXPANDED STRING;
  • SetMultiStringValue — запись значения типа MULTI STRING;
  • SetStringValue — запись строкового значения;
  • DeleteKey — удаление ключа;
  • DeleteValue — удаление значения ключа;
  • EnumKey — получить перечисление ключей реестра;
  • EnumValues — получить перечисление значений ключей;
  • CheckAccess — проверка прав доступа к ключу реестра.

В данном случае они не используются, а подробнее узнать об их применении можно в великом MSDN.

 

Мониторим систему удаленно

Для осуществления функций мониторинга системы потребуется работать с пространством имен WMI (/root/cimv2), что даст нам возможность обращаться к необходимым провайдерам Win32_Processor, Win32_OperatingSystem, Win32_PerfFormattedData_PerfOS_System, Win32_OperatingSystem, Win32_Process, Win32_Service.

Итак, получаем информацию о центральном процессоре системы (CPU), включая его загрузку в процентах и данные CPUID, для этого сделаем так:

$obj = new COM ('winmgmts:{impersonationLevel=impersonate}//'
.$server.'/root/cimv2');
$pc = 0;
foreach ($obj->instancesof('Win32_Processor') as $mp)
{
echo "Processor (".++$pc.")rn";
echo "Name: ".trim( $mp->Name )." @ " .
$mp->CurrentClockSpeed . " MHzrn";
echo "CPU Load: ".$mp->LoadPercentage . "%rn";
}

Здесь мы создаем новый COM-объект и, обращаясь к методам провайдера Win32_Processor, получаем нужную нам информацию:

Processor (1)
Processor Id: BFEBFBFF0001067A
Name: Pentium(R) Dual-Core
CPU E5300 @ 2.60GHz @ 1196 MHz
CPU Load: 18%
CPU Status: OK
CPU Stepping:
CPU Revision: 5898
System Name: GUZY

Данные о температуре процессора мы можем получить, обратившись к пространству имен /root/WMI и провайдеру MSAcpi_ThermalZoneTemperature. Получение актуальной температуры CPU работает не на всех материнских платах ПК, зато прекрасно работает на ноутах.

Работа с пространством имен /root/WMI и провайдером MSAcpi_ThermalZoneTemperature:

$obj = new COM ('winmgmts:{impersonationLevel=impersonate}//'
.$server.'/root/WMI');

foreach($obj->instancesof ('MSAcpi_ThermalZoneTemperature') as $mp)
{
echo "<pre>rn";
$ctemp=($mp->CurrentTemperature);
echo "<b>Current CPU temperature: " . ( $ctemp — 2732)/10 . "C" . "rn";
}

Здесь перед выводом на страницу мне пришлось перевести температуру из кельвинов в привычные русскому глазу единицы Цельсия. Двигаемся дальше и с помощью старого доброго пространства имен /root/cimv2 получаем информацию об установленной оси, сервис-паках и аптайме. Здесь использованы методы провайдеров Win32_OperatingSystem и Win32_PerfFormattedData_PerfOS_System. Для перевода секунд при отображении uptime используется функция format_time($temp).

Выводим параметры OS’и и uptime:

foreach($obj->instancesof('Win32_OperatingSystem') as $mp )
{
$temp=($mp->Name);
echo "OS name: " .substr($temp,0,-40). "rn";
$temp2=($mp->ServicePackMajorVersion);
echo "Service pack: " . $temp2 . "rn";
}

foreach ($obj->instancesof('Win32_PerfFormattedData_PerfOS_System') as $mp)
{
$temp=($mp->SystemUpTime);
echo "System uptime: ".format_time($temp)."rn";
}

Результаты работы наших скриптов:

OS name: Microsoft Windows Server 2008 R2 Enterprise
Service pack: 0
System uptime: 23hour 32min 42sec

Таким образом, с помощью языка PHP в связке с WMI мы можем получать любую информацию о ПК удаленно.

 

Рулим виндами удаленно

Для реализации перезагрузки ПК необходимо обратиться к пространству имен /root/cimv2 и вызвать метод Reboot провайдера Win32_OperatingSystem. Для завершения работы необходимо вызвать метод ShutDown.

Удаленная перезагрузка системы:

$obj = new COM('winmgmts:{impersonationLevel=impersonate,(Shutdown)}//'
.$server.'/root/cimv2');
foreach($obj->instancesof('Win32_OperatingSystem') as $mp)
{
echo "<pre>rn";
echo "<b>Rebooting immediatelyrn</b>rn</pre>";
$ctemp=($mp->Reboot);
}

Для просмотра запущенных служб:

$process = $obj->execquery("SELECT * FROM Win32_Service");
foreach ( $process AS $row )
{
echo "<pre>rn";
echo "NAME: " . $row->Name .",
rnDISPLAY NAME:".strtolower($row->DisplayName).",
rnPATH: " . strtolower($row->PathName ). ",
rnSTATE: " . strtolower($row->state )."<br/>";
}

Для просмотра процессов:

$process = $obj->execquery("SELECT * FROM Win32_Process");
if ( $process->count > 0 )
{
foreach ( $process AS $row )
{
echo "<pre>rn";
echo "PID: ".$row->processid.",
rnPROCESS NAME: ".strtolower( $row->name ).",
rnMEMORY USAGE: ".number_format
( $row->workingsetsize )."<br/>";
}
}

Для запуска или остановки служб используем методы StartService и StopService объекта Win32_Service:

$process = $obj->execquery("SELECT * FROM Win32_Service Where Name='$servicesname'");
foreach ($process AS $row)
{
$row->StartService();
echo "Service started!";
}

А вот для запуска процессов придется использовать метод Create объекта win32_process:

$obj_win32_process=new COM('winmgmts:{impersonationLevel=impersonate}//'
.$server.'/root/cimv2:Win32_Process');
$obj_win32_process->Create($processname,Null,Null,lngProcessID2);
echo "Process created!";

 

Заключение

Таким образом, используя все возможности WMI-провайдеров из PHP, можно получать и публиковать на web-сайте любую информацию об удаленных машинах, а также практически без ограничений ими управлять, манипулируя процессами, службами и реестром. В рамках статьи показаны лишь наиболее простые варианты применения связки PHP и WMI для удаленного мониторинга и управления Windows-системами. В исходниках ты найдешь пример получения PTR (pointer) записей домена (файл dns_ptr.php), реализованный с помощью использования пространства имен /root/MicrosoftDNS и провайдера MicrosoftDNS_PTRType. Вся эта система у меня реализована в виде web-сайта с подключаемыми модулями-функциями.

В общем, теперь все рычаги управления Windows-системами c помощью php-интерпретатора в твоих руках — пользуйся, но не в деструктивных целях!

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии