Перейти к публикации
iT4iT.CLUB
Kitsum

Switch Port Mapping, строим карту расположения хостов на портах свичей

Рекомендованные сообщения

Update 03.12.2015

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

    sw6.thumb.jpg.be5279ee3b621aa294a6db47a4

     

  2. В конфигурацию добавлен параметр $domain позволяющий удалять из DNS имени хоста имя домена. Чтобы из name.domain.com сделать name, необходимо указать $domain = ".domain.com"
  3. Обновлена база производителей сетевого оборудования - oui.txt
  4. Мелки доработки интерфейса.

 

Update 26.11.2015

  1. Добавлена возможность отображать реальные имена портов (Fa1, Ethernet1/0/1, Port1 ...). Внимание: не все устройства способны передавать данную информацию, в связи с этим оставлены числовые идентификаторы, чтобы в таких случаях иметь систему идентификации.
    Скрытый текст

    sw5.thumb.jpg.dcddec4de97e754ccd995e572e

     

  2. Добавлена возможность описывать в конфигурации настройки для каждого устройства отдельно. Если не использовать эту возможность, то для оборудования будет применена общая конфигурация.
  3. Добавлена возможность описывать в конфигурации уникальные OID-ы для конкретного оборудования аналогично п.2.
  4. Мелкие доработки интерфейса и кода.

 

sw4.thumb.png.6a856c6e3d9af36c7fe8e2ee6b

В данной теме мы будем рассуждать о мониторинге сетевого оборудования и подключенных к нему хостах. Следовало бы разместить её в другом разделе, но 90% всех манипуляций и дальнейшая эксплуатация будет производиться на UNIX-подобной платформе. В моем случае используется:

  1. Linux Ubuntu 14.04
  2. Apache/2.4.7
  3. PHP 5.5.9
  4. Библиотека php5-snmp

Также само сетевое оборудование (маршрутизаторы и свичи) должно поддерживать работу по протоколу SNMP и соответствовать стандартам ISO.

Проект разработан отталкиваясь от топологии сети - звезда. Имеются множество отдельных подсетей 192.168.0.0 все они ходят во внешний мир через маршрутизаторы (в моем случае фирмы Cisco). В самих подсетях используются различные свичи, по большей части поддерживающие SNMP v1 и выше.

Ранее я уже поднимал данную тему на другом, дружественном, форуме, но потом работа над проектом бала остановлена. На данный момент вопрос опять стал актуален и решено переделать как основную программу, так и внешний вид. Старая версия была написана на скорую руку и выглядела невзрачно и с большими изъянами в коде.

Скрытый текст

sw1.png.223c16bb9db3c4b0b87ce510be74d07c

На данный момент проект преобразился и выглядит следующим образом. Ваш браузер должен поддерживать HTML5.

Скрытый текст

sw2.thumb.png.b5a20123c13502de0bab8994cc

Скрытый текст

sw3.thumb.png.88282e0fea5c631f3d66fece65

Скрытый текст

sw4.thumb.png.6a856c6e3d9af36c7fe8e2ee6b

Чтобы избежать вопроса "зачем это нужно?" предлагаю Вам задачку. Попробуйте назвать номер порта на свиче к которому подключен компьютер дяди Васи зная лишь его 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',
        ),
    ),
);

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

  1. $url - содержит http адрес до каталога со скриптом. Измените /switch/ на используемый Вами
  2. network_id, object_name - любой понравившийся идентификатор для подсети. Используйте латиницу и\или цифры и не используйте пробелы.
  3. name - описание для подсети. Оно будет отображаться в списке на главной странице скрипта и в навигационном баре
  4. router - IP адрес маршрутизатора, через который подсеть ходит во внешний мир
  5. switch - список IP адресов свичей используемых в подсети

Можно производить уникальную конфигурацию для любого сетевого устройства. Для этого в конфигурации нужного объекта необходимо указать адрес устройства и описать массив настроек для него. Можно изменять абсолютно любые существующие значения в скрипте. ВНИМАНИЕ: если Вы не понимаете, за что отвечает та или иная переменная и как устроена эта кухня, лучше обратитесь к нам, и мы Вам обязательно поможем!

Список рекомендуемых для изменения значений (описание значений имеется в самом скрипте):

  1. community
  2. atPhysAddress
  3. sysDescr
  4. dot1dTpFdbAddress
  5. dot1dTpFdbPort
  6. dot1dBasePortIfIndex
  7. 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: Если все сделано правильно, то Вы сможете насладится нашим велосипедом. Проект будет дорабатываться и обрастать всяческими "свистульками". Приятного использования 😃

 

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Пример 1

  1. Сеть является домашней
  2. Один маршрутизатор с IP адресом 192.168.0.1
  3. Один свич с IP адресом 192.168.0.2
  4. SNMP Community на обоих устройствах настроен одинаково - public
Скрытый текст

$domain = '';
$community = 'public';

$unit = array(
    'home_network' => array(
        'name'   => 'Домашняя сеть Васи Пупкина',
        'router' => '192.168.0.1',
        'switch' => array('192.168.0.2'),
    ),
);

 

Пример 2

  1. Сеть эксплуатируется в маленьком офисе
  2. Один маршрутизатор с IP адресом 192.168.0.1
  3. Два свича с IP адресами 192.168.0.2 и 192.168.0.3
  4. SNMP Community на обоих устройствах настроен одинаково - public
Скрытый текст

$domain = '';
$community = 'public';

$unit = array(
    'office' => array(
        'name'   => 'Сеть фирмы "Рога и Копыта"',
        'router' => '192.168.0.1',
        'switch' => array('192.168.0.2', '192.168.0.3'),
    ),
);

 

Пример 3

  1. Сеть эксплуатируется в небольшом магазине
  2. Один маршрутизатор с IP адресом 192.168.0.1
  3. Два свича с IP адресом 192.168.0.2 и 192.168.0.3
  4. SNMP Community на маршрутизаторе - private
  5. SNMP Community на свичах - public
Скрытый текст

$domain = '';
$community = 'public';

$unit = array(
    'small_shop' => array(
        'name'   => 'Магазин артефактов Бабы Нины',
        'router' => '192.168.0.1',
        'switch' => array('192.168.0.2', '192.168.0.3'),
    ),

    '192.168.0.1' => array(
        'community' => 'private'
    ),
);

 

Пример 4

  1. Сеть эксплуатируется в большом магазине
  2. Два маршрутизатора с IP адресами 192.168.1.1 и 192.168.2.1
  3. Один свич с IP адресом 192.168.1.2
  4. Два свича с IP адресами 192.168.2.2 и 192.168.2.3
  5. SNMP Community везде одинаков - public
  6. Поднят домен с именем youbigstore.com
Скрытый текст

$domain = '.youbigstore.com';
$community = 'public';

$unit = array(
    'router1' => array(
        'name'   => 'Помещение персонала к.101',
        'router' => '192.168.1.1',
        'switch' => array('192.168.1.2'),
    ),

    'router2' => array(
        'name'   => 'Торговый зал',
        'router' => '192.168.2.1',
        'switch' => array('192.168.2.2', '192.168.2.3'),
    ),
);

 

Пример 5

  1. Сеть эксплуатируется в офисном здании (3 этажа), каждый этаж находится в своей подсети. Сервер с установленным Switch Рort Mapping находится за пределами этих сетей, например в соседнем здании.
  2. 1 этаж. Маршрутизатор Cisco 800 с WAN IP адресом 10.10.1.1 и VLAN 192.168.10.0
  3. 1 этаж. Два свича 3Com с IP адресами 192.168.10.2 и 192.168.10.3
  4. 1 этаж. SNMP Community - public1
  5. 2 этаж. Маршрутизатор Cisco 800 c WAN IP адресом 10.10.2.1 и VLAN 192.168.20.0
  6. 2 этаж. Два свича 3Com с IP адресами 192.168.20.2 и 192.168.20.3
  7. 2 этаж. SNMP Community - public2
  8. 3 этаж. Маршрутизатор Cisco 800 c WAN IP адресом 10.10.3.1 и VLAN 192.168.30.0
  9. 3 этаж. Один свич Allied Telesis с IP адресом 192.168.30.2
  10. 3 этаж. SNMP Community - public3
  11. Поднят домен с именем domain.com
Скрытый текст

$domain = '.domain.com';
$community = '';

$unit = array(
    # Описываем оборудования 1 этажа
    'floor1' => array(
        'name'   => 'Первый этаж',
        'router' => '10.10.1.1',
        'switch' => array('192.168.10.2', '192.168.10.3'),
    ),
    # Уникальные настройки для оборудования 1 этажа
    '10.10.1.1'    => array('community' => 'public1'),
    '192.168.10.2' => array('community' => 'public1'),
    '192.168.10.3' => array('community' => 'public1'),
    
    # Описываем оборудования 2 этажа
    'floor2' => array(
        'name'   => 'Второй этаж',
        'router' => '10.10.2.1',
        'switch' => array('192.168.20.2', '192.168.20.3'),
    ),
    # Уникальные настройки для оборудования 2 этажа
    '10.10.2.1'    => array('community' => 'public2'),
    '192.168.20.2' => array('community' => 'public2'),
    '192.168.20.3' => array('community' => 'public2'),
    
    # Описываем оборудования 3 этажа
    'floor3' => array(
        'name'   => 'Третий этаж',
        'router' => '10.10.3.1',
        'switch' => array('192.168.30.2', '192.168.30.3'),
    ),
    # Уникальные настройки для оборудования 3 этажа
    '10.10.3.1'    => array('community' => 'public3'),
    '192.168.30.2' => array('community' => 'public3'),
    '192.168.30.3' => array('community' => 'public3'),
);

 

Пример 6

  1. Частная сеть с нестандартным оборудованием
  2. Один маршрутизатор Noname с IP адресом 192.168.0.1
  3. SNMP OID atPhysAddress маршрутизатора отвечающий за соответствие MAC - IP имеет вид ".1.3.6.1.2.1.3.1.1.2" (предположим, что это не стандартный OID)
  4. SNMP Community маршрутизатора - private
  5. Один свич Cisco с IP адресом 192.168.0.2
  6. SNMP Community свича - public
Скрытый текст

$domain = '';
$community = '';

$unit = array(
    'home1' => array(
        'name'   => 'Частная сеть',
        'router' => '192.168.0.1',
        'switch' => array('192.168.0.2'),
    ),
    # Настройки для маршрутизатора
    '192.168.0.1' => array(
        'community'     => 'private',
        'atPhysAddress' => '.1.3.6.1.2.1.3.1.1.2',
    ),
    # Настройки для свича
    '192.168.0.2' => array(
        'community'     => 'public',
    ),
);

 

PS: Если имеются вопросы, не стесняйтесь обращаться, постараемся помочь!

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Во, было бы не плохо включить  использования функции DHCP snooping, если таковая используется на коммутаторах. Тогда информация будет быстрее выдаваться, однозначно. В следующую версию впихни ;)

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо.
Реализация для CentOS чем нибудь отмечается? что нужно подправить?
В чем разница между network_id, object_name ,

Изменено пользователем Den MoRDa

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

  • Похожие публикации

    • Автор: 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
    • Автор: Kitsum
      Набросок небольшой программы на PHP для облегчения жизни IT отделу. Позволяет просматривать какие хосты располагаются на портах сетевого оборудования (за основу взято оборудование фирмы Cisco). Для связи используется SNMP протокол. Из информации об узле выводятся:
      MAC IP DNS имя Производитель оборудования Подробное описание можно посмотреть в следующей теме.
       
    • Автор: Kitsum
      Делюсь шаблоном для мониторинга состояния маршрутизаторов CISCO, zabbix 2.4
      Работа с устройством реализована по протоколу SNMP и тут есть ряд подводных камней, но самый основной это изменения стандарта от одной версии прошивки к другой.
      Если понадобится изменить OID значения, то поискать их можно тут http://tools.cisco.com/Support/SNMP/do/BrowseOID.do но часть старый параметров в базе отсутствует. Тут уж или через поисковик или "Селяви, что в перевод с древнегреческого - не повезло!".
      Простая конфигурация устройства:
      cisco-test#configure terminal Enter configuration commands, one per line. End with CNTL/Z. cisco-test(config)#snmp-server community public RO cisco-test(config)# Но при этом любой может подключиться к устройству и читать с него данные, если вы хотите чтобы плохие люди могли еще и отдавать команды то RO необходимо заменить на RW
      Если Вы желаете ограничить доступ к SNMP серверу устройства по IP, то необходимо использовать access-list:
      cisco-test#configure terminal Enter configuration commands, one per line. End with CNTL/Z. cisco-test(config)#ip access-list standard SNMP_ACCESS_RO cisco-test(config-std-nacl)#permit 192.168.1.2 cisco-test(config)#snmp-server community public RO SNMP_ACCESS_RO cisco-test(config)#^Z cisco-test# Сommunity можно обозвать как угодно, хоть BLABLABLA место public. IP естественно заменить на адрес Вашего сервера. RO - только чтение, RW - полный доступ
      Мы будем только читать, поэтому RO. В теории конечно можно отлавливать определенные события на устройстве и предпринимать ответные действия автоматически, только в таких случаях RW. Но об этом мы поговорим в другой раз.
      Теперь необходимо добавить макрос в zabbix Администрирование -> Общие -> Макросы
      {$SNMP_COMMUNITY} = имя community указанное в конфигурации CISCO, например "public" Сам шаблон можно забрать в конце поста.
      Немного о шаблоне.

      На данным момент собираются данные:
      Аптайм Модель маршрутизатора Загрузка центрального процессора за: 5 секунд, 1 минуту, 5 минут Статус (online\offline) Память: ОЗУ, ПЗУ Список доступных интерфейсов Статусы сетевых интерфейсов Количество byte RX\TX на каждом интерфейсе Количество error byte RX\TX на каждом интерфейсе По этим данным строятся соответствующие графики (ОЗУ, ПЗУ и т.п не выведены, можете добавить самостоятельно)
      Пока маловато триггеров, но по мере обновления шаблона, их количество увеличится:
      Маршрутизатор выключен или с ним нет связи по Ethernet Маршрутизатор был пере запущен менее 5 минут назад Нагрузка на ЦП выше 80%  PS: следите за обновлениями!
      zbx_templates_router_cisco.xml
    • Автор: Kitsum
      Доброе время суток.
      Сегодня пойдет речь о том, как переправлять данные с MQTT брокера в базу данных MySQL. Транспортировать будем как сами адреса, так и значения всех топиков, на которые оформлена подписка. Данную задачу нельзя назвать распространенной, но все же, она имеет место быть и может пригодиться в том случае, если данные востребованы в системах не способных работать с MQTT протоколом самостоятельно или брокер находится в изолированной системе, а данные востребованы, например, в GUI за её приделами.

      Для осуществления задуманного нам потребуется самостоятельный процесс, который сыграет роль транспортного узла между MQTT брокером и базой данный MySQL. А значит, его придется где-то держать. В моем случае, это сервер под управлением операционной системой Linux Ubuntu 16.04.3 и дальнейшее описание будет под неё, но для других ОС действия аналогичные.
      Сам демон будет написан на Python и для его работы нам потребуется:
      python3 python-pip python-dev libmysqlclient-dev библиотека paho-mqtt для python https://pypi.python.org/pypi/paho-mqtt библиотека mysqlclient для python https://github.com/PyMySQL/mysqlclient-python Но начнем мы, в первую очередь, с подготовки базы данных.
      На плечи MySQL ляжет не только хранение, но и частичная обработка данных. Для этих целей нам потребуется отдельная база, хранимая процедура и функция с реализацией небольшой логики, и пользователь с ограниченными правами под чьим именем мы будем обращаться к ним. В конце поста, кроме самого демона, будет опубликован .sql файл, который достаточно просто импортировать, например с помощью стандартный средств базы данных
      mysql -uroot -p Вводим пароль администратора MySQL и импортируем наш .sql файл, но прежде, дочитайте статью до конца, возможно, Вы захотите внести свои изменения.
      mysql> source /media/mqttMySqlClient.sql После этого будет получен следующий результат:
      Создана база (схема) с именем mqtt Пользователь с именем mqtt-agent и паролем p@$$w0rd имеющий возможность подключаться с внешних адресов Пользователю будут назначены ограниченные права (только EXECUTE) в этой схеме Будет добавлена процедура update_topic, на которую ляжет задача добавления и обновления данных Будет добавлена функция get_topic для упрощения поиска данных На тот случай, если Вы захотите внести изменения или создать все ручками, рассмотрим содержимое sql файла.
      Если схема mqtt не существует, она будет создана
      CREATE DATABASE IF NOT EXISTS `mqtt`; Аналогичным образом будет создан пользователь mqtt-agent. Если необходимо конкретизировать, с какого адреса будет производиться подключение под этим пользователем, то замените % на доменное имя или ip адрес хоста. Если планируется использовать демона на том же сервере где установлен MySQL, замените % на localhost. Также разрешено не более 2 активных подключений, измените это значение на необходимое Вам.
      CREATE USER IF NOT EXISTS 'mqtt-agent'@'%' IDENTIFIED BY 'p@$$w0rd' WITH MAX_USER_CONNECTIONS 2; Пользователю будут выставлены ограниченные права. Ему будет разрешено пользоваться только хранимыми процедурами и функциями. Никакие самостоятельные запросы выполнять нельзя.
      GRANT EXECUTE ON `mqtt`.* TO 'mqtt-agent'@'%'; Переходим к работе с самой схемой
      USE `mqtt`; Будет создана таблица topics со следующей структурой.
      md5 - содержит уникальный одноименный хеш полученный из полного адреса топика. Именно по этому ключу и будет производиться поиск данных. Почему именно по нему, а не по самому имени? Дело в том, что md5 хеш имеет фиксированную, заранее известную, длину, что нельзя сказать о имени топика. Именно это ограничение не позволит сделать имя топика первичным ключом и явно идентифицировать данные в таблице. time - содержит UNIX время добавления/обновления данных по конкретному топику (по умолчанию GMT+0) topic - адрес топика. В контексте, упомянутого ранее, поля md5, не несет для нас никакой смысловой нагрузки. value - данные опубликованные в топике. DROP TABLE IF EXISTS `topics`; CREATE TABLE `topics` ( `md5` varchar(32) NOT NULL, `time` bigint(20) DEFAULT NULL, `topic` text, `value` text, PRIMARY KEY (`md5`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Теперь необходимо создать хранимые процедуры и функции, но сделать это будет невозможно из-за присутствие в их синтаксисе разделителя совпадающего с концом данных в sql запросе - ";" Чтобы избежать этот неловкий момент, изменяем разделить на произвольный.
      DELIMITER $$ Создает процедуру update_topic. Она принимает в качестве входных параметров два значения, адрес топика и опубликованные данные. Оба параметра являются текстовыми. Процедура, вычисляет md5 хеш из адреса топика и уже по нему производит поиск записи в таблице. Если запись не будет найдена, она будет создана, в противном случае данные в поле value будут обновлены. Данная процедура должна ускорить работу демона и избавить его от задержек, которые были бы неминуемы при выполнении этих же запросов на стороне клиента.
      DROP PROCEDURE IF EXISTS `update_topic`$$ CREATE DEFINER=CURRENT_USER() PROCEDURE `update_topic`(topic text, value text) BEGIN declare nMD5 varchar(32) default md5(topic); declare NUM bit; declare uTime bigint(20) default UNIX_TIMESTAMP(); SELECT COUNT(t.md5) INTO NUM FROM topics t WHERE t.md5 = nMD5; if NUM <> 1 then INSERT INTO topics VALUES(nMD5, uTime, topic, value); else UPDATE topics t SET t.time = uTime, t.value = value WHERE t.md5 = nMD5; end if; END$$ Также будет добавлена функция get_topic. Она необходима для запроса данных от имени созданного ранее пользователя и ограничений, наложенных на него. Функция принимает адрес топика в текстовом виде, производит вычисление md5 хеша и основываясь на его совпадении с имеющимися записями выводит значение поля value искомого топика.
      DROP FUNCTION IF EXISTS `get_topic`$$ CREATE DEFINER=CURRENT_USER() FUNCTION `get_topic` (topic text) RETURNS text BEGIN declare hMD5 varchar(32) default md5(topic); declare topicValue text; SELECT t.value INTO topicValue FROM topics t WHERE t.md5 = hMD5; RETURN topicValue; END$$ И в завершении всего, будет восстановлено стандартное значение разделителя.
      DELIMITER ; На этом разбор sql файла можно считать законченным. Он не содержит каких-либо сложным манипуляций и должен быть понятен. Все эти операции можно выполнить руками, но я совету воспользоваться импортом, как и было описано ранее.
      Переходим к демону
      В первую очередь устанавливаем необходимые пакеты.
      sudo apt-get install python3 python-pip python-dev libmysqlclient-dev Устанавливаем недостающие библиотеки для Python
      pip install paho-mqtt mysqlclient Добавим пользователя из-под которого будет запускаться демон
      sudo useradd --shell /usr/sbin/nologin --system mqtt-agent Выставляем все необходимые права (каталог /media как пример)
      sudo chown mqtt-agent:mqtt-agent /media/mqttMySqlClient.py sudo chmod 0700 /media/mqttMySqlClient.py Добавляем демона в автозагрузку через планировщик задач и от имени созданного пользователя
      sudo crontab -u mqtt-agent -e Добавляем в конец следующую запись
      @reboot /media/mqttMySqlClient.py start Запускаем демона от имени все того же пользователя
      sudo -u mqtt-agent /media/mqttMySqlClient.py start Это основное, что требуется сделать на сервере для организации работы демона.
      Переходим к разбору настроек программы
      Т.к изначально за основу была взята концепция другого демона из ветки Zabbix, то конфигурация перекочевала оттуда и аналогично разбита на несколько секций.
      """ Настройки MQTT """ mqtt_server = "mqtt.it4it.club" mqtt_port = 1883 mqtt_login = "" mqtt_password = "" mqtt_client_id = "mqttMySqlClient" Настройки подключения к брокеру. Все должно быть интуитивно понятным. Помните, что при совпадении идентификаторов клиентов, они начнут конкурировать за подключение и по очереди терять связь. Не допускайте их совпадений.
      """ Список топиков для подписки """ subscribe = { '$SYS/#', '#', } Список топиков для подписки указывается через запятую и в кавычках.
      """ Настройки MySQL """ mysql_host = "127.0.0.1" mysql_port = 3306 mysql_user = "mqtt-agent" mysql_passwd = "p@$$w0rd" mysql_schema = "mqtt" mysql_log_file = "/var/log/mqttMySqlClient.log" Настройки подключения с MySQL серверу также не должны вызывать вопросов.
      """ Настройки общие """ pid_file = "/tmp/mqttMySqlClient.pid" Последний параметр указывает на размещение .pid файла демона.
      Команды управления классические
      start - запуск в режиме демона stop - остановка в режиме демона restart - перезапуск в режиме демона window - запуск в оконном режиме, также позволяет запускать процесс в операционных системах Windows После запуска, демон пытается установить связь с MQTT брокером и пока это не произойдет, связь с MySQL сервером устанавливаться не будет. Если во время работы, связь с брокером будет потеряна то в принудительном порядке, будет разорвано соединение с базой данных. Таким образом, по активным сессиям MySQL сервера можно судить о наличии связи у демона с брокером. Во время простоя, а в нашем случае, это отсутствие потока данных от брокера, для проверки связи с сервером базы данных будет использована процедура эмуляции ping для MySQL сервера. Она представляет из себя простую арифметическую задачу на сложение не приводящей к работе с данными в базе. Операция выполняется крайне быстро и её удачное выполнение сигнализирует клиенту о наличии связи с базой, а базе об активности клиента. В связи с этим, периодическая активность клиента при отсутствие данных от брокера, является показателем нормальной работы.
      И на последок
      Если вы хотите произвести выборку из таблицы под именем пользователя используемым по умолчанию и с его ограничениями. Необходимо воспользоваться функцией get_topic с указанием полного адреса, интересующего топика.
      select mqtt.get_topic('$SYS/broker/version'); В ответ мы получим
      +---------------------------------------+ | mqtt.get_topic('$SYS/broker/version') | +---------------------------------------+ | mosquitto version 1.4.8 | +---------------------------------------+ 1 row in set (0,00 sec) На этом пока все.
      Файлы проекта: 
      PS: Это тестовая версия демона и возможно она будет претерпевать некоторые изменения.
       
  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу.

×