Здравствуйте, уважаемое хабро-сообщество! Решил выплеснуться в онлайн.
собственный решения, которые облегчают деятельность сетевых специалистов и других ИТ-собратьев.
В этой статье мы поговорим о мониторинге событий стандартного (для многих производителей) механизма защиты от несанкционированного подключения устройств к сети - механизма ПортБезопасность .
Решение изначально создавалось для коммутаторов от компании Циско , но при желании его легко можно добавить к любому коммутатору и к любым событиям на основе SNMP-ловушек.
Если интересно, добро пожаловать под. Небольшой экскурс в то, о чем мы говорим.
Технологии ПортБезопасность работает на основе MAC-адресов.
Порт доступа свитча проверяет указанное количество (по умолчанию один) маков на предмет входящего трафика и при появлении нового мак-адреса активирует защиту сети, блокируя порт. Коммутатор также может отправлять SNMP -тапаемся по хосту, указанному в настройках интерфейса.
Существует три типа режима блокировки:
- неисправность - выключить порт + snmp-ловушка
- ограничивать — ограничение входящего трафика с неизвестного Mac+ snmp-ловушка
- защищенный — ограничение входящего трафика с неизвестного Mac молча, без ловушка -А.
Система мониторинга, как следует из названия – Заббикс .
Поддержка трапа Заббикс Вроде есть, но я так и не научился им пользоваться.
В итоге я принял свое решение, которое меня полностью устраивает. Собственно, всё решение представляет собой довольно простой обработчик скриптов ( обработчик ловушек ) для пары конкретных SNMP - лестницы Обработчик написан, естественно, на питон и вызывается стандартным демоном snmptrapd .
Код обработчика размещен по адресу github .
Краткий теоретический экскурс окончен, перейдем к конкретике.
Механизм мониторинга построен и работает по следующей цепочке:
[1. Коммутатор Cisco] → [2. демон snmptrapd] → [3. сценарий] → [4. Забфикс]
Остальная часть истории будет следовать в том же порядке.
1. Циско
Настраиваем на коммутаторах хозяин который будет получать ловушки и запускать скриптЗдесь настраиваем его отдельно для каждого порта ПортБезопасность .snmp-server enable traps port-security snmp-server enable traps errdisable snmp-server host 10.1.0.1 version 2c public
В примере ниже ПортБезопасность настроен в режиме гибридного порта компьютер+телефон .
Поэтому максимальное количество указанных маков – два.
Режим блокировки ограниченный switchport port-security maximum 2
switchport port-security
switchport port-security violation restrict
switchport port-security mac-address sticky
switchport port-security mac-address sticky 1111.11co.ffee vlan access
switchport port-security mac-address sticky 0000.0000.beef vlan voice
Также будет полезно включить механизм на выключателе автоматическое восстановление , чтобы при исчезновении причины блокировки блокировка лечилась сама без стороннего вмешательства.
Если причина не исчезла, после каждой попытки автовосстановления будет отправляться новая ловушка.
errdisable recovery cause psecure-violation
errdisable recovery interval 300
Вот и все, что касается переключателя.
Подробнее о том, как настроить PortSecutity, вы можете прочитать по ссылкам
- Руководство по настройке программного обеспечения Cisco IOS: Настройка безопасности портов
- Безопасность портов на xgu.ru
2. снмптрапд
snmptrapd стандартная услуга по обработке SNMP - лестницы.
В Ubuntu устанавливается командой > sudo apt install snmptrapd
конфигурация настраивается в файле /etc/snmp/snmptrapd.conf Каждый тип ловушки уникален как для разных вендоров, так и для разных типов блокировки (restricted|shutdown).
Мы остановимся на двух конкретных:
- CISCO-ERR-DISABLE-MIB::cErrDisableInterfaceEvent (1.3.6.1.4.1.9.9.548.0.1.1) — ловушка отправляется в режиме завершения работы
- ciscoPortSecurityMIB::cpsSecureMacAddrViolation (1.3.6.1.4.1.9.9.315.0.0.1) — ловушка отправляется в ограниченном режиме
authCommunity log,execute,net public
traphandle .
1.3.6.1.4.1.9.9.315.0.0.1 /etc/zabbix/externalscripts/traphandlers/cisco-psec-traphandler.py
traphandle .
1.3.6.1.4.1.9.9.548.0.1.1 /etc/zabbix/externalscripts/traphandlers/cisco-psec-traphandler.py
Далее для краткости буду называть эти лестницы по номерам.
315 И 548 .
3. сценарий
Здесь я последовательно опишу логику написания скрипта, руководствуясь которым можно будет по аналогии написать другие обработчики (трафандлеры) для других типов ловушек и/или устройств.Те, кому не очень интересно, что происходит под капотом, могут сразу перейти к следующей главе.
Правда, возможно, имеет смысл сначала немного пройтись по этому разделу, чтобы понять, зачем нужен файл конфигурации скрипта.
config.ini .
Кстати, начнём, наверное, с Configuration.ini. Для простоты сразу представлю его содержание [snmp]
community = public
[api]
zabbix_url = https://zabbix.acme.loc
zabbix_user = api_ro
zabbix_passwd = neskazhu
[zabbix]
server = 10.1.1.1
port = 10051
zabbix_sender = /usr/bin/zabbix_sender
#the predefined keyname of an item that has to be created for a given host in Zabbix
trapkeyname_disable = ErrDisable
trapkeyname_restrict = ErrRestrict
[logging]
logfile = /var/log/cisco-errdisable-traphandler.log
loglevel = INFO
Мне кажется, конфиг достаточно прозрачен для понимания.
Здесь мы устанавливаем snmp-community, уровень логирования и параметры доступа к серверу.
Заббикс через Забфикс_API И zabbix_sender .
Единственный, пожалуй, непонятный момент – это параметры Trapskeyname_disable И Trapskeyname_restrict .
Значит эти параметры соответствуют лестницам 548 И 315 и определите ключевые имена для Предметы (элементы данных) в Заббикс .
Вперед, продолжать.
Как уже говорилось выше, наш обработчик принимает на вход два типа ловушек: 315 И 548 .
В коде они отличаются вот этим элементарным условием: if "548.0.1.1" in trapstr:
mode = "disable"
trapkeyname = "trapkeyname_disable"
elif "315.0.0.1" in trapstr:
mode = "restrict"
trapkeyname = "trapkeyname_restrict"
else:
logging.error("Unknown trap. Discarding .
")
exit(1)
Далее скрипт переходит к Заббикс с использованием Забфикс_API чтобы по названию или адресу свитча узнать, ведем ли мы в принципе мониторинг трапов с этого свитча.
Здесь используется модуль ЗабфиксAPI и еще пара способов хост.get И элемент.получить .
Ничего сложного.
Перейдем к разбору ловушек.
Интересно, что структура наших двух лестниц радикально отличается.
Смотри сюда
Пример лестницы 548: switch-20
UDP: [0.0.0.0]->[192.168.99.20]:-2039
DISMAN-EVENT-MIB::sysUpTimeInstance 338:5:51:38.08
SNMPv2-MIB::snmpTrapOID.0 CISCO-ERR-DISABLE-MIB::cErrDisableInterfaceEvent
cErrDisableIfStatusCause.10640.0 9
А это типичная лестница 315: switch-27
UDP: [0.0.0.0]->[192.168.99.27]:-13209
DISMAN-EVENT-MIB::sysUpTimeInstance 342:22:17:16.63
SNMPv2-MIB::snmpTrapOID.0 CISCO-PORT-SECURITY-MIB::cpsSecureMacAddrViolation
IF-MIB::ifIndex.10028 10028
IF-MIB::ifName.10028 FastEthernet0/28
CISCO-PORT-SECURITY-MIB::cpsIfSecureLastMacAddress.10028 0:22:55:88:ee:dd
Кстати, вышеприведенные лестницы я изобразил в человекочитаемом формате.
Фактически ловушки поступают на вход скрипта в формате АСН.
1 , который выглядит совершенно иначе.
И именно с этим сырым форматом мы и будем работать.
Вот как выглядят те же лестницы в необработанном виде: Лестница 548: iso.3.6.1.2.1.1.3.0 21:19:06.72
iso.3.6.1.6.3.1.1.4.1.0 iso.3.6.1.4.1.9.9.548.0.1.1
iso.3.6.1.4.1.9.9.548.1.3.1.1.2.10640.0 9
Лестница 315: iso.3.6.1.2.1.1.3.0 342:22:17:16.63
iso.3.6.1.6.3.1.1.4.1.0 iso.3.6.1.4.1.9.9.315.0.0.1
iso.3.6.1.2.1.2.2.1.1.10028 10028
iso.3.6.1.2.1.31.1.1.1.1.10028 "FastEthernet0/28"
iso.3.6.1.4.1.9.9.315.1.2.1.1.10.10028 "00 22 55 88 EE DD "
Формат АСН.
1 , хотя он и относится к структурированным, работать с ним далеко не так удобно, как с JSON или xml .
Просто так с помощью ключа вытащить нужную информацию не получится.
Вам необходимо изучить каждую лестницу отдельно, а затем посчитать на пальцах, в каком слове и букве скрыт искомый смысл.
Не очень современно конечно, ну да ладно SNMP это долгое наследие.
Может быть гНМИ спасет нас всех.
Тогда мы сделаем это красиво.
Вернемся к нашим овцам.
Из приведенных лестниц видно, что в случае лестницы 315 мы легко можем узнать номер порта и даже MAC-адрес, вызвавший триггер безопасность порта .
И мы, конечно, это сделаем.
Но с 548 - все сложнее.
Здесь нам доступно только имя свитча (switch-20) (кстати, оно не сохранится, если пробросить лестницу на другой хост по инструкции вперед В snmptrapd ), и вместо имени заблокированного интерфейса мы имеем только его индекс — SNMP еслииндекс .
Индекс содержится в последней строке нашей лестницы iso.3.6.1.4.1.9.9.548.1.3.1.1.2.10640.0 9 и равен числу 10640 Чтобы из еслииндекс чтобы получить имя порта свитча, нужно обратиться к самому свитчу с помощью SNMP .
За это отвечает отдельная функция в скрипте.
find_ifDesc_from_ifIndex() .
И, конечно же, коммутатор должен быть настроен на прием SNMP с нашего хоста и с тем snmp-сообществом, которое прописано там же config.ini .
Окончательный код анализа наших ловушек выглядит так: if mode is "disable":
trapvalue = traplist[-2]
ifIndex = trapvalue.split(".
")[-2] ifName = find_ifDesc_from_ifIndex(ip, ifIndex, snmp_config['community']) elif mode is "restrict": ifName = traplist[7].
strip('"') mac = ':'.
join(traplist[-7:-1]).
strip('"')
В результате мы имеем один из двух наборов данных
- (имя переключателя, имя интерфейса, тип ловушки)
- (имя коммутатора, имя интерфейса, MAC-адрес, тип релейной схемы)
Почему-то архитекторы Заббикс не разрешать внедрение данных в систему с помощью API .
Единственный (на момент написания скрипта, но я его написал уже давно) способ поместить туда произвольные данные - использовать zabbix_sender .
zabbix_sender для необходимого имя хоста передает ключ:значение пара где ценить — это те же данные, которые мы подготовили, и в качестве ключа необходимо указать заранее заданное имя ключа для элементов данных в Заббикс .
И именно это самое имя нужно написать в config.ini для параметров ловушка_имя_х .
Как ценить передается имя интерфейса или строка, состоящая из имени интерфейса и MAC-адреса.
Установка скрипта
Скрипт может быть где угодно.Он запускается демоном snmptrapd и чтобы Заббикс никак не привязан.
Но лично я держу это в себе.
/etc/zabbix/external-скрипты просто потому, что «почему бы и нет».
Для работы скрипта необходим ряд модулей, которые указаны в файле require.txt. Чтобы установить необходимые модули, достаточно выполнить команду: sudo -H pip install -r requirements.txt
Также необходимо иметь утилиту zabbix_sender .
В моем любимом Убунту он поставляется в отдельной упаковке, которая называется zabbix-отправитель , но с дефисом вместо подчеркивания.
Ну, это так.
sudo apt установить zabbix-sender
4. Забфикс
В Заббикс для каждого коммутатора, от которого мы хотим получать ловушки, нам необходимо создать элементы данных (Items) и по одному триггеру для каждого ловушки.Как уже говорилось выше, имена ключей для этих элементов данных должны быть записаны в файле config.ini .
Но вам не о чем беспокоиться.
Готовый шаблон с этими компонентами уже есть в репозитории вместе с кодом.
Также в Zabbix нужно создать специального пользователя, от имени которого будет взаимодействовать скрипт. Заббикс через API .
Подойдет простой пользователь с правами только чтения для группы с переключателями и без доступа к Frontend. Результат будет выглядеть примерно так:
те.
хорошо видно, что на переключателе с именем катализатор100 порт заблокирован Фа0/2 левый mac-адрес 00:22:55:Д4:3Ф:51 Здесь, кстати, пригодится один грязный хак.
По неизвестной причине в интерфейсе Заббикс , в виджете «Проблемы» для одноименного поля установлено ограничение в 20 символов на длину строки значения триггера.
Но один только мак-адрес занимает 17 символов, а с именем интерфейса минимум 23. В общем, для полной красоты это ограничение нужно изменить.
Он находится в файле: $ZABBIX_FRONTEND_HOME/include/items.inc.php
Найдите этот фрагмент: switch ($item['value_type']) {
case ITEM_VALUE_TYPE_STR:
$mapping = getMappedValue($value, $item['valuemapid']);
// break; is not missing here
case ITEM_VALUE_TYPE_TEXT:
case ITEM_VALUE_TYPE_LOG:
if ($trim && mb_strlen($value) > 20) {
$value = mb_substr($value, 0, 20).
'.
';
}
А затем настройте обе 20-ки.
Я установил значение 30. Теперь оно выглядит красиво.
Вот, пожалуй, и все.
Готов ответить на вопросы в комментариях.
п.
с.
Я хочу поделиться одной особенностью Zabbix, которая называется теги .
Наверное многие в курсе, но многим просто не интересно, поэтому скрыл: теги забфикса Посмотрите, как я настраиваю Действия:
ярлык безопасность порта написано в шаблоне для каждого триггера и теперь условия в Действия
можно записать в одну строку.
Или два.
Самое удобное, чего мне очень не хватало раньше.
п.
п.
с.
Вторая часть статьи готова.
Разблокировка заблокированных портов из интерфейса Zabbix Теги: #*nix #cisco #cisco #python #Системное администрирование #zabbix
-
Свобода Программиста
19 Oct, 24 -
Аутентификация Eap-Sim В Wlan
19 Oct, 24 -
Пивик
19 Oct, 24