Jump to content
iT4iT.CLUB
Kitsum

ProduKey + PHP как один из способов анализа обстановки с лицензированием софта оконной компании

Recommended Posts

Всем доброе время суток.

Сегодня пойдет речь об одном из вариантов сбора информации о лицензиях операционных системах Windows и некоторого сопутствующего программного обеспечения.  Для сбора будет использована утилита ProduKey, это далеко не идеальный вариант, но вполне приемлемый, если нет иных средств мониторинга, и требуется что-то быстро слепить на коленке без траты денег.

И так, имеется группа компьютеров находящихся в домене, подсеть 10.10.10.0/24, ProduKey запускается от учетной записи администратора домена или администратора той ветки, к которой принадлежит подсеть.

Программой можно пользоваться как в графическом интерфейсе, так и в консольном режиме. Последний вариант, лично для меня, более предпочтителен.

get-windows-office-keys2.png

ВАЖНО: нам требуется программа только на Английском языке т.к имена ключей использующихся в отчетах должны соответствовать именам ключей в PHP скрипте далее.

В корне с программой создаем .bat файл со следующим содержимым

produkey.exe /iprange 10.10.10.2 10.10.10.254 /sjson 10.10.10.0.json /WindowsKeys 1 /OfficeKeys 1 /SQLKeys 1 /IEKeys 0 /ExchangeKeys 1 /ExtractEdition 0

Используемые параметры

  • /iprange - указывает диапазон адресов для сканирования
  • /sjson - файл отчета необходимо сохранить в формате json
  • /WindowsKeys 1 - собирать ключи операционных систем
  • /OfficeKeys 1 - собирать ключи Office
  • /SQLKeys 1 - собирать ключи SQL сервера
  • /IEKeys 0 - НЕ собирать ключи IE
  • /ExchangeKeys 1 - собирать ключи Exchange
  • /ExtractEdition 0 - НЕ собирать расширенную информацию об операционной системе

Это один из вариантов запуска, большее количество параметров описано на сайте разработчика.

После того, как утилита закончит свою работу, она сохранит отчет в формате json в указанный нами файл. Можно использовать и другие форматы отчетов, но явного представления о количестве и качестве мы не получим. Программа только собирает данные, все остальные манипуляции с ними ложатся на плечи рядовых администраторов.

Но не беда, на помощь нам приходит, уже затертый до дыр, Apache + PHP.

Все файлы отчета помещаем на машину, где установлены эти ребята, и обязательно за пределами Web сервера. Сам PHP скрипт будет выглядеть следующим образом.

<?PHP
if(false) {
    ini_set('error_reporting', E_ALL);
    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
}
$myKeys = array(
    'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX' => 'Управляющая компания',
    'YYYYY-YYYYY-YYYYY-YYYYY-YYYYY' => 'Завод №1',
    'ZZZZZ-ZZZZZ-ZZZZZ-ZZZZZ-ZZZZZ' => 'Складская зона',
);
$info = array();
/*
 Тут указываем путь и шаблон поиска файлов отчетов (Here we specify the path and template for finding report files)
 glob("../../../info/log_*.json")
 glob("/var/log/*.json";
 glob("*.json");
*/
foreach(glob("*.json") as $file) {
    $json = str_replace(array("\r\n", "\n"), '', file_get_contents($file));
    $json = json_decode(iconv('cp1251', 'utf-8', $json), true);
    if(is_array($json)) {
        foreach($json as $id => $obj) {
            if(preg_match_all('/(.+) \((.+)\)/m', $obj['Computer Name'], $host)) {
                $ip =& $host[2][0];
                $name =& $host[1][0];

                $net = explode('.', $ip);
                array_splice($net, 3);
                array_push($net, '0');
                if($ip  == $name) $name = '<u>'.$name.'</u>';
                $net = implode('.', $net);
                $info[$obj['Product Name']][$obj['Product Key']][$net][] = $ip.' ('.$name.')';
            }
        }
    }
}
echo '<html lang="ru-RU" dir="ltr">';
echo '<head>';
echo '<style type="text/css">body {cursor: default;} i b:hover {color: forestgreen; text-decoration: underline;} #host:hover {color: forestgreen;}</style>';
echo '<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>';
echo '</head>';
echo '<body>';
echo '<pre>';
$uSoft = 0;
$uKey  = 0;
$uNet  = 0;
foreach($info as $software => $keys) {
    $uSoft++;
    echo "<b style='font-size: large; cursor: pointer;' onclick=\"if($('div#s".$uSoft."').is(':visible')) $('div#s".$uSoft."').hide(400); else $('div#s".$uSoft."').show(400);\">".$software."</b> <i style='font-size: normal;'>(licenses: ".count($keys).")</i>\n";
    echo "<div id='s".$uSoft."' hidden>";
    asort($keys);
    foreach($keys as $key => $subnet) {
        $uKey++;
        if(!$key) $key = 'UNKOWN';
        echo "\t<i><b style='cursor: pointer; color: forestgreen;' onclick=\"if($('div#k".$uKey."').is(':visible')) $('div#k".$uKey."').hide(400); else $('div#k".$uKey."').show(400);\">".$key."</b> (hosts: ".(count($subnet, COUNT_RECURSIVE) - count($subnet)).")</i> <b style='color: red;'>".(isset($myKeys[$key])? $myKeys[$key] : '')."</b>\n";
        echo "<div id='k".$uKey."' hidden>";
        foreach($subnet as $net => $host) {
            $uNet++;
            echo "\t\t<i><b style='cursor: pointer;' onclick=\"if($('div#n".$uKey.$uNet."').is(':visible')) $('div#n".$uKey.$uNet."').hide(400); else $('div#n".$uKey.$uNet."').show(400);\">".$net."</b> (hosts: ".count($host).")</i>\n";
            echo "<div id='n".$uKey.$uNet."' hidden style='padding-bottom: 10px;'>";
            foreach($host as $name) echo "\t\t\t<span id='host'><i>".$name."</i></span>\n";
            echo "</div>";
        }
        echo "</div>";
    }
    echo "</div>\n";
}
echo '</pre>';
echo '</body>';
echo '</html>';
?>

Просто и сердито.

На выходе мы получаем каталогизированный список программного обеспечения, используемых ключей и списка хостов на которых были найдены эти ключи с сортировкой по сетям.

get-windows-office-keys.png

Также в скрипте можно указать список ключей и дать им имена.

$myKeys = array(
    'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX' => 'Управляющая компания',
    'YYYYY-YYYYY-YYYYY-YYYYY-YYYYY' => 'Завод №1',
    'ZZZZZ-ZZZZZ-ZZZZZ-ZZZZZ-ZZZZZ' => 'Складская зона',
);

Удобно если требуется явно указать на какие подразделения или объекты приобреталась та или иная лицензия. Все совпадения будут выделены красной подписью.

Выводы

Из плюсов, это явная простота и стоимость данного решения. Начальную статистику можно получить уже через пару часов после поднятия вопроса о необходимости иметь результат еще вчера. Наглядность представления. Можно добавить расчет стоимости поддержания данного софта в "деревянных" или сразу в "бакинских", ну и естественно принять соответствующие меры, какие, решать уже Вам.

Из минусов, это не 100% результативность т.к статистика будет получена только по тем машинам, которые были онлайн на момент сканирования. Отсутствие системы кэширования для накопления данных при периодических опросах сети. Хотя последнее можно исправить средствами PHP, но пока такая задача не ставилась.

  • Like 1

Share this post


Link to post
Share on other sites
foreach(glob("*.json") as $file) {

 

Можно складывать отчёты на мелкомаечную шару и монтировать на linux, в моём случае это debian.

Инсталим  cifs-utils если ещё нет.

apt-get install cifs-utils 

Создаём директорию куда будем монтировать

mkdir -p /mnt/win/ 

Ну и смонтируем с вариантом подключения пользователя в домене

mount -t cifs //АДРЕС/ШАРЫ /mnt/win/ -o dom=ДОМЕН,user=ПОЛЬЗОВАТЕЛЬ,pass=ПАРОЛЬ

Или без авторизации

mount -t cifs //IP/SHARE /mnt/win/  -o guest

На самом деле вариантов много, но это уже другая история. В итоге вставляем в скрипт путь до файлов с отчётами, как-то так.

foreach(glob("/mnt/win/*.json") as $file) {

Удачи!

  • Like 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

  • Similar Content

    • By Kitsum
      Описанный ниже велосипед является продолжением одной из моих статей на другом, интересном мне, ресурсе. Продолжение и все последующие обновления будут происходить только на it4it.club
      Для начала, хочу процитировать самого себя и тем самым дать пояснения: почему, зачем и для кого это нужно.
      Данная тема получила большую популярность у коллег и не раз выручила Вашего покорного слугу, не дав разгореться стулу на котором он сидит.
      Но имеющегося функционала стало не хватать, требовалось не только слышать и иногда видеть, а еще получать удаленный доступ к оборудованию и лицезреть всю картину в целом.
      Задача поставлена, идем исполнять, но с начало забегу немного вперед и продемонстрирую текущий функционал.
      Общее окно программы переработано и теперь отображает список всех групп из Zabbix с их хостами. Список активных триггеров переехал в нижнюю часть окна и отображает дополнительную информацию об узлах с которыми не все гладко. Сам список можно увеличивать, если все совсем плохо, или уменьшать если выражение "Хьюстон у нас проблемы" Вы слышите только в фильмах. Также появились цветные маркеры важности триггера. По двойному клику по активному триггеру мы перемещаемся в соответствующую группу где находится проблемный узел.
      Не забыли и про то, ради чего вся начальная песня и писалась - трей с всплывающими оповещениями и звуковым сигналом. Основное окно сворачивается именно туда, чтобы не залеживаться на панели где ценится каждый свободный пиксель.
      Хосты в группах стали кликабельны, правда пока только ПКМ, и имеют всплывающее меню позволяющее выполнять банальные действия:
      Подключение к узлу:
      Telnet SSH RDP VNC Проверка соединения:
      Ping Traceroute Естественно его можно расширить, добавив всяких вкусностей по мере возрастания аппетита IT отдела.
      Программа по прежнему имеет серверную и клиентскую часть, что позволило организовать кэширование запросов и осуществлять оповещения в момент определения проблемы сервером, а не по таймеру обновления, как это организовано в dashboard zabbix. Раньше узнали о проблеме, раньше приступили к устранению. Естественно и устаревшие триггеры убираются также оперативно.
      Также это позволило избавить программу от информации о доступе к серверу, что мне кажется не приемлемым для оповещалки. Чем меньше дырок, тем крепче сон.
      Приступим к реализации.
      Ну и естественно, Ваш покорный слуга еще не научился писать на C++ ничего более сложного чем "Hello World", поэтому клиент и сервер будет написан на PHP. За исключением того момента, что клиентская часть (при помощи магии Гарри Поттера) станет бинарным файлом. Бог с ним, серверная часть не доступна обывателю, а это самое важное!!!
      Для начала, нужно придумать безопасный и понятный алгоритм не нагружающий сервер т.к клиентов может быть 100и или 1000и, всякое бывает. Все не безопасные команды обязаны выполняться на сервере без участия клиента. Дальнейшая работа клиента: обработка данных, выполнение действий с триггерами и т.п должно выполняться только у клиента, не затрагивая сервер.
      При обращении клиента к серверу по http происходит проверка его ip на наличие в списках разрешенных. В противном случае показываем фигу. Проверяем, наличие актуального кеша, и отдаём его. Если кеша нет, генерируем новый. Если запрос прилетел от zabbix: принудительно считаем кеш устаревшим, генерируем новый и после этого рассылаем всем клиентам оповещения по UDP протоколу. Это позволит свести расход ресурсов базы данных к нулю т.к все клиенты ринутся забирать новые данные, а все уже в кеше. Супер, все дешево и сердито.
      Серверная часть представляет из себя файл index.php где-то на Вашем web сервере. Актуально для Zabbix 2.4 (скорее всего будет актуальна и для последующих версий, будем проверять по мере возрастания аппетита).
      Для дополнительной безопасности рекомендую создать отдельную учетную запись в базе данных с правами только на чтение и только к базе zabbix. Это актуально в наши дни.
      Переходи в zabbix
      Первым делом переходим в Настройка -> Действия -> Источники события: Триггеры и создать новое действие. Назовем случайным образом, например Report problems to ZabbixTrigger.
      В условиях выставляем
      Значение триггера = ПРОБЛЕМА Значение триггера = OK Это все необходимо, чтобы проблемы в GUI появлялись и исчезали точно именно тогда, когда это происходит в Zabbix (не путать с dashboard).
      Вкладка "Операции" должна выглядеть следующим образом. Естественно что путь до php скрипта должен быть вашим.
      Вуаля! Если Вы все сделали правильно (без кардинальных изменений), то я рад приветствовать нового ездока моего велосипеда. Поедем тандемом!
      Сам клиент прикреплен в конце поста.
      Для тех, кто читает титры в кинотеатре
      При запуске будет создан файл config.ini в корне программы. При необходимости, измените его настройки, благо их не много.
      [server] url="http://zabbix/zabbix-gui" update="60" [client] showalarm="20" Параметр url отвечает за http путь до скрипта на сервере, update за интервал (в секундах) обновления данных с сервера, а showalarm вроде как должен влиять на время отображения всплывающей подсказки в трее.
      Теперь немного структуры.
      В каталоге sounds находится звук оповещения о новом триггере, формат ogg Каталог icons содержит маркеры триггеров. trigger00 - для нормального состояния, а все последующие соответствуют начальным настройкам zabbix во вкладке Администрирование -> Общие раздел Важность триггеров. Можете изменить на свои цвета, программа все подхватит при перезагрузки. Ну и на закуску каталог ext, это как говорится для меломанов, содержит фри программы для обработки внешних действий клиента. Вы можете заменить их на свои при условии, что стандартные имена параметров запуска и их последовательность совпадают. PS: На этом все, спасибо тем кого это заинтересовало. Предлагайте свои идеи или способы доработки велосипеда. А если найдется программист на C++ так милости просим. В любом случае, функционал будет в дальнейшем расширяться.
      zabbixTrigger.zip
    • By Kitsum
      Update 03.12.2015
      Добавлена возможность отображать DNS имена для определенных хостов, это позволит явно и человеко-понятно идентифицировать соответствующие узлы в сети. Отсутствие записи на DNS сервере должно привлечь соответствующее внимание к хосту.  
      В конфигурацию добавлен параметр $domain позволяющий удалять из DNS имени хоста имя домена. Чтобы из name.domain.com сделать name, необходимо указать $domain = ".domain.com" Обновлена база производителей сетевого оборудования - oui.txt Мелки доработки интерфейса.  
      Update 26.11.2015
      Добавлена возможность отображать реальные имена портов (Fa1, Ethernet1/0/1, Port1 ...). Внимание: не все устройства способны передавать данную информацию, в связи с этим оставлены числовые идентификаторы, чтобы в таких случаях иметь систему идентификации.  
      Добавлена возможность описывать в конфигурации настройки для каждого устройства отдельно. Если не использовать эту возможность, то для оборудования будет применена общая конфигурация. Добавлена возможность описывать в конфигурации уникальные OID-ы для конкретного оборудования аналогично п.2. Мелкие доработки интерфейса и кода.  

      В данной теме мы будем рассуждать о мониторинге сетевого оборудования и подключенных к нему хостах. Следовало бы разместить её в другом разделе, но 90% всех манипуляций и дальнейшая эксплуатация будет производиться на UNIX-подобной платформе. В моем случае используется:
      Linux Ubuntu 14.04 Apache/2.4.7 PHP 5.5.9 Библиотека php5-snmp Также само сетевое оборудование (маршрутизаторы и свичи) должно поддерживать работу по протоколу SNMP и соответствовать стандартам ISO.
      Проект разработан отталкиваясь от топологии сети - звезда. Имеются множество отдельных подсетей 192.168.0.0 все они ходят во внешний мир через маршрутизаторы (в моем случае фирмы Cisco). В самих подсетях используются различные свичи, по большей части поддерживающие SNMP v1 и выше.
      Ранее я уже поднимал данную тему на другом, дружественном, форуме, но потом работа над проектом бала остановлена. На данный момент вопрос опять стал актуален и решено переделать как основную программу, так и внешний вид. Старая версия была написана на скорую руку и выглядела невзрачно и с большими изъянами в коде.
      На данный момент проект преобразился и выглядит следующим образом. Ваш браузер должен поддерживать HTML5.
      Чтобы избежать вопроса "зачем это нужно?" предлагаю Вам задачку. Попробуйте назвать номер порта на свиче к которому подключен компьютер дяди Васи зная лишь его IP. Или еще интереснее - зная лишь производителя его сетевого оборудования. Или вопрос от начальника "Скажи мне, кто подключен к этому свичу, а я пока узнаю, кого нужно искать".
      Раньше это делалось следующим образом. Подключаемся к маршрутизатору и спрашиваем, какой MAC принадлежит интересующему нас IP, пусть это будет 192.168.0.3
      cisco-router#sh arp | include Vlan1 Internet 192.168.0.1 210 0800.0694.d027 ARPA Vlan1 Internet 192.168.0.2 210 0800.bdf0.0010 ARPA Vlan1 Internet 192.168.0.3 210 000e.be08.001c ARPA Vlan1 Internet 192.168.0.4 210 000e.42ee.20cf ARPA Vlan1 Internet 192.168.0.5 210 0800.218e.be09 ARPA Vlan1 Internet 192.168.0.6 5 20cf.0800.000e ARPA Vlan1 Internet 192.168.0.7 - 001c.0010.000e ARPA Vlan1 Internet 192.168.0.8 6 0010.1fc4.0800 ARPA Vlan1 Internet 192.168.0.9 2 d027.0694.0800 ARPA Vlan1 ... Теперь мы знаем MAC, это 000e.be08.001c. Подключаемся к свичу и просим его показать нам таблицу MAC адресов с сортировкой по конкретному MAC-у.
      cisco-switch#sh mac-address-table | include 000e.be08.001c 000e.be08.001c Dynamic 1 FastEthernet21 Теперь мы знаем, что интересующий нас (или не нас) хост использует порт FastEthernet21
      Все прошло относительно быстро и гладко. Но что делать, если порт имеет порядковый номер превышающий общее число физических портов на свиче, оборудование разных производителей и оно не поддерживает одинаковый формат MAC адресов, отсутствуют различные фильтры, как например "include" в оборудовании Cisco. При этом может быть несколько свичей с десятками хостов. Все это повлияет на время поиска и на конечный результат.
      Реализация
      Мы знаем, что и у какого оборудования спрашивать. Так и давайте спрашивать это используя SNMP протокол. Первым делом необходимо настроить Ваше сетевое оборудование, выставить необходимые разрешения и community. Описывать этот пункт нету смысла т.к у Вас своё оборудования, а у дяди Васи совсем другое.
      На сервере, где установлен Apache необходимо доставить библиотеку реализующий работу snmpwalk в PHP
      apt-get install php5-snmp service apache2 restart На самом деле большая часть работы уже сделана. Теперь необходимо скачать сам скрипт, он будет прикреплен к данному посту и отредактировать его под себя.
      Редактируем .htaccess
      RewriteEngine On Options +FollowSymlinks Options -MultiViews RewriteBase /switch/ RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) index.php?$1 [L] Убедитесь, что у Вас подключен модуль mod_rewrite и измените относительный путь указанный в RewriteBase на удобный Вам. Если закинуть каталог switch в корневую веб директории Apach, то вносить изменений в файл не нужно.
      Редактируем index.php
      $url = 'http://'.$_SERVER["HTTP_HOST"].'/switch/'; $domain = '.domain.com'; $community = 'public'; $unit = array( 'network_id' => array( 'name' => 'Желаемое для отображения имя подсети или объекта где сеть эксплуатируется', 'router' => '192.168.1.1', 'switch' => array('192.168.1.2'), ), 'object_name' => array( 'name' => 'Желаемое для отображения имя подсети или объекта где сеть эксплуатируется', 'router' => '192.168.2.1', 'switch' => array('192.168.2.2', '192.168.2.3', '192.168.2.4'), ), // UPDATE 26.11.2015 'new_object' => array( 'name' => 'new object name', 'router' => '192.168.3.1', 'switch' => array('192.168.3.2', '192.168.3.3'), // Уникальные настройки для маршрутизатора 192.168.3.2 '192.168.3.1' => array( 'community' => 'public2', ), // Уникальные настрокий для свича 192.168.3.3 '192.168.3.3' => array( 'community' => 'public3', 'ifName' => '.1.3.6.1.2.1.31.1.1.1.1', 'dot1dBasePortIfIndex' => '.1.3.6.1.2.1.17.1.4.1.2', ), ), ); Мы старались сделать конфигурацию интуитивно понятной, получилось это или нет, спорный вопрос. Поживем увидем, а пока разберем, что тут к чему.
      $url - содержит http адрес до каталога со скриптом. Измените /switch/ на используемый Вами network_id, object_name - любой понравившийся идентификатор для подсети. Используйте латиницу и\или цифры и не используйте пробелы. name - описание для подсети. Оно будет отображаться в списке на главной странице скрипта и в навигационном баре router - IP адрес маршрутизатора, через который подсеть ходит во внешний мир switch - список IP адресов свичей используемых в подсети Можно производить уникальную конфигурацию для любого сетевого устройства. Для этого в конфигурации нужного объекта необходимо указать адрес устройства и описать массив настроек для него. Можно изменять абсолютно любые существующие значения в скрипте. ВНИМАНИЕ: если Вы не понимаете, за что отвечает та или иная переменная и как устроена эта кухня, лучше обратитесь к нам, и мы Вам обязательно поможем!
      Список рекомендуемых для изменения значений (описание значений имеется в самом скрипте):
      community atPhysAddress sysDescr dot1dTpFdbAddress dot1dTpFdbPort dot1dBasePortIfIndex ifName Определение производителя по MAC адресу
      Каждому производителю выделяется определенный список MAC адресов для использования в его сетевом оборудовании. Ознакомиться с этим списком можно по адресу http://standards-oui.ieee.org/oui.txt Мы включили этот файл в состав архива, но советуем Вам периодически обновлять его.
      В скрипте используется shell_exec
      $vendor = explode('(hex)', shell_exec("cat ./oui.txt | grep ".str_replace(' ', '-', substr($mac, 0, 8)))); Это потенциально не безопасно, но мы не передаем ей данные полученные от пользовательского ввода, только MAC адреса. В любом случае shell_exec должен быть разрешен или часть кода, отвечающая за определения производителя, должна быть удалена.
      Есть очень интересная статья на сайте CISCO. Она поможет Вам разобраться в принципах работы данного скрипта. К сожалению я узнал об этой статье уже после написания большей части кода программы. Но уже имеются идеи для следующей версии!
      PS: Если все сделано правильно, то Вы сможете насладится нашим велосипедом. Проект будет дорабатываться и обрастать всяческими "свистульками". Приятного использования 😃
       
    • By Kitsum
      Доброе время суток.
      Более года назад мне потребовалось выдергивать карты сетей из web интерфейса zabbix, но эта потребность была не долгой, и вскоре все было забыто. И вот недавно, разбирая закрома, наткнулся на реализацию этой идеи. 
      Зачем это нужно?
      Большинству людей, пользующихся системами мониторинга, достаточно того интерфейса, который предоставляет разработчик. А разработчик обычно останавливается на реализации web интерфейса. Можно забыть про всякие виджеты, push уведомления или иные способы оповещения "из коробки". Это сильно угнетает т.к у меня нет возможности постоянно смотреть на дашборд в ожидании каких либо событий. Да и вообще я могу быть погруженным в другие людские заботы или, что еще боле серьезное, отсутствовать на рабочем месте.
      Чтобы как-то исправить две последние ситуации были реализованы следующие дополнения
      Push уведомления: Android, iOS, Windows - очень удобно получать информацию о проблемных узлах прямо на телефон. Порой решения проблемы приходят в голову быстрее, чем кто-либо еще о ней узнает.
      Мониторинг триггеров в GUI под Windows - пока что сырая, но вполне работоспособная система позволяющая получать всплывающие уведомления, сопровождающиеся звуковым оповещениям и интерфейсом для быстрого доступа к узлу.
      Теперь захотелось пойти немного дальше и позволить удаленным приложениям забирать актуальные карты сетей по их идентификатору в zabbix интерфейсе. А также в планах вывести общую карту сети на большой монитор для всех коллег. И делать это, хотелось бы, не светя учетными данными пользователей zabbix и не нагружая сам сервер. В общем, эта мелочь будет описана в данной теме.
      И так, что нам понадобится.
      Т.к наличие zabbix подразумевает наличие web сервера и PHP, то вы даже не догадаетесь, на чем мы все будем писать? или догадаетесь? ... эээ блин!
      Первым делом нам необходимо дополнить арсенал PHP модулем CURL. В данный момент у меня все это хозяйство крутиться на Ubuntu 16.04 с PHP-7.1 и добавить модуль можно следующим способом.
      sudo apt-get update sudo apt-get install php7.1-curl sudo /etc/init.d/apache2 reload Создаем на нашем web сервере, в произвольном месте, файл graphics.php со следующим содержимым
      <?PHP if(false) { ini_set('error_reporting', E_ALL); ini_set('display_errors', 1); ini_set('display_startup_errors', 1); } $settings = array( 'request' => '', 'name' => 'guestlogin', 'password' => 'guestpassword', 'autologin' => '', 'enter' => 'Sign in' ); function putImage($data = false) { header('Content-Type: image/png'); header('Content-Transfer-Encoding: binary'); if($data) echo $data; } if(isset($_GET['sysmapid']) and preg_match('/^[0-9]{1,2}$/', $_GET['sysmapid'])) { $imageUrl = 'http://localhost/zabbix/'; $imageTmp = base64_encode(microtime(null)); $imagePng = '/tmp/zabbixTrigger_map'.$_GET['sysmapid']; $cookie = '/tmp/zabbixTrigger_cookie'; if(file_exists($imagePng)) { if(time() - filemtime($imagePng) < 30) { putImage(); exit(file_get_contents($imagePng)); } unlink($imagePng); } $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $settings); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie); curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); $post = (file_exists($cookie)) ? 'map.php?sysmapid='.$_GET['sysmapid'] : 'index.php'; curl_setopt($ch, CURLOPT_URL, $imageUrl.$post); $data = curl_exec($ch); if(curl_getinfo($ch, CURLINFO_CONTENT_TYPE) != 'image/png') { curl_setopt($ch, CURLOPT_URL, $imageUrl.'map.php?sysmapid='.$_GET['sysmapid']); $data = curl_exec($ch); file_put_contents($imageTmp, $data, LOCK_EX); $finfo = finfo_open(FILEINFO_MIME_TYPE); if(finfo_file($finfo, $imageTmp) == 'image/png') { file_put_contents($imagePng, $data, LOCK_EX); putImage($data); } else echo 'error'; unlink($imageTmp); } else { file_put_contents($imagePng, $data, LOCK_EX); putImage($data); } curl_close($ch); } ?> Что здесь происходит.
      Скрипт пытается авторизоваться на zabbix сервере. Советую, для этих целей, использовать гостевую учетную запись. И минуя прочий html шлак, забирает картинку по её идентификатору. Как узнать идентификатор нужной нам карты сети? Для этого откройте карту в дашборд zabbix, и в строке запроса, вы увидите её порядковый номер.

      Нас интересует переменная sysmapid, именно её мы будем использовать для передачи идентификатора для graphics.php

      Теперь о том, как передать данные для авторизации гостевой учетной записи.
      $settings = array( 'request' => '', 'name' => 'guestlogin', 'password' => 'guestpassword', 'autologin' => '', 'enter' => 'Sign in' ); Данный массив представляет собой список всех форм участвующих в авторизации пользователя. И пусть Вас не пугает их количество, на самом деле их ровно столько, сколько в самом интерфейсе zabbix. Вам необходимо исправить только поля с именем пользователя и пароля.
      Жизненно необходимо указать http путь до zabbix сервера, это делается в переменной
      $imageUrl = 'http://localhost/zabbix/'; Также имеются переменные, описывающие, где будут храниться временные файлы изображений и cookie на нашем сервере
      $imagePng = '/tmp/zabbixTrigger_map'.$_GET['sysmapid']; $cookie = '/tmp/zabbixTrigger_cookie'; Скрипт кэширует изображения во временном каталоге и отдает его, если не прошло более 30 секунд с момента его создания. Также во временном каталоге будет храниться файл cookie необходимый для работы curl. 
      ВАЖНО: не переносите эти файлы в рабочий каталог web сервера!
      Таким образом, мы забираем у zabbix карты сетей без передачи какой либо конфиденциальной информации. Можно дополнить скрипт и отдавать только определенные карты и только конкретным хостам. В общем, есть почва для размышлений.
       
    • By Kitsum
      Всем привет!
      И так, имеется компьютер, которому предоставлен доступ в интернет через proxy сервер. Для обычной работы в браузере этого вполне достаточно, но возникла ситуация когда потребовалось выпустить в интернет (по протоколу HTTP/HTTPS) приложение не имеющее сетевых настроек прокси. Первой попыткой было завернуть трафик через Proxifier, но из-за специфики работы программы через Java VM она потерпела фиаско. Конечно, можно и нужно было попробовать разобраться с JVM, но хотелось здесь и сейчас!
      Принято решение завернуть http/s трафик windows в proxy сервер.

      В состав Windows (начиная с 2000) включена утилита netsh предназначенная для конфигурации сетевых параметров. Утилита имеет функционал от настройки ip адресов до конфигурации IPSec, но нас интересует настройка службы WinHTTP.

       
      Для конфигурации WinHTTP через командную строку (cmd), последнюю необходимо запускать с правами администратора.

      Добавление общей записи о прокси-сервере
      netsh winhttp set proxy proxy-server="10.10.10.1:3128" Добавление записи о прокси-сервере с указанием конкретных протоколов
      netsh winhttp set proxy proxy-server="http=10.10.10.1:3128;https=10.10.10.1:3129" Добавление записи о прокси-сервере с указанием конкретных протоколов и списка исключений
      netsh winhttp set proxy proxy-server="http=10.10.10.1:3128;https=10.10.10.1:3129" bypass-list="*.example.com" Импорт настроек из IE
      netsh winhttp import proxy source=ie Просмотр текущей конфигурации
      netsh winhttp show Сброс настроек
      netsh winhttp reset proxy  
    • By Kitsum
      Необычные проблемы требуют необычных решений.

      Начнем с прелюдии
      На определенном удалении друг от друга имеются две локальные домашние сети. Во главе одной стоит маршрутизатор на базе стационарного компьютера с RouterOS на борту, а сердцем второй является Cisco 800-ой серии (далее просто Кошка). В каждой из сетей имеются ресурсы представляющие интерес друг для друга. И вот настал прекрасный момент,  была приобретена статика, и начался процесс поднятия GRE тоннеля. Все завелось с первого раза, пакетики побежали между сетями. Данное событие было отмечено, как подобает Русскому представителю IT сообщества и все разошлись заниматься своими делами.
      Но счастье было не долгим. Через пару дней, из-за не преодолимых обстоятельств, произошло отключение питания на стороне "Кошки" и MikroTik начал скучать и ждать своего боевого товарища. После проведения аварийно-восстановительных работ "Кошка" радостно заурчала, но пакетики не побежали. 
      Вскрытие показало, что провайдер не поддерживает адекватную работу с DHCP семейства кошачьих и в панике выдавал первый свободный IP из пула, со всеми вытекающими последствиями. Несколько недель велись переговоры с провайдером, и раз эта статья была написана, значит, провайдер пока не добился положительного результата.
      Решено разбираться самостоятельно и попробовать поднимать тоннель, основываясь только на одном статическом адресе. Ведь в цирке медведи ездят на одноколесных велосипедах? А чем мы хуже медведей?!
      Реализация
      Кошка будет гулять по всему пулу адресов провайдера, следовательно, приспосабливаться к этим загулам придется MiktoTik-у. Средствами RouterOS решить эту проблему сходу не получилось и решено вводить в бой тяжелую артиллерию, это сверх мощный и производительный сервер Raspberry Pi  А Вы, что подумали?) Эта игрушка с 512mb RAM, 800мГц CPU, Lunux-ом на борту и питанием от USB разъема самого MikroTik-а очень сильно расширяет функционал маршрутизатора, не повышая расходы на электроэнергию и общую стоимость проекта. 
      Если быть серьезным, то MikroTik API + Raspberry Pi (далее просто Малина) позволяют реализовать практически любую Вашу фантазию.
      Фото моего роутера
      Поведение будет следующим:
      На MikroTik-е настраивается проброс 80 порта до Малины. Cisco каждые N минут будет обращаться по протоколу http на Raspberry Pi и методом GET передавать секретный ключ. На борту Малинки крутится Apache + PHP. Последний проверяет корректность ключа, реализуя идентификацию кошки по схеме "Свой\Чужой". Если идентификация пройдена успешно, то по средствам API маршрутизатора происходит перенастройка GRE тоннеля. Хочу отметить, что таким способом можно производить конфигурацию всего маршрутизатора, а не только GRE.
      Проброс портов на MikroTik-е
      /ip firewall nat add action=netmap chain=dstnat disabled=no dst-port=80 in-interface=ether1 protocol=tcp to-addresses=192.168.1.100 to-ports=80 in-interface - имя интерфейса смотрящего в интернет to-addresses - внутренний адрес малинки Не забудьте активировать сервис API у маршрутизатора.
      /ip service enable 5 Настройка Cisco
      cisco-test#configure terminal cisco-test(config)#kron policy-list gre cisco-test(config-kron-policy)#cli more http://64.64.64.64/?key=a7656fafe94dae72b1e1487670148412 cisco-test(config-kron-policy)#exit cisco-test(config)#kron occurrence gre in 015 recurring cisco-test(config-kron-occurrence)#policy-list gre cisco-test(config-kron-occurrence)#^Z cisco-test#write В данном случае настраивается задание для планировщика KRON на выполнение команды more каждые 15 минут. Сама команда просто выводит на экран содержимое из различных источников. Естественно необходимо изменить IP адрес на актуальный для Вас.
      Значение key необходимо изменить на Ваш ключ, указанный в PHP скрипте ниже и закодированный в md5!
      Еще один важный момент. В GET запросе, символ вопроса "?" обозначает, что начинается передача параметров. В Cisco это спец символ показывающий справку по командам и чтобы его ввести, необходимо перед его написанием нажать Ctrl + V
      PHP Script для Raspberry Pi
      Нам понадобится PHP class для работы с RouterOS API https://github.com/BenMenking/routeros-api
      <?PHP /** * @copyright: iT4iT.CLUB (c) 2015 * @author: https://it4it.club */ # Данные для подключения к API RouterOS $host = '192.168.0.1'; $login = 'login'; $pass = 'password'; # Уникальный ключ для проверки "Свой\Чужой". Удаленный маршрутизатор обязан передавать его в md5 $key = 'secret key'; # Интерфейс, который необходимо переконфигурировать $interfaceName = 'gre-tunnel1'; if(isset($_GET['key']) and $_GET['key'] == md5($key)) { require('./routeros_api.class.php'); $API = new RouterosAPI(); if($API->connect($host, $login, $pass)) { $API->write('/interface/gre/print'); foreach($API->read() as $id => $param) { if($param['name'] == $interfaceName and $param["remote-address"] != $_SERVER['REMOTE_ADDR']) { $API->comm("/interface/gre/set", array( "numbers" => $id, "remote-address" => $_SERVER['REMOTE_ADDR'], )); break; } } $API->disconnect(); } } ?> В данном скрипте при совпадении ключей происходит поиск интерфейса gre-tunnel1 в ветке /interface/gre и в случае его обнаружения следует изменение параметра remote-address на IP клиента передавшего верный ключ в формате md5.
      Более подробно почитать об API можно на официальном сайте http://wiki.mikrotik.com/wiki/Manual:API
      PS: Данный вариант управления маршрутизатором довольно забавен и очень гибок, но будьте очень осторожны, "друзья" Эдварда не дремлют! Советую также использовать https, фильтр по IP (провайдера) в коде скрипта и в фаерволе MikroTik-а.
      routeros_cisco_rpi.zip
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...