Usm checker
Данный модуль является заменой устаревшему модулю usm_ping
Описание
Модуль предназначен для определения доступности узлов сети (в т.ч. доступности абонентских устройств).
Для определения доступности используются различные методы проверок, которые дают более достоверный результат в зависимости от специфики конкретных сетей или устройств.
Модуль является аналитическим и не может со 100% достоверностью определить активность узла в сети. Например, если на тестируемом узле заблокированы ICMP-запросы, то единственным способом определить доступность такого узла может быть проверка записи в ARP-таблице маршрутизатора этого узла, но и в ARP-таблице маршрутизатора данные могут быть не достоверны, так как запись в ней находится еще какое-то время, вне зависимости от фактической доступности узла, либо же не находится, если с узлом долгое время не было обмена IP-пакетами. Поэтому следует выбирать методы проверок, которые дают более точный результат для проверяемого устройства, либо же выполнять настройку устройства таким образом, чтобы оно отвечало на ICMP ECHO.
Например, выполнять проверку методом ping для определения доступности оборудования абонента не всегда целесообразно, так как у большинства абонентов ICMP-трафик на оборудовании запрещен; для этих целей лучше использовать менее точный способ - чтение ARP таблицы, что дает некоторую погрешность, но для определения доступности абонентов ею можно пренебречь.
В то же время, читать ARP-таблицу для определения доступности оборудования также не целесообразно, так как после потери доступности оборудования, его ARP-запись будет находиться в ARP-таблице маршрутизатора еще какое-то время (в зависимости от настроек маршрутизатора, это может быть достаточно длительный период); здесь лучше использовать только ICMP-ECHO.
Модуль пришел на замену устаревшего модуля usm_ping, который выполнял проверку доступности узлов только методом ping.
Требования
- Python - Для работы модуля необходим Python3 любой поддерживаемой на данный момент версии. Статус версий можно посмотреть здесь: "Status of Python versions". Рекомендуется использовать версию с состоянием "security" или "bugfix". Версии отмеченные как "end-of-life" не поддерживаются. Отмеченные как "feature" не рекомендуется использовать.
- USERSIDE 3.12.41+ (для версии 2.0.0-alpha)
- USERSIDE 3.12.69+ (для версии 2.0.0-beta)
- USERSIDE 3.13+ (для версии 2.0.0)
Установка
Установите Python и менеджер пакетов pip
sudo apt install -y python3 python3-dev python3-pip libsnmp-dev
Скачайте архив, извлеките из него каталог с файлами модуля (это следует делать также и при обновлении).
Перейдите в этот каталог и установите зависимости (по умолчанию подразумевается, что все модули находятся в каталоге /opt/userside/название_модуля
):
python3 -m venv venv ./venv/bin/pip install --upgrade pip ./venv/bin/pip install --upgrade -r requirements.txt
Затем, если это первоначальная установка, скопируйте файл settings.yml-example с именем settings.yml
sudo cp settings.yml-example settings.yml
Отредактируйте этот файл (предварительно ознакомьтесь с форматом yaml, если это необходимо):
Укажите верные значения для секции api - URL вашего USERSIDE и API-ключ.
Настройте необходимые методы обнаружения (checks), как это описано в следующем разделе Стратегии проверок доступности. В исходном примере файла настроек для примера имеется три проверки разных типов. Две последние закомментированы. Сначала ознакомьтесь с настройкой стратегий проверок доступности и настройте необходимые проверки (достаточно одной для тестового запуска), прежде чем продолжить.
Стратегии проверок доступности
Всего существует три стратегии (метода) проверки доступности узлов: ping, cmd, snmp
Каждый метод содержит обязательные поля, такие как:
- method - наименование метода
- networks - список подсетей, для которых применять данный метод.
И не обязательные поля:
- group - наименование группы, в которую включается данная проверка (об использовании групп будет сказано позже).
- host_type - тип узлов, которые должны быть выбраны из указанных подсетей (параметр networks). Может принимать три значения:
- any - любые типы узлов (по умолчанию);
- customer - только узлы, являющиеся абонентами;
- equipment - только узлы, являющиеся оборудованием. Этот фильтр может помочь разделить проверку по типам хостов в том случае, если вы смешиваете в одной подсети и оборудование и абонентов. Данный параметр появился в версии 3.12.69.
Эти поля относятся абсолютно ко всем проверкам.
В конфигурации можно настраивать любое количество проверок, если в этом есть необходимость. Методы в разных проверках могут повторяться.
Методы проверок
ping
Данный метод предназначен для выявления активных узлов путем асинхронной icmp-flud проверки ответов на запрос ICMP-ECHO к этим узлам. Если узел ответил - он считается активным. В противном случае - не активным. Метод работает только в ОС Linux.
Данный метод основан на низкоуровневом взаимодействии с сетевыми асинхронными сокетами linux и является очень мощным и быстрым способом обнаружения активных узлов сети. Все IP-адреса, которые необходимо опросить, делятся на итерации (количество адресов в итерации определяется параметром in_iteration) и затем запускается каждая итерация асинхронно (в сеть направляется лавинный ICMP-ECHO-REQUEST трафик для всех узлов в итерации). Спустя время, обозначенное в timeout, запускается следующая итерация, а узлы, которые не успели прислать ответы на запросы из предыдущей итерации, считаются не доступными (если значение retry установлено в 0, иначе предыдущая итерация повторяется такое количество раз, сколько указано в retry, пока все узлы в ней не ответят.
Из-за высокой скорости опроса, данный метод создает большую нагрузку на сеть, потребляя все свободные ресурсы. Это может приводить к тому, что сетевая подсистема сервера, особенно если это виртуальная машина, не будет справляться с нагрузкой (гипервизоры специально фильтруют флуд такого типа). Также проблема может возникнуть на промежуточных или целевых узлах сети. Некоторые коммутаторы/маршрутизаторы также могут фильтровать флуд. Всё это может привести к потерям (дропам) ICMP-ECHO-REQUEST на этапе доставки между модулем и целевым узлом или всё тоже самое, но для ответов ICMP-ECHO-RESPONSE. Если это происходит (явно активные узлы не отвечают и помечаются как не активные), то следует использовать итерации поменьше (уменьшить in_iteration) и увеличить таймаут (зазор между итерациями), тем самым создавая меньшую нагрузку. Опытным путём подберите значение, которое гарантировано пропускается вашим оборудованием без потерь.
Данный метод может включать дополнительные необязательные параметры, такие как:
- in_iteration - значение которого - количество асинхронных ICMP-ECHO запросов в одной итерации. По умолчанию используется значение 10, но если ваша сетевая инфраструктура препятствует прохождению такого большого ICMP-трафика, уменьшайте значение до такого, при котором ICMP-трафик не будет отфильтрован оборудованием сети. Вплоть до единицы, если сетевая инфраструктура не способна работать асинхронно. Также стоит увеличивать это значение до любого возможного (до 65535), если ваша сетевая инфраструктура просто монстр, способный пережевать арматуру.
- timeout - таймаут ожидания ответов в секундах (время на одну итерацию). Значение по умолчанию - 1 секунда. Не рекомендуется указывать время ожидания менее секунды. Если нужно увеличить время между итерациями - увеличьте это значение. Если же ваша сетевая инфраструктура не работает асинхронно и in_iteration = 0 или около того, то можно использовать значения менее секунды, чтобы ускорить опрос.
- retry - количество попыток выполнения запросов. По умолчанию 0 - дополнительные попытки не предпринимаются. Если же у вас есть сегменты сети с частыми потерями, можно увеличить это значение до 1 или 2, но не больше, т.к. перезапрос будет выполняться для всех узлов в предедлах одной итерации (асинхронной пачки).
cmd
Данный метод предназначен для выявления активных узлов путем выполнения произвольной команды. Это может быть удобно для чтения ARP-таблицы при помощи команды ip neigh
или использования fping, если встроенный асинхронный пингер по какой-то причине не подходит, или любых других команд, которые на выходе формируют список IP-адресов активных узлов по одному в строке.
Ваша команда должна выводить на стандартный вывод список IP-адресов активных узлов по одному в строке. Перед тем, как использовать ее в конфиге, не забудьте убедиться, что команда срабатывает и выводит список IP-адресов по одному в каждой строке.
ARP. Примером может послужить команда ip neigh show | awk '{print $1}'
Если вместо iproute2 на Вашем сервере используется устаревший net-tools, то вместо ip neigh следует использовать инструмент arp.
Например, если в FreeBSD команда arp -an
выводит список ARP-записей, IP-адреса в которых помещены внутри круглых скобок, то можно воспользоваться командой:
arp -an | grep eth0 | awk -F '[()]' '{print $2}'
, чтобы извлечь их в простой список IP-адресов.
SSH. Вы также можете выполнить команду на удаленном узле через ssh, например: ssh gw.network.net -i /path/to/id_rsa 'ip neigh show dev eth0' 2>/dev/null | awk '{print $1}'
fping. Вы можете использовать вызов сторонней утилиты fping, если вам удобней и привычней использовать ее возможности для проверки доступности узлов. Для этого ваша команда должна быть примерно следующей: /usr/bin/fping -r 1 -t 20 -a -A -q %hosts%
. Более подробно о параметрах читайте в man fping. Также для работы fping необходимо обязательно установить значение параметра ignore_status_code в yes.
Команда указывается в значении параметра command. Внутри команды может использоваться переменная %hosts%
, в процессе выполнения вместо нее будут подставлены IP-адрса, которые подлежат проверке, разделенные пробелами.
Данный метод может включать дополнительный необязательный параметр:
- ignore_status_code - может принимать значения yes или no (по умолчанию). Определяет, стоит ли реагировать на код статуса завершения команды, отличный от нуля. Если Вы используете fping, то обязательно установите значение этого параметра в yes.
snmp
Данный метод предназначен для выявления активных узлов путем чтения ARP-таблицы или любой другой SNMP-таблицы, содержащей IP-адреса активных узлов, используя SNMP-запрос GET-BULK.
По умолчанию выполняется чтение из таблицы .1.3.6.1.2.1.4.22.1.3
(ipNetToMediaNetAddress).
Данный метод включает следующие обязательные параметры:
- community - наименование комьюнити для чтения
- host - адрес узла SNMP-агента
И один не обязательный параметр:
- value_from - может принимать значение value или index (по умолчанию) и указывает, откуда считывать IP-адрес, из значения строки или из индекса (суффикса) OID.
Также можно указать альтернативный OID ARP-таблицы (если на вашем устройстве он не стандартный). Для этого используется необязательный параметр oid. Вы можете использовать любую другую SNMP-таблицу, содержащую IP-адреса активных абонентов. Например, таблицу активных сессий BRAS.
IP-адрес узла может содержаться в значении каждой строки таблицы (value) либо в суффиксе OID каждой строки таблицы (index). Модуль извлекает IP-адрес узла из OID и считывает его только в том случае, если значение этого OID не пусто (удобно, если IP извлекается из индекса, а не из значения.
Первый тестовый запуск
Выполните тестовый запуск модуля с правами суперпользователя:
sudo ./venv/bin/python usm_checker.py
В консоль будут выводиться сообщения о его работе. Убедитесь, что модуль отработал корректно. По завершении модуль передает данные об активных хостах в USERSIDE и отображает количество узлов в USERSIDE, которые изменили свое состояние по результатам работы модуля. Убедитесь, что всё работает как нужно, прежде чем ставить модуль на автоматический запуск.
Автоматизированный запуск
Отредактируйте файл settings.yml, изменив в секции log значение to_console на no и значение level на 2.
Добавьте в системный cron строку, периодически запускающую модуль.
Если у вас небольшая сеть (до 500 узлов), то достаточно запускать модуль раз в несколько минут, чтобы он определял активность как оборудования так и абонентов.
*/2 * * * * root /opt/userside/usm_checker/venv/bin/python /opt/userside/usm_checker/usm_checker.py > /dev/null 2>&1
В этом случае будут запускаться все проверки из конфигурационного файла.
Но, если количество узлов большое, либо модуль работает достаточно долго (больше 30 секунд), следует использовать разделенный запуск по группам. Для этого, при помощи параметра group в файле настроек settings.yml, разнесите проверки по группам. Например, выделите группу для оборудования, назвав ее equipment и группу для абонентов, назвав ее customers.
Обратите внимание! Для версий модуля до 2.1, допускается одновременный запуск только одной группы, которая имеет метод ping. Начиная с версии 2.1 алгоритм изменен и параллельный запуск работает нормально. То есть, если у вас всего две группы (equipment = ping и customers = cmd) то вы можете запускать их одновременно через cron. Но если бы у вас было две разные группы с методом ping (например, equipment_radio = ping, equipment_cable = ping), то их одновременный запуск нежелателен! Для этого необходимо настроить cron таким образом, чтобы он выполнял запуск этих двух процессов со сдвигом во времени один относительно другого.
Группы
Проверки можно группировать. Группа может содержать любое количество проверок, но проверка может входить только в одну группу. Файл настроек может выглядеть следующим образом (здесь проверка методом ping отнесена к группе equipment, а проверка методом cmd, считывающая ARP-таблицу, к группе customers).
checks: - method: ping group: equipment networks: - 192.186.0.0/24 - 192.168.1.128/25 - method: cmd group: customers command: "ip neigh show | awk '{print $1}'" networks: - 192.168.2.0/24
Теперь можно запускать модуль отдельно для каждой группы проверок, указывая название необходимых групп в качестве аргументов.
Например, чтобы запускать проверки для оборудования раз в минуту, а проверки для абонентов раз в 10 минут, cron будет выглядеть следующим образом:
*/1 * * * * root /opt/userside/usm_checker/venv/bin/python /opt/userside/usm_checker/usm_checker.py equipment > /dev/null 2>&1 */10 * * * * root /opt/userside/usm_checker/venv/bin/python /opt/userside/usm_checker/usm_checker.py customers > /dev/null 2>&1
При запуске модуля без аргументов, будут выполнены все проверки из файла настроек, не зависимо от их группы. Чтобы выполнить проверки из нескольких групп, перечислите их все через пробел.
Ротация файлов журнала
Файлы журнала, создаваемые модулем, нуждаются в ротации. Для этого следует использовать стандартные инструменты ротации логов в операционной системе.
Следующая настройка будет выполнять ротацию всех файлов *.log ежесуточно и хранить 7 архивных копий (за 7 дней)
В Linux за ротацию отвечает демон logrotate. Создайте файл /etc/logrotate.d/userside, в который поместите следующий текст (не забудьте про путь, если Вы его изменили):
/var/log/userside/*.log { rotate 7 daily compress delaycompress missingok notifempty }
Запуск модуля в Docker
Инструкция по использованию модуля usm_checker в Docker-окружении доступна по ссылке: https://github.com/userside/usm_checker-docker-env
F.A.Q.
Q: Заведомо активные узлы сети при опросе методом ping идентифицируются как не активные.
A: Ваша сетевая подсистема сервера или какое-то устройство в сети на пути следования ICMP-трафика ограничивает полосу ICMP-пакетов, принимая их за флуд и отбрасывая все пакеты сверх лимита. Модуль выполняет асинхронный опрос узлов. То есть, в сеть направляется сразу большое количество ICMP-ECHO запросов одновременно, что выглядит как довольно сильный мгновенный ICMP-трафик. В методе PING модуля реализованы так называемые итерации. Это блоки, в которые помещается определенное количество IP-адресов для асинхронного опроса. Каждый такой блок (каждая итерация) имеет свой таймаут (по умолчанию 1 секунда). Это означает, что итерации запускаются с интервалом в одну секунду: сначала в сеть направляются ICMP-ECHO запросы, а затем одну секунду ожидаются ответы. Затем запускается следующая итерация. Это помогает избежать шейпинга ICMP-трафика. Если вы видите, что узлы, которые заведомо активны и доступны, вдруг идентифицируются модулем как не доступные - попробуйте уменьшить количество IP-адресов в одной итерации. За это отвечает параметр in_iteration в настройках метода ping. Вы можете уменьшать это значение вплоть до единицы. Однако стоит понимать, что чем больше узлов может быть опрошено асинхронно (одновременно) - тем быстрее происходит опрос и информация является более актуальной. Следует стремиться найти максимальное значение для in_iteration, при котором ICMP-трафик гарантированно не теряется. На виртуальных машинах с обычным простейшим сетевым адаптером, разделяемым другими виртуальными машинами, этот параметр может принимать значения даже ниже 10. Все зависит от того, насколько оборудование вашей сети справляется с ICMP-трафиком.
Q: При опросе методом PING возникает ошибка [Errno 97] Address family not supported by protocol
A: Вероятней всего у вас отключен протокол IPv6. В этом случае из-за ограничений операционной системы модуль не сможет работать корректно. Проверьте файл /etc/default/grub на наличие строки, наподобие GRUB_CMDLINE_LINUX="ipv6.disable=1" и, если она там есть, ее нужно убрать, затем пересобрать grub посредством команды sudo update-grub