Access Point Registration Table: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 221: Строка 221:
 
где для кажого клиента будет создан отдельный элемент данных, при этом используются три уникальных значения, клиент с тем же маком но подключившись в другом диапазоне (другой интерфейс) рассматривается как другой клиент даже если используется один SSID для разных частот)
 
где для кажого клиента будет создан отдельный элемент данных, при этом используются три уникальных значения, клиент с тем же маком но подключившись в другом диапазоне (другой интерфейс) рассматривается как другой клиент даже если используется один SSID для разных частот)
   
==Темплейт==
+
==Готовый Темплейт==
 
{{#spoiler:show=zabbix template|
 
{{#spoiler:show=zabbix template|
   

Версия 21:05, 20 августа 2022

Таблица уровней клиентов для точек доступа Cisco

Задача

Собирать данные о траффике и уровне сигнала с точек доступа

  • Клиенты динамические, их мак-адреса заранее не известны
  • SSID добавляются и удаляются по мере необходимости
  • Точки могут иметь как один интерфейс так и два


Для того что бы получить информацию по SNMP о клиентах подключенных к точке доступа, существует специальный MIB CISCO-DOT11-ASSOCIATION-MIB
Он доступен достаточно давно, как минимум он работает на точках 1200 и 1100 серий, ну и на более современных тоже.


Просмотр OID

Пример с использованием display-hint

# snmpwalk -v2c -c MON 192.168.77.2  .1.3.6.1.4.1.9.9.273.1.3.1   -OX
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientCurrentTxRateSet[1]["450"][STRING: da:20:60:64:36:95] = Hex-STRING: 07
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientCurrentTxRateSet[2]["450"][STRING: a4:45:19:5a:ef:48] = Hex-STRING: 01
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientUpTime[1]["450"][STRING: da:20:60:64:36:95] = Gauge32: 15898 second
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientUpTime[2]["450"][STRING: a4:45:19:5a:ef:48] = Gauge32: 425 second
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientSignalStrength[1]["450"][STRING: da:20:60:64:36:95] = INTEGER: -64 dBm
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientSignalStrength[2]["450"][STRING: a4:45:19:5a:ef:48] = INTEGER: -89 dBm
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientSigQuality[1]["450"][STRING: da:20:60:64:36:95] = Gauge32: 24 percentage
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientSigQuality[2]["450"][STRING: a4:45:19:5a:ef:48] = Gauge32: 9 percentage
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientAgingLeft[1]["450"][STRING: da:20:60:64:36:95] = Gauge32: 58 second
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientAgingLeft[2]["450"][STRING: a4:45:19:5a:ef:48] = Gauge32: 34 second
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientPacketsReceived[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 149529 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientPacketsReceived[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 346 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientBytesReceived[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 23101125 byte
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientBytesReceived[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 113287 byte
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientPacketsSent[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 617733 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientPacketsSent[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 251 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientBytesSent[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 745190393 byte
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientBytesSent[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 47693 byte
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientDuplicates[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 2389 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientDuplicates[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 12 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientMsduRetries[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 159859 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientMsduRetries[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 331 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientMsduFails[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 0 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientMsduFails[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 0 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientWepErrors[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 0 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientWepErrors[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 0 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientMicErrors[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 0 error
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientMicErrors[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 0 error
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientMicMissingFrames[1]["450"][STRING: da:20:60:64:36:95] = Counter32: 0 packet
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientMicMissingFrames[2]["450"][STRING: a4:45:19:5a:ef:48] = Counter32: 0 packet

Или без использования

# snmpwalk -v2c -c MON 192.168.77.2  .1.3.6.1.4.1.9.9.273.1.3.1   -On
.1.3.6.1.4.1.9.9.273.1.3.1.1.1.1.3.52.53.48.218.32.96.100.54.149 = Hex-STRING: 05
.1.3.6.1.4.1.9.9.273.1.3.1.1.1.2.3.52.53.48.164.69.25.90.239.72 = Hex-STRING: 01
.1.3.6.1.4.1.9.9.273.1.3.1.1.2.1.3.52.53.48.218.32.96.100.54.149 = Gauge32: 15911 second
.1.3.6.1.4.1.9.9.273.1.3.1.1.2.2.3.52.53.48.164.69.25.90.239.72 = Gauge32: 439 second
.1.3.6.1.4.1.9.9.273.1.3.1.1.3.1.3.52.53.48.218.32.96.100.54.149 = INTEGER: -63 dBm
.1.3.6.1.4.1.9.9.273.1.3.1.1.3.2.3.52.53.48.164.69.25.90.239.72 = INTEGER: -89 dBm
.1.3.6.1.4.1.9.9.273.1.3.1.1.4.1.3.52.53.48.218.32.96.100.54.149 = Gauge32: 31 percentage
.1.3.6.1.4.1.9.9.273.1.3.1.1.4.2.3.52.53.48.164.69.25.90.239.72 = Gauge32: 10 percentage
.1.3.6.1.4.1.9.9.273.1.3.1.1.5.1.3.52.53.48.218.32.96.100.54.149 = Gauge32: 58 second
.1.3.6.1.4.1.9.9.273.1.3.1.1.5.2.3.52.53.48.164.69.25.90.239.72 = Gauge32: 51 second
.1.3.6.1.4.1.9.9.273.1.3.1.1.6.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 149587 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.6.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 347 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.7.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 23109939 byte
.1.3.6.1.4.1.9.9.273.1.3.1.1.7.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 113333 byte
.1.3.6.1.4.1.9.9.273.1.3.1.1.8.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 618046 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.8.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 251 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.9.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 745583754 byte
.1.3.6.1.4.1.9.9.273.1.3.1.1.9.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 47693 byte
.1.3.6.1.4.1.9.9.273.1.3.1.1.10.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 2392 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.10.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 12 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.11.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 159964 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.11.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 331 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.12.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 0 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.12.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 0 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.13.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 0 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.13.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 0 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.14.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 0 error
.1.3.6.1.4.1.9.9.273.1.3.1.1.14.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 0 error
.1.3.6.1.4.1.9.9.273.1.3.1.1.15.1.3.52.53.48.218.32.96.100.54.149 = Counter32: 0 packet
.1.3.6.1.4.1.9.9.273.1.3.1.1.15.2.3.52.53.48.164.69.25.90.239.72 = Counter32: 0 packet

Разбор OID

Как можно видеть, сам OID состоит из нескольких частей Для определенности рассмотрим уровни сигнала:

.1.3.6.1.4.1.9.9.273.1.3.1.1.3.1.3.52.53.48.218.32.96.100.54.149 = INTEGER: -63 dBm
.1.3.6.1.4.1.9.9.273.1.3.1.1.3.2.3.52.53.48.164.69.25.90.239.72 = INTEGER: -89 dBm
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientSignalStrength[1]["450"][STRING: da:20:60:64:36:95] = INTEGER: -64 dBm
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientSignalStrength[2]["450"][STRING: a4:45:19:5a:ef:48] = INTEGER: -89 dBm

Часть .1.3.6.1.4.1.9.9.273.1.3.1.1.3 это и есть OID CISCO-DOT11-ASSOCIATION и она общая Далее в самом OID закодировано значение "кому принадлежит сигнал", т е какому клиенту


Выделенное значение и его описание:

  • 2.3.52.53.48.164.69.25.90.239.72 - номер интерфейса, он же ifIndex, dot11Radio0 (1), или dot11Radio1 (2), в примере клиент подключен к 5Ghz интерфейсу (dot11Radio1)
  • 2.3.52.53.48.164.69.25.90.239.72 - Длинна SSID в байтах, в пример 3 символа (SSID в примере "450")
  • 2.3.52.53.48.164.69.25.90.239.72 - коды ASCII символов SSID, их три - "450"
  • 2.3.52.53.48.164.69.25.90.239.72 - мак-адрес, 6 байт, записаны в деятичной форме, "a4:45:19:5a:ef:48", например 164(десятичное) = a4(hex), 69(десятичное) = 45 (hex) и так далее.

Интеграция с Zabbix

SNMP autodiscovery

Есть дока но мне она не нравится =)

В целом идея такая:

  • В поле SNMP OID указываю discovery[{#S},1.3.6.1.4.1.9.9.273.1.3.1.1.3]
  • Заббикс сам делает snmpwalk 1.3.6.1.4.1.9.9.273.1.3.1.1.3 и в результате получает список клиентов и их сигналы
snmpwalk -v2c -c MON 192.168.77.2   1.3.6.1.4.1.9.9.273.1.3.1.1.3   -OX
Bad operator (INTEGER): At line 73 in /usr/share/snmp/mibs/ietf/SNMPv2-PDU
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientSignalStrength[1]["450"][STRING: 0:8:ca:2b:1:24] = INTEGER: -65 dBm
CISCO-DOT11-ASSOCIATION-MIB::cDot11ClientSignalStrength[2]["450"][STRING: a4:45:19:5a:ef:48] = INTEGER: -67 dBm

и на выходе формирует JSON в котором есть поля "{#SNMPINDEX}" - это часть которую нужно дописать к OID указанному в discovery что бы получить значение

[
  {
    "{#SNMPINDEX}": "1.3.52.53.48.0.8.202.43.1.36",
    "{#S}": "-66"
  },
  {
    "{#SNMPINDEX}": "2.3.52.53.48.164.69.25.90.239.72",
    "{#S}": "-66"
  }
] 

Это выглядит странновато, но суть этого - получить список суффиксов, которые потом можно использовать для получения других значений
В поле "{#S}" записан сигнал и его значение я нигде не использую, но в общем случае (для других MIB/OID) тут может быть что-то что можно использовать (в оригинальной документации это имена интерфейсов)
В общем случае можно указать несколько OID которые нужно обходить snmpwalk-ом, но при этом нужно держать в голове что SNMPINDEX должен совпадать - так работает для таблицы интерфейсов где по разным префиксам но с одним и тем же ifIndex можно получить данные с интерфейса - имя, дескрипшен, байты и т.п.

Если же указать 2 OID с разной структурой (например интерфейсы и таблицу регистрации клиентов) то ничего хорошего не получится - данные будут перемешаны (подробно я не смотрел код как именно и почему )


Далее при создании прототипов элементов данных можно использовать "{#SNMPINDEX}" и тогда все остальные переменны в JSON полученном при discovery будут доступны

Например, если при создании прототипа данныхь указать OID=.1.3.6.1.4.1.9.9.273.1.3.1.1.2.{#SNMPINDEX} то (для моего примера будет автоматически создано 2 элемента данных, в именах которых можно использовать например значение макроса "{$S}". Это хорошо ложиться на пример с интерфейсом, но в моем случае этот макрос как и остальные совершенно бесполезен так как вся статическая информация закодирована в OID который собственно доступен через макрос "{SNMPINDEX}"

Processing

Для того что бы получить нужные данные в удобном виде полученный при discovery JSON можно редактировать с помошью встроенного JavaScript

В моем случае на скорую руку вышел вот такой скрипт:

var records = JSON.parse(value);

for (i = 0; i < records.length; i++) {
    var OID = records[i]["{#SNMPINDEX}"].split('.')
    // IFINDEX AND IFNAME
    var dot1RadioIfIndex = OID.shift();
    records[i]['{#DOT1RADIO_IFINDEX}'] = dot1RadioIfIndex
    records[i]['{#DOT1RADIO_IFNAME}'] = "Dot11Radio" + (parseInt(dot1RadioIfIndex) - 1).toString()

    // get mac as 6 last digits converted dec -> hex and joined with ':'
    var MAC = ""
    var MACDigitHex
    for (j = 0; j < 6; j++) {
        MACDigitDec = OID.pop();

        MACDigitHex = parseInt(MACDigitDec).toString(16);
        MAC = MACDigitHex + " " + MAC
    }
    records[i]['{#MAC}'] = MAC.trim().split(" ").join(":")

    // SSID. The first octet is length, others are ASCII characters 
    SSID = ""
    ssidLength = OID.shift();
    
    for (j = 0; j < ssidLength; j++) {
      SSID += String.fromCharCode(parseInt(OID[j]));

    }
    records[i]['{#SSID}'] = SSID
}
return JSON.stringify(records);

Идея в том что бы добавить поля построенные на основе SNMPINDEX в Json, и в дальнейшем они будут доступны при создании элементов данных


В результате из исходного JSON получаю такой

[
  {
    "{#SNMPINDEX}": "1.3.52.53.48.0.8.202.43.1.36",
    "{#S}": "-62",
    "{#DOT1RADIO_IFINDEX}": "1",
    "{#DOT1RADIO_IFNAME}": "Dot11Radio0",
    "{#MAC}": "0:8:ca:2b:1:24",
    "{#SSID}": "450"
  },
  {
    "{#SNMPINDEX}": "2.3.52.53.48.164.69.25.90.239.72",
    "{#S}": "-79",
    "{#DOT1RADIO_IFINDEX}": "2",
    "{#DOT1RADIO_IFNAME}": "Dot11Radio1",
    "{#MAC}": "a4:45:19:5a:ef:48",
    "{#SSID}": "450"
  }
]

который уже содержит статическую информацию о клиенте и который можно использовать для создания элеметов данных

Прототпипы жлементов данных

Формируем имя и ключ на основе данных из Json, например

Name cDot11ClientSignalStrength [ {#MAC}@{#DOT1RADIO_IFNAME}:{#SSID} ]

где для кажого клиента будет создан отдельный элемент данных, при этом используются три уникальных значения, клиент с тем же маком но подключившись в другом диапазоне (другой интерфейс) рассматривается как другой клиент даже если используется один SSID для разных частот)

Готовый Темплейт