Библиотека сайта rus-linux.net
20-ти минутный урок по SNMP - автоматизация системного администрирования при помощи Perl
Оригинал: The 20-Minute SNMP Tutorial - Automating System Administration with Perl
Автор(ы): David N. Blank-Edelman,
Дата публикации: 2009 г.
Перевод: Коваленко Алексей
Дата перевода: 28.10.2009 г.
Ниже представлена выдержка из книги "Автоматизация системного администрирования с использованием Perl, Второе издание". Основательно обновленное и расширенное, это второе издание содержит сведения о новейших операционных системах, технологиях и модулях Perl. "Автоматизация системного администрирования с использованием Perl" поможет вам выполнить работу с меньшими усилиями. Второе издание не только предлагает подходящие инструменты для работы, но так же дает рекомендации по выбору оптимального пути подхода к определенным проблемам и безопасной автоматизации насущных задач.
Простой протокол управления сетью (SNMP) это широко распространенный протокол управления сетевыми устройствами. К сожалению, как упоминалось в начале Главы 12, SNMP, это не очень простой протокол (несмотря не его название). Этот, достаточно длинный, урок даст вам информацию, которая необхода для начала работы с SNMP версии 1.
SNMP испольует метод опроса управляющей станцией агентов, запущенных на удаленных устройствах SNMP, для получения от них информации. Агент может также сигнализировать управляющей станции о том, что произошло важное событие, например такое, как достижение счетчиком порога. Когда мы программировали SNMP в Perl в Главе 12, SNMP, мы, по существу, выступали как управляющая станция, опрашивающая SNMP-агентов на других устройствах сети.
В этом руководстве мы сосредоточимся на версии 1 SNMP. Всего были представлены семь версий этого протокола (SNMPv1, SNMPsec, SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, и SNMPv3); версия 1 в настоящее время наиболее широко используется, и это несмотря на то, что в конечном счете ожидается внедрение версии 3 в силу того, что в версии 3 улучшена архитектура безопасности.
Perl и SNMP оба используют простые типы данных. Perl использует скалярный тип как базовый. Списки и хэш-массивы - это просто наборы скалярных данных в Perl. В SNMP вы также работаете со скалярными переменными. Переменные SNMP могут содержать любой из четырех примитивных типов: целые, строки, идентификаторы объектов (подробнее об этом чуть позже) или нулевые значения. И, так же как в Perl, в SNMP набор связанных переменных может быть сгруппирован для формирования больших структур (чаще всего таблиц). На этом их подобие заканчивается.
Perl и SNMP радикально отличаются в отношении имен переменных. В Perl вы можете, учитывая некоторые ограничения, именовать ваши переменные так, как вам нравится. Имена переменных в SNMP значительно более ограничены. Все переменные SNMP существуют в пределах структуры виртуального иерархического хранилища, известного как управляющая информационная база (management information base - MIB). Все действительные имена переменных определяются в пределах этого каркаса. MIB (в настоящее время версии MIB-II) определяет структуру дерева для всех объектов (и их имен), которые могут управляться через SNMP.
В некотором роде MIB подобна файловой системе; но вместо организации файлов MIB логически организует управляющую информацию в иерархическую древовидную структуру. Каждый узел в этом дереве имеет короткую текстовую строку, называемую ярлыком, и сопутствующий номер, который представляет его позицию на данном уровне дерева. Для того, чтобы вы поняли как это работает, перейдем к поиску в MIB переменной SNMP, которая содержит в себе описание системы. Предлагаю, для наглядности, вместе со мной посмотреть на дерево высотою в восемь уровней.
Рисунок G.1, "Поиск sysDescr(1) в MIB" показывает картину верхушки дерева MIB.
Рисунок G.1. Поиск sysDescr(1) в MIB
Верхушка дерева содержит стандартные структуры: iso(1), ccitt(2), joint-iso-ccitt(3)
. Под узлом iso(1)
есть узел, называемый org(3)
для других структур. Под этим узлом находится узел dod(6)
, для
Министерства Обороны. Под ним узел internet(1)
- поддерево для Интернет сообщества.
Здесь уже становится интересно. Совет по архитектуре Интернета определил принадлежность к internet(1)
поддеревьев, перечисленных в
Таблице
G.1, "Поддеревья узла internet(1)"
Таблица G.1. Поддеревья узла internet(1)
Поддерево |
Описание |
---|---|
directory(1) |
Каталог OSI |
mgmt(2) |
Стандартные объекты RFC |
experimental(3) |
Эксперименты Интернета |
private(4) |
Специализированный |
security(5) |
Безопасность |
snmpV2(6) |
Свойства SNMP |
Поскольку нас интересует использование SNMP для управления устройствами, будем использовать ветвь mgmt(2)
.
Первый узел, расположенный под mgmt(2)
, это сама MIB (это почти рекурсия). Так как существует только одна MIB, то для нее
существует только один узел , расположенный под mgmt(2)
, это - mib-2(1)
.
Реальная суть MIB начинается с этого уровня дерева. Мы ищем первый набор ветвей, называемый группами объектов, содержащий переменные, которые мы хотим опросить.
system(1) interfaces(2) at(3) ip(4) icmp(5) tcp(6) udp(7) egp(8) cmot(9) transmission(10) snmp(11)
Вспомните, мы ищем переменную SNMP "system description"
, поэтому группа system(1)
- логичное место для поиска. Первый узел в этом дереве, это sysDescr(1)
. Вот мы и нашли объект, который нам нужен.
Зачем нам необходим весь этот процесс прохода по дереву? Затем, что он обеспечивает нас идентификатором объекта (OID) sysDescr(1)
,
который является набором номеров, разделенных точками, для каждого ярлыка дерева, встреченного нами на пути к объекту.
Рисунок G.2, "Поиск OID для желаемого объекта" показывает это графически.
Рисунок G.2, Поиск OID для желаемого объекта
Таким образом OID для Интернет, это 1.3.6.1
, OID группы системных объектов - 1.3.6.1.2.1.1
, и OID
для объекта sysDescr
- 1.3.6.1.2.1.1.1
.
Когда мы действительно хотим использовать этот OID на практике, нам необходимо присоединить к нему дополнительный номер для получения
значения этой переменной. То есть, нам необходимо добавить в конце OID .0
, представляющий первый (и единственный,
поскольку устройство не может иметь более одного описания) экземпляр этого объекта.
Попробуем это сделать, чтобы получить краткое представление об SNMP в действии. В этом приложении, для демонстрационных целей, мы использовали инструменты командной строки из пакета Net-SNMP. Этот пакет - прекрасная свободная реализации SNMP версии 1 и версии 3. Мы использовали эту частную реализацию, поскольку один из модулей Perl подключается к ее библиотеке, но любой другой клиент, имеющий возможность отправлять SNMP запросы, так же прекрасно подойдет. После того, как вы ознакомитесь с инструментами командной строки SNMP, перейти к использованию эквивалентных инструментов Perl будет проще.
Инструменты командной строки Net-SNMP позволяют нам добавить перед OID или именем переменной точку (.)
, если мы хотим определить OID/имя
переменной начинающееся с корня дерева. Таким образом, существует два способа задания пути,
с помощью которых мы можем выполнить запрос к машине solarisbox
и получить описание ее системы (обратите внимание, что обе части команды должны быть написаны
в одной строке; здесь же они разнесены по разным строкам для удобства чтения):
$ snmpget -v 1 -c public solarisbox .1.3.6.1.2.1.1.1.0 $ snmpget -v 1 -c public solarisbox \
.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0
Обе эти строки выводят:
system.sysDescr.0 = Sun SNMP Agent, Ultra-1
Вернемся к теории. Важно помнить, что P в SNMP обозначает Протокол (Protocol). Сам по себе SNMP это просто протокол для общения между объектами в инфраструктуре управления. Операции или "модули данных протокола" ("protocol data units") (PDU) должны быть простыми. Вот перечень PDU, которые вы будете встречать наиболее часто, в особенности, когда программируете в Perl: [148]
get-request
-
get-request
это "рабочая лошадь" семейства PDU: она используется для опроса SNMP объекта и получения значений некоторых SNMP переменных.
get-next-request
-
get-next-request
подобнаget-request
, за исключением того, что она возвращает пункт MIB, следующий за определенным в запросе пунктом ("первый лексикографический наследник" в терминах RFC). Эта операция задействуется тогда, когда вы пытаетесь найти все пункты в логической таблице объекта, например, вы можете отправлять набор повторяющихсяget-next-request
для опроса каждой строки таблицы ARP рабочей станции. Далее мы увидим практический пример работы с этой операцией.
get-bulk-request
-
get-bulk-request
это дополнительная операция для SNMPv2/v3, которая позволяет групповую передачу информации. С другими PDU, вы обычно запрашиваете и получаете небольшую часть информации.get-bulk
позволяет вам сделать один запрос и получить целый набор значений. Этот путь может быть намного более эффективным для передачи больших объемов информации (подобно целым таблицам).
set-request
-
set-request
делает только то, что вы ожидаете: она пытается изменить значение переменной SNMP. Эта операция используется для изменения конфигурации SNMP-совместимого устройства.
trap/snmpV2-trap
-
trap ("ловушка")
это имя SNMPv1,snmpV2-trap
это имя SNMPv2/3. "Ловушки" позволяют получать от SNMP-совместимых устройств сигналы их управляемого агента о событии (например, перезагрузке, или достижении счетчиком порога) без выполнения явного запроса. "Ловить" отчеты о событиях уместно в моменты, когда события происходят, а не во время выполнения опроса агента.
inform-request
-
inform-request
это дополнение к списку PDU для SNMPv2/3. Она обеспечивает подобную "ловушке" функциональность с дополнительным подтверждением. (С нормальными запросами "ловушек" агент отправляет оповещение, но не имеет возможности узнать получено ли оно. Информирование обеспечивает этот механизм.)
response
-
response
это операция, используемая для ответа на запрос от любой другой операции. Она может быть ответом наget-request
, сигнализировать об успешном выполненииset-request
, и так далее. Вы нечасто специально используете эту операцию когда программируете, поскольку большинство SNMP библиотек, программ и модулей Perl самостоятельно отправляют ответные квитанции SNMP. Однако, важно не только понимать, как выполняются запросы, но так же, как происходят ответы на них.
Если вы никогда ранее не имели дела с SNMP, то естественной реакцией на этот список может быть вопрос: "Что это за набор функций? Получить,
установить, сообщить мне, когда что-то происходит; и это все, что здесь можно сделать?" Но простота, реализованная создателями SNMP изначально, ничуть не умоляет мощи этого протокола.
Если производитель устройства тщательно отбирает для него SNMP переменные, то с использованием этого
протокола может быть сделано очень многое. Классический пример из RFC - это перезагрузка SNMP-совместимого устройства. Операция "reboot-request" ("запрос
перезагрузки") может не существовать, но производитель может легко реализовать ее, используя переменную-триггер SNMP, отсчитывающую
некоторое количество секунд перед выполнением перезагрузки. Если эта переменная изменена через set-request
, спустя определенное время инициируется перезагрузка устройства.
Учитывая эту мощь, какой тип безопасности должен иметь место, чтобы не допустить перезагрузок вашей машины кем бы то ни было, у кого есть SNMP клиент? В ранних версиях протокола механизм защиты был довольно слабым. Факт, что некоторые люди раскрывали акроним SNMP ("Simple Network Management Protocol") как "Security Not My Problem" ("Безопасность Не Моя Проблема"), поскольку у SNMPv1 очень слабый механизм аутентификации. Для того, чтобы объяснить все "кто, что, и как?" этого механизма защиты, нам необходимо рассмотреть некоторые спецификации, что мы и сделаем.
SNMPv1 и SNMPv2c позволяют нам определить административные отношения, названные сообществами, между SNMP объектами. Сообщества - это путь группирования SNMP агентов, которые имеют похожие ограничения доступа с управляемыми объектами, которые, в свою очередь, соответствуют этим ограничениям. Все объекты, находящиеся в сообществе, совместно используют одно и тоже имя сообщества. Для подтверждения того, что вы часть сообщества вам достаточно знать имя этого сообщества. Это часть схемы - "Кто может иметь доступ?".
Теперь рассмотрим часть схемы "К чему они могут иметь доступ?". RFC 1157 называет части MIB, относящиеся к определенному сетевому объекту, видами SNMP MIB. Например, SNMP-совместимый тостер [149] не будет обеспечивать все те же самые SNMP конфигурации переменных, как SNMP-совместимый маршрутизатор.
Для каждого объекта в MIB определена его доступность: read-only
, read-write
или none
(только на чтение
, на чтение и запись
и нет
доступа
). Это называется режимом доступа к объекту SNMP. Если мы объединим
вид SNMP MIB и режим доступа SNMP вместе, то получим профиль сообщества SNMP,
который описывает типы доступа, применимые к подходящим переменным в MIB,
через определенное сообщество.
Когда мы соединяем вместе части "кто" и "что", мы получаем политику доступа SNMP, которая описывает, какой вид доступа члены определенного сообщества предлагают друг-другу.
Как это работает в реальной жизни? Вы настраиваете ваш маршрутизатор или вашу рабочую станцию так,
чтобы они принадлежали по-крайней мере
двум сообществам, одно из них контролирует доступ на чтение, другое на чтение и запись.
Люди часто говорят об этих сообществах как о public
(публичном)
и private (частном)
сообществах, используя для этих сообществ
общепринятые названия. Например, на маршрутизаторе Cisco вы
можете включить это как часть конфигурации:
! set the read-only community name to MyPublicCommunityName snmp-server community MyPublicCommunityName RO ! set the read-write community name to MyPrivateCommunityName snmp-server community MyPrivateCommunityName RW
На машине с операционной системой Solaris вы можете включить это в файл /etc/snmp/conf/snmpd.conf:
read-community MyPublicCommunityName
write-community MyPrivateCommunityName
SNMP запросы к любому из этих устройств должны будут использовать имя сообщества MyPublicCommunityName
для получения
доступа к переменным только для чтения или имя сообщества MyPrivateCommunityName
для изменения значений переменных на этих устройствах, доступных по чтению/записи. Другими
словами, имя сообщества функционирует как псевдо-пароль для получения SNMP доступа к устройству.
Это слабая схема безопасности. И дело не только в том, что имя
сообщества передается обычным текстом в любом пакете SNMPv1, но и в том, что общая стратегия
строится по принципу "безопасность за счет незнания".
В последних версиях SNMP, в частности, v3 - безопасность протокола значительно улучшена. RFC 3414 и 3415 определяют User Security Model (Модель Безопасности Пользователя) (USM) и View-Based Access Control Model (Видовую Модель Управления Доступом) (VACM): USM обеспечивает построенную на шифровании защиту для аутентификации и шифрование сообщений, в то время как VACM предлагает всесторонний механизм управления доступом для объектов MIB. Мы не будем обсуждать эти механизмы здесь, но, возможно, вам стоит посвятить время внимательному прочтению RFC, поскольку популярность SNMPv3 постоянно возрастает. Я также рекомендую к прочтению учебные пособия по SNMPv3, представленные в дистрибутиве Net-SNMP. Если вы заинтересовались USM и VACM и тем, как они могут быть сконфигурированы, то можете обратиться к хорошему учебному пособию на эту тему, которое опубликовал производитель SNMP решений NuDesign Technologies (http://www.ndt-inc.com/SNMP/HelpFiles/v3ConfigTutorial/v3ConfigTutorial.html).
SNMP на практике
Теперь, когда вы получили существенную дозу теории SNMP, давайте попробуем применить эти знания на практике. Вы уже читали, как запросить у машины описание системы (вспомните, что было написано ранее), теперь рассмотрим два следующих примера: запрос времени работы системы с момента последнего перезапуска и таблицы маршрутизации IP.
До настоящего момента вы узнавали в теории про размещение и имя SNMP переменной в MIB. Так вот, запрос информации через SNMP - это процесс состоящий из двух шагов:
-
Поиск правильного MIB документа. Если вы просматриваете независимые от устройства настройки, которые могут быть найдены в любом обычном SNMP устройстве, то возможно вы найдете их в RFC 1213 [150]. Если вам необходимы определенные производителем имена переменных (например, переменная, которая содержит цвет мигающего индикатора на фронтальной панели определенного VoIP коммутатора), то вам будет нужно связаться с производителем коммутатора и запросить у него копию модуля MIB. Здесь я хочу обратить внимание на точность в терминологии, поскольку нередко слышу подобные некорректные заявления: "Мне необходима MIB для этого устройства." Но в мире существует только одна MIB; все остальное помещается где-либо в ее структуре (обычно внутри раздела
private(4)
). -
Поиск среди описаний MIB, до тех пор пока вы не найдете SNMP переменную(-ые), которая вам требуется.
Чтобы выполнение этого второго этапа стало для вас более простым, [151] позвольте мне декодировать формат.
Описания MIB становятся не такими страшными, как только вы начинаете их использовать. Они выглядят как один длинный набор объявлений переменных, и они подобны тем, которые вы встретили бы в исходном коде. Это не случайное совпадение, поскольку они являются объявлениями переменных. Если производитель принимал участие в разработке этого модуля, то модуль будет хорошо прокомментирован, подобно любому хорошему файлу исходного кода.
Информация MIB записывается в подмножестве Абстрактной синтаксической нотации версии один (АСН.1) - стандартной нотации Взаимодействия Открытых Систем (OSI). Описание этого подмножества и другие детали описаний данных для SNMP можно найти в RFC Структура для Управляющей Информации (SMI), которая сопутствует RFC, определяющим SNMP протокол и текущую MIB. Например, последнее (на момент написания этого материала) описание SNMP протокола может быть найдено в RFC 3416, последняя база MIB, управляемая этим протоколом в RFC 3418, и SMI для этой MIB в RFC 2578. Я упомянул об этом, поскольку нередко приходится переключаться между разными документами когда производится поиск спецификаций субъекта SNMP.
Теперь давайте воспользуемся этими знаниями для решения первой задачи: поиск через SNMP времени работы системы от момента последней перезагрузки. Эта информация достаточно общая, поэтому, с большой долей вероятности, мы сможем найти требуемую SNMP переменную в RFC 1213. Быстрый поиск по значению "uptime" в RFC 1213 приносит следующий отрывок АСН.1:
Опишем этот отрывок построчно:
sysUpTime OBJECT-TYPE
Эта строка определяет объект, называемый sysUpTime.
SYNTAX TimeTicks
Этот объект имеет тип TimeTicks. Типы объектов определяются в SMI I, о ней мы упомянем мгновением позже.
ACCESS read-only
Этот объект может быть только прочитан через SNMP (т.е. может быть выполнен только запрос get-request); он не может быть изменен (т.е. запрос set-request выполнен быть не может).
STATUS mandatory
Этот объект должен быть реализован в любом SNMP агенте.
DESCRIPTION...
Это текстуальное описание объекта. Всегда читайте внимательно это поле. В этом описании для нас кроется сюрприз: sysUpTime показывает только общее количество времени, которое прошло с момента когда "была повторно инициализирована сетевая часть управления системой." Это значит, что мы можем узнать только время работы системы с момента последнего старта ее SNMP агента. Это практически всегда означает то же самое, что и последний старт самой системы, но если вы увидели аномалию, то это (прим. переводчика - перезапуск SNMP агента) может быть одной из причин ее появления.
::= { system 3 }
Здесь указывается, где размещается объект в дереве MIB. Объект sysUpTime - это третье ответвление дерева группы системных объектов. Эта информация также дает вам часть OID, она потребуется вам позже.
Если мы хотим запросить эту переменную на машине solarisbox в сообществе только для чтения, мы можем использовать следующий инструмент командной строки Net-SNMP:
$ snmpget -v 1 -c MyPublicCommunityName solarisbox system.sysUpTime.0
Эта команда возвращает следующий результат:
system.sysUpTime.0 = Timeticks: (5126167) 14:14:21.67
показывающий, что агент был последний раз инициализирован 14 часов назад.
Замечание
Приведенные примеры в этом приложении предполагают, что наши SNMP агенты были настроены, чтобы разрешать запросы от опрашивающего узла. В общем случае, если вы можете ограничить SNMP доступ определенным подмножеством "доверенных" узлов, то вы должны это сделать.
"Необходимо знать" - это прекрасный принцип безопасности, которого надо придерживаться. Хорошей практикой является ограничение сетевых служб, предоставляемых каждой машиной или устройством. Если вам не требуется предоставлять сетевые службы, отключите их. Если требуется - ограничьте доступ к ним только теми устройствами, которым "необходимо знать".
Пришло время для нашего второго и более продвинутого SNMP примера: выгрузка содержимого таблицы IP маршрутизации устройства. Сложность этого примера вытекает из необходимости трактовки набора скалярных данных как единственной логической таблицы. Мы должны будем вызывать PDU get-next-request
для того, чтобы это осуществить. Нашим первым шагом по направлению к этой цели будет поиск описания MIB для таблицы IP маршрутизации. Выполнив поиск по значению "route" в RFC 1213, мы в конечном счете находим это описание:
-- The IP routing table contains an entry for each route -- presently known to this entity. ipRouteTable OBJECT-TYPE SYNTAX SEQUENCE OF IpRouteEntry ACCESS not-accessible STATUS mandatory DESCRIPTION "This entity's IP Routing table." ::= { ip 21 }
Оно не выглядит сильно отличающимся от описания, которое мы рассматривали выше. Различия состоят в строках ACCESS
и SYNTAX
. Строка ACCESS
это предупреждение о том, что данный объект - просто структурная
метка-заполнитель, представляющая целую таблицу, а не реальную переменную, которая может быть опрошена. Строка SYNTAX
говорит нам о том, что это таблица, состоящая из набора объектов IpRouteEntry
. Давайте посмотрим на начало описания IpRouteEntry
:
ipRouteEntry OBJECT-TYPE SYNTAX IpRouteEntry ACCESS not-accessible STATUS mandatory DESCRIPTION "A route to a particular destination." INDEX { ipRouteDest } ::= { ipRouteTable 1
Строка ACCESS
говорит, что мы нашли еще одну метку-заполнитель - заполнитель для каждой строки в нашей таблице.
Но эта метка-заполнитель все же может нам кое-что рассказать. Она показывает, что мы имеем возможность доступа к каждой строке с
использованием объекта индекса, - объекта ipRouteDest
каждой строки.
Если эти множественные уровни определений вас путают, то разобраться можно связав их с Perl. Притворимся, что мы имеем дело с хэшем структуры списков Perl. Хэш ключа для строки был бы переменной ipRouteDest
. Значение для этого хэша было бы тогда ссылкой на список, содержащий другие элементы в этой строке (т. е. оставшуюся часть записи маршрута).
Определение ipRouteEntry
продолжается как показано ниже:
ipRouteEntry ::= SEQUENCE { ipRouteDest IpAddress, ipRouteIfIndex INTEGER, ipRouteMetric1 INTEGER, ipRouteMetric2 INTEGER, ipRouteMetric3 INTEGER, ipRouteMetric4 INTEGER, ipRouteNextHop IpAddress, ipRouteType INTEGER, ipRouteProto INTEGER, ipRouteAge INTEGER, ipRouteMask IpAddress, ipRouteMetric5 INTEGER, ipRouteInfo OBJECT IDENTIFIER }
Теперь вы можете видеть элементы, из которых состоит каждая строка в таблице. MIB продолжается, описывая эти элементы. Ниже первые два определения для этих элементов:
Рисунок G.3, "Структура ipRouteTable и ее индекс" показывает картину ipRouteTable как часть MIB, чтобы помочь резюмировать всю эту информацию.
Рисунок G.3. Структура ipRouteTable и ее индекс
Как только вы поймете эту часть MIB, следующий шаг, это запрос информации. Этот процесс известен
как "проход таблицы". Большинство SNMP пакетов имеют инструмент командной строки называемый,
примерно как snmptable или snmp-tbl, который будет выполнять этот процесс
для вас, но он может не предлагать необходимого вам избирательного контроля. Например, возможно,
вы не хотите выгружать всю таблицу маршрутизации целиком: вы, возможно, просто хотите получить
список всех значений ipRouteNextHop
. Вдобавок к этому некоторые из Perl SNMP пакетов
не имеют процедур прохода по дереву. Из-за всего выше перечисленного очень полезно знать, как
выполнить эту процедуру вручную.
Чтобы облегчить понимание этого процесса, я покажу вам как выглядит информация, которую мы в конечном счете собираемся получить от устройства. Это позволит вам увидеть, как каждый шаг процесса добавляет дополнительную строку данных, которые мы собираем, к таблице.
default 192.168.1.1 UGS 0 215345 tu0 127.0.0.1 127.0.0.1 UH 8 5404381 lo0 192.168.1/24 192.168.1.189 U 15 9222638 tu0
Здесь показаны маршруты для внутреннего "петлевого" интерфейса по умолчанию и для локальной сети, соответственно.
Теперь посмотрим как действовать чтобы получить подмножество этой информации с использованием инструментов командной строки Net-SNMP. Для этого примера нас интересуют только первые две колонки вывода (назначение маршрута и адрес следующего интервала). В первую очередь мы выполняем начальный запрос к этим двум переменным в таблице. Все, что напечатано утолщенным шрифтом это одна длинная строка команды, здесь она напечатана на отдельных строчках для удобства прочтения:
$ snmpgetnext -v 1 -c public computer \ ip.ipRouteTable.ipRouteEntry.ipRouteDest\ ip.ipRouteTable.ipRouteEntry.ipRouteNextHop ip.ipRouteTable.ipRouteEntry.ipRouteDest.0.0.0.0 = IpAddress: 0.0.0.0 ip.ipRouteTable.ipRouteEntry.ipRouteNextHop.0.0.0.0 = IpAddress: 192.168.1.1
Мы должны обратить внимание на две части ответа на этот запрос. Первая - это актуальные данные: информация, возвращенная после
знака равенства. 0.0.0.0 означает "маршрут по умолчанию", таким образом, возвращенная информация соответствует первой строке вывода таблицы маршрутизации. Вторая важная часть этого ответа, это .0.0.0.0 прикрепленное к именам переменных. Это индекс для записи ipRouteEntry
, представляющий строку таблицы.
Теперь, когда у нас есть первая строка, мы можем выполнить следующий вызов get-next-request
, на этот раз используя индекс.
get-next-request
всегда возвращает следующий пункт в MIB, таким образом, снабдив его индексом строки, мы просто
получаем обратно следующую за ним строку:
$ snmpgetnext -v 1 -c public computer \ ip.ipRouteTable.ipRouteEntry.ipRouteDest.0.0.0.0\ ip.ipRouteTable.ipRouteEntry.ipRouteNextHop.0.0.0.0 ip.ipRouteTable.ipRouteEntry.ipRouteDest.127.0.0.1 = IpAddress: 127.0.0.1 ip.ipRouteTable.ipRouteEntry.ipRouteNextHop.127.0.0.1 = IpAddress: 127.0.0.1
Возможно, вы уже предполагаете следующий шаг. Мы выполняем еще один get-next-request
используя часть 127.0.0.1 (индекс) ответа ip.ipRouteTable.ipRouteEntry.ipRouteDest.127.0.0.1
:
$ snmpgetnext -v 1 -c public computer \ ip.ipRouteTable.ipRouteEntry.ipRouteDest.127.0.0.1 \ ip.ipRouteTable.ipRouteEntry.ipRouteNextHop.127.0.0.1 ip.ipRouteTable.ipRouteEntry.ipRouteDest.192.168.1 = IpAddress: 192.168.1.0 ip.ipRouteTable.ipRouteEntry.ipRouteNextHop.192.168.11.0 = IpAddress: 192.168.1.189
Взглянув на пример вывода netstat, показанный ранее, вы можете увидеть, что мы достигли нашей цели и выгрузили все строки таблицы IP маршрутизации. Возникает вопрос - как бы мы узнали об этом, если бы не видели заранее вывод netstat? В нормальных обстоятельствах мы должны были бы продолжить выполнять запросы как обычно:
$ snmpgetnext -v 1 -c public computer \ ip.ipRouteTable.ipRouteEntry.ipRouteDest.192.168.1.0 \ ip.ipRouteTable.ipRouteEntry.ipRouteNextHop.192.168.1.0 ip.ipRouteTable.ipRouteEntry.ipRouteIfIndex.0.0.0.0 = 1 ip.ipRouteTable.ipRouteEntry.ipRouteType.0.0.0.0 = indirect(4)
И что же мы видим - ответ не соответствует запросу! Мы запрашивали ipRouteDest
и ipRouteNextHop
, но получили в ответ ipRouteIfIndex
и
ipRouteType
. Мы достигли границы таблицы ipRouteTable
. Запрос SNMP get-next-request
выполнил свою неизменную работу и возвратил "первого лексикографического наследника" в MIB для каждого объекта в нашем запросе. Вновь обратившись к описанию ipRouteEntry
, в предыдущей выдержке из RFC 1213, мы можем увидеть, что ipRouteIfIndex(2)
следует за ipRouteDest(1)
, а ipRouteType(8)
, в самом деле, следует за ipRouteNextHop(7)
.
Поэтому ответ на вопрос: "Откуда вы знаете, когда завершать опрос для получения содержимого таблицы?", такой - "Когда вы получили
сообщение о том, что достигнута граница этой таблицы". С точки зрения программы, это транслируется в проверку того, что та же самая строка
или префикс OID, запрошенные вами, возвращаются в ответ на ваш запрос. Например, вы можете убедиться, что все ответы на запрос об ipRouteDest содержат те же ip.ipRouteTable.ipRouteEntry.ipRouteDest
или 1.3.6.1.2.1.4.21.1.1.
Теперь, когда вы обладаете знанием основ SNMP, возможно, вы захотите обратиться к Главе 12, SNMP для того, чтобы посмотреть, как вы можете их использовать с Perl. Также вам необходимо обратить внимание на ссылки, размещенные в конце Главы12, SNMP для получения более подробной информации об SNMP.
[148] Канонический список PDU для SNMPv2 и v3 находится в RFC 3416; он построен на базе списка PDU в SNMPv1 из RFC 1157. Список в RFC не содержит намного больше PDU, чем упоминалось здесь, таким образом, вы упустите не очень многое.
[149] Несколько SNMP-совместимых машин для газированной воды использовались в Интернете, таким образом, все это не так уж и неправдоподобно. Возможно, это покажется вам смешным, но Интернет-тостер (управляемый по SNMP через SLIP соединение) дебютировал в 1990!
[150] RFC 1213 незначительно обновлен в RFC 4293, 4022, и 4113. RFC 3418 добавил в MIB дополнительные пункты SNMPv2.
[151] Эта задача становится даже легче, если вы используете хороший GUI MIB браузер подобный mbrowse или jmibbrowser. Часто вы можете получить большой объем информации о содержимом MIB выполнив snmpwalk на устройстве.
Если вам понравилась эта выдержка, купите копию Автоматизация системного администрирования с использованием Perl, Второе издание.
Авторские права O'Reilly Media, Inc., 2009 г.