Мониторинг SNMP трапов#

В текущей реализации поддерживаются версии SNMP v1 и v2c.

Файл правил состоит из пяти основных частей:

  • Header — документация с определением переменных;

  • Lookup — таблицы приведения числовых обозначений в человекочитаемый формат;

  • Preparation — подготовка служебной информации и предварительная обработка трапов;

  • Body — ветвление правил по SNMP трапам;

  • Footer — подготовка результата для дальнейшей обработки.

Lookup — таблицы приведения#

IANAifType = {
    "1": "Other", // other - none of the following
    "2": "Regular 1822", // regular1822
    "3": "HDH 1822", // hdh1822
    "4": "DDN X.25", // ddnX25
    "5": "RFC-877 X.25", // rfc877x25
    "6": "Ethernet CSMA-CD", // ethernetCsmacd
    "7": "ISO 8802.3 CSMA-CD", // iso88023Csmacd
    "8": "ISO 8802.4 Token Bus", // iso88024TokenBus
    ...
    "212": "Voice FGD Exchange Access North American", // voiceFGDEANA - voice FGD Exchange Access North American
    "213": "Voice Direct Inward Dialing" // voiceDID - voice Direct Inward Dialing
}

ifAdminStatus = {
    "1": "Up", // up - ready to pass packets
    "2": "Down", // down
    "3": "Testing" // testing - in some test mode
}

ifOperStatus = {
    "1": "Up", // up - ready to pass packets
    "2": "Down", // down
    "3": "Testing", // testing - in some test mode
    "4": "Unknown", // unknown - status can not be determined for some reason.
    "5": "Dormant", // dormant
    "6": "Not Present", // notPresent - some component is missing
    "7": "Lower Layer Down" // lowerLayerDown - down due to state of lower-layer interface(s)
}

Preparation — подготовка данных#

// Устанавливаем стандартный Agent, Manager и Class
_Manager = "SNMP Trap adapter on " + hostname()
_Agent = "SNMPagent"
_Class = "300"

// Проверяем если получили SNMPv2 трап и ковертируем его в SNMPv1 стиль
if (typeof $notify !== "undefined") // Если $notify существует то это SNMPv2 трап
{
    _Node = $PeerAddress
    _NodeAlias = $PeerIPaddress

    if (regmatch($notify, "\.iso\.")) {
        $notify = ".1." + extract($notify, "\.iso\.(.*)")
    }

    if (nmatch($notify, ".1.3.6.1.6.3.1.1.5")) // SNMPv2 Generic трап
    {
        $Enterprise = extract($notify, "(.*)\.[0-9]+$")
        $specific_trap = "0"
        $generic_trap = (int(extract($notify, ".*\.([0-9]+)$")) - 1).toString()
    } else // Enterprise Specific трап
    {
        if (match(extract($notify, "\.([0-9]+)\.[0-9]+$"), "0")) {
            $Enterprise = extract($notify, "(.*)\.[0-9]+\.[0-9]+$")
        } else {
            $Enterprise = extract($notify, "(.*)\.[0-9]+$")
        }
        $specific_trap = extract($notify, ".*\.([0-9]+)$")
        $generic_trap = "6"
    }
} else // Это SNMPv1 трап
{
    _Node = $Node
    if (typeof $IPAddress !== "undefined")
    {
        _NodeAlias = $IPAddress
    } else {
        _NodeAlias = $IPaddress
    }
}

Body — определение трапов и извлечение необходимых данных для создания события#

На примере конфигурации для Cisco Generic трапов:

if (match($generic_trap, "6")) // Проверяем если Enterprise Specific трап
{
    switch ($Enterprise) {
        case "dummy case statement": // Это позволит ибежать синтаксических ошибок при отсутствующих кейсай
            break
        // В этом сегменте определяем Enterprise Specific трапы не относящиеся к Generic, как в следующем примере
        case ".1.3.6.1.4.1.9.9.43.2":    // Если $Enterpries соответствует Cisco и трапу ciscoConfigManMIBNotificationPrefix
            switch ($specific_trap) {
                case "1": // - ciscoConfigManEvent
                    // ...
                    break
                case "2": // - ccmCLIRunningConfigChanged
                    // ...
                    break
                case "3": // Если $specific_trap соответсвует ccmCTIDRolledOver
                    _AlertGroup = "cisco"
                    _Agent = "cisco"
                    _Summary = "ccmCTIDRolledOver: This notification indicates that the Config Change Tracking ID has rolled over and will be reset."
                    _Severity = 3
                    _Type = 1
                    _ExpireTime = 10
                    _Identifier = _Node + _Summary
                    break
                default:
                    _Summary = "Unknown specific trap number (" + $specific_trap + ") received for enterprise " + $Enterprise
                    _Identifier = _Node + $Enterprise + $generic_trap + $specific_trap + _Agent + _Manager
                    _Severity = 3
                    _Type = 1
            }
            break
        default:
            $EventID = $Enterprise + "|" + $generic_trap + "|" + $specific_trap
            switch ($EventID) {
                case "dummy case statement": // Это позволит ибежать синтаксических ошибок при отсутствующих кейсай
                    break
                default:
                    _Summary = "Enterprise ID Not Found (see details): " + $Enterprise + " " + $generic_trap + " " + $specific_trap
                    _Severity = 2
                    _Type = 1
            }
            _Identifier = _Node + " " + $Enterprise + " " + $generic_trap + " " + $specific_trap + " " + _AlertGroup + " " + _AlertKey + " " + _Agent + " " + _Manager
    }
} else // Проверяем если Generic трап
{
    // Стантартно для Generic
    _Agent = "Generic"
    switch ($generic_trap) {
        // В этом сегменте определяем только SNMP Generic трапы
        case "0": // coldStart
            _AlertGroup = "Generic"
            _AlertKey = ""
            _Summary = "Cold Start"
            _Severity = 2
            _Type = 1
            _Identifier = _Node + " " + _AlertGroup + " " + _Agent + " " + _Manager + " " + $generic_trap
            break
        case "1": // warmStart
            // ...
            break
        case "2": // linkDown
            // ...
            break
        // ...
        default:
            _Summary = "Invalid Generic Trap Number: " + $Enterprise + " " + $generic_trap + " " + $specific_trap
            _Severity = 2
            _Type = 0
            _Identifier = _Node + " " + $Enterprise + " " + $generic_trap + " " + $specific_trap + " " + _Agent + " " + _Manager
    }
    switch ($Enterprise) {
      // В этом сегменте определяем SNMP Generic трапы которые относятся к другим MIB или к Enterprise (Generic трапы имеющие дополнительную Enterprise информацию)
        case ".1.3.6.1.6.3.1.1.5": // RFC1907 - SNMPv2-MIB
            if (nmatch($OID1, ".1.3.6.1.4.1.9") || nmatch($OID2, ".1.3.6.1.4.1.9") || nmatch($OID4, ".1.3.6.1.4.1.9")) { // Если трап содержит один из данных OID, значит это Enterprise Generic трап принадлежащий Cisco
                _Agent = "Generic-Cisco SNMPv2"
                _Class = "40057"
                switch ($generic_trap) {
                    case "0": // При попадании в этот кейс, выполняем следующий что бы не дублировать код
                    case "1": // Для трапов coldStart и warmStart одинаковая ветка, так что можно их обрабатывать одинаково
                        $sysUptime = $1
                        $whyReload = $2
                        details($sysUptime, $whyReload)

                        _Summary = _Summary + ": " + $2
                        _Identifier = _Identifier + " " + $2
                        break
                    case "2":
                    case "3": // Так же как и для предыдущих, linkDown и linkUp обрабатываем одинаково
                        // ...
                        break
                    // ...
                    default:
                }
            } if (nmatch($OID6, ".1.3.6.1.4.1.9")) { // Если Generic трап содержит данный OID, значит это Generic-Cisco трап
                _Agent = "Generic-Cisco SNMPv2"
                _Class = "40057"
                switch ($generic_trap) {
                    case "2":
                    case "3": // linkDown, linkUp
                        $ifIndex = $1
                        $ifAdminStatus = ifAdminStatus[$2] + " ( " + $2 + " )"
                        $ifOperStatus = ifOperStatus[$3] + " ( " + $3 + " )"
                        $ifDescr = $4
                        $ifType = IANAifType[$5] + " ( " + $5 + " )" // Берем описание из Lookup таблицы
                        $locIfReason = $6
                        details($ifIndex, $ifAdminStatus, $ifOperStatus, $ifDescr, $ifType, $locIfReason)

                        switch ($2) {
                            case "2": // Down
                                _Summary = _Summary + ", Administratively: " + $6 + "  ( " + $4 + " )"
                                _Severity = 2
                                break
                            case "3": // Testing - in some test mode
                                _Summary = _Summary + ", Testing: " + $6 + "  ( " + $4 + " )"
                                _Severity = 2
                                break
                            default:
                                _Summary = _Summary + ": " + $6 + "  ( " + $4 + " )"
                        }
                        _Identifier = _Identifier + " "
                        break
                    default:
                    // ...
                }
            } else { // Если не подходит не под онид из перечисленнх вариантов, значит это Generic IETF SNMPv2 Трап
                _Agent = "Generic-IETF-SNMPv2-MIB"

                switch ($generic_trap) {
                    case "2":
                    case "3": // linkDown, linkUp
                        // ...
                        break
                    // ...
                    default:
                    // ...
                }
            }
            break
        // ...
        default:
            if (match($Enterprise, "")) {
                _Summary = "Dummy Enterprise! If you matched here you have problems! (see details)"
            }
            else // Обрабатываем неизвестный Enterprise как SNMPv1 Generic трап
            {
                _Agent = "Generic-Unknown"
                switch ($generic_trap) {
                    case "2":
                    case "3": // linkDown, linkUp
                        //...
                        break
                    default:
                        _Summary = _Summary + "  ( Enterprise = " + $Enterprise + " )"
                }
            }
    }
}

Алерты#

Для отправки алертов необходимо установить параметр _Alert = true в соответствующих ветках файла правил где необходимо создать алерт.

Пример ветки трапа с алертом:

// ...
        case "2": // linkDown
            _AlertGroup = "Generic Link Status"
            _AlertKey = "ifEntry." + $1
            _Summary = "Link Down"
            _Severity = 5
            _Type = 1
            _Identifier = _Node + " " + _AlertKey + " " + _AlertGroup + " " + _Agent + " " + _Manager
            _Alert = true // При установке данного параметра в true будет создан алерт на текущий трап
            break
// ...

Доступные параметры в файле правил:

Поле

Версии SNMP

Описание

$Community

V1 и V2c

Строка community SNMP

$contextEngineID

V3

Context Engine ID

$Enterprise

V1

Строка enterprise SNMP

$generic_trap

V1

Целочисленное значение Generic SNMP-трапа

$IPAddress

V1, V2c и V3

IP-адрес (происхождение SNMP-трапа)

$Node

V1, V2c и V3

Имя узла (происхождение SNMP-трапа). IP-адрес (если имя узла не может быть разрешено)

$notify

V2c и V3

Специфическое поле notify V2c

$PeerAddress

V1, V2c и V3

Имя хоста или IP-адрес, откуда был получен SNMP-трап

$PeerIPaddress

V1, V2c и V3

IP-адрес, откуда был получен SNMP-трап

$Protocol

V1, V2c и V3

Протокол полученного трапа. Это может быть либо UDP, либо TCP

$ReceivedPort

V1, V2c и V3

Номер порта, откуда был получен SNMP-трап. Это определяется свойством Port

$ReceivedTime

V1, V2c и V3

Время получения SNMP-пакета с сетевого интерфейса

$ReqId

V1

Идентификатор запроса SNMP

$securityEngineID

V3

Security Engine ID авторитетного SNMP-субъекта. Для трапов - это Engine ID источника трапа

$securityLevel

V3

Уровень безопасности trap или inform:

noAuth - trap или inform не имеют аутентификации и конфиденциальности,

authNoPriv - trap или inform имеют аутентификацию, но без конфиденциальности,

authPriv - trap или inform имели аутентификацию и конфиденциальность

$securityName

V3

Security Name, используемое для аутентификации трапа

$SNMP_Version

V1, V2c и V3

Имеет значение 1 для трапов SNMP V1 и значение 2 для трапов SNMP V2c

$specific_trap

V1

Целочисленное значение Specific SNMP-трапа

$UpTime

V1 и V2c

Аптайм SNMP трапов, выраженное в целых числах

$n_hex

Шестнадцатеричное представление переменных varbind