Что такое протокол snmp. SNMP: протокол управления сетью

Большинство современных типов сетевого оборудования поддерживает протокол SNMP. Данный стандарт считается очень простым по структуре. Его внедрение осуществить в современных компаний несложно. Управление компьютерами посредством соответствующего протокола может быть осуществлено с применением широкого спектра программных решений. Какие основные возможности имеет SNMP? Каким образом задействуется соответствующий протокол на практике?

Что представляет собой протокол SNMP?

Для начала изучим основные сведения о рассматриваемой технологии. Что это — SNMP? Данная как Simple Network Management Protocol, и означает «Простой протокол сетевого управления». Данный стандарт относится к числу самых распространенных, что задействуются в целях управления различными девайсами в IP-сетях, функционирующих на базе архитектуры TCP/IP. Например, роутерами, коммутаторами, рабочими станциями, сетевыми принтерами.

Рассматриваемый протокол чаще всего применяется в тех случаях, когда инфраструктура предполагает осуществление контроля девайсов, которые подключены к сети, на предмет выполнения условий, заданных администратором. Структура сведений, оборот которых осуществляется в рамках протокола SNMP, включает, в частности, те, что представлены в виде переменных, посредством которых можно описать конфигурацию что находится в сетевой системе. Посредством управляющих приложений соответствующие переменные могут запрашиваться, а в ряде случаев — и задаваться.

Возможности SNMP

Рассматриваемый протокол позволяет осуществлять настройку тех или иных девайсов с помощью главного сервера без обращения к специальным программам, функционал которых рассчитан на мониторинг различных сетевых процессов. С помощью протокола, о котором идет речь, можно осуществлять в ходе администрирования процессов в сети не только управление (SNMP в этом смысле является уникальным инструментом) теми или иными процедурами, но, в частности, также наблюдать за производительностью инфраструктуры, выявлять проблемы, возникающие в ней, осуществлять мониторинг пользования сетевыми ресурсами.

Рассмотрим теперь то, какие ключевые компоненты формируют инфраструктуру сетей, работающих на основе SMTP.

SNMP: основные компоненты

SNMP — протокол, который предполагает задействование нескольких сетевых компонентов. К основным можно отнести:

Управляемый объект — компьютер или приложение, на которое отправляет те или иные команды с использованием протокола, о котором идет речь, администратор сети;

База данных MIB;

Приложение-агент;

Программа-менеджер;

Система обеспечения сетевого взаимодействия.

Управляемый объект может не только получать команды от администратора, но и направлять их — в соответствии с заданными параметрами. Данные с объекта передаются на программу-менеджер, которая по устаноленным алгоритмам интерпретирует их. В свою очередь, на управляемом девайсе функционирует приложение-агент. Оно собирает информацию по соответствующему устройству и при необходимости транслирует ее в формате, адаптированном к специфике протокола SNMP.

Система обеспечения сетевого взаимодействия позволяет администратору работать с несколькими программами-менеджерами в целях осуществления контроля над функционированием инфраструктуры. В сетях может инсталлироваться при этом несколько разновидностей ПО соответствующего типа.

Важнейший, возможно, ключевой элемент протокола SNMP — MIB, или база управляющих сведений. Ее предназначение — в описании структуры данных, обмен которыми осуществляется в процессе управления девайсами. Фактически, соответствующая база данных позволяет разместить информацию, что задействуется для управления устройством, непосредственно на нем, будь то модем, сервер или, к примеру, SNMP — это универсальный протокол, и во многом его функциональность возможно реализовать благодаря, прежде всего, возможностям базы данных MIB.

В девайсах, совместимых с данной технологией, содержатся как стандартные переменные, так и те, что характеризуют особенности отдельного устройства. Основные элементы данной базы — идентификаторы типа OID. Они позволяют устанавливать переменные, которые считываются или же определяются посредством протокола SMNP.

Приложение-агент, являющееся компонентом сетевой инфраструктуры SMNP, обычно получает запросы с использованием порта 161. В свою очередь, программа-менеджер может задействовать любые порты, доступные в сети. При этом уведомления данный тип ПО получает обычно на порт 162.

Рассмотрим основные инструменты, задействуемые администраторами, которые пользуются протоколом SNMP в работе, подробнее. В числе таковых — программа-менеджер.

Программа-менеджер в рамках протокола SNMP: основные возможности

Данный вид ПО позволяет благодаря возможностям рассматриваемого протокола осуществлять управление группами самых разных устройств в рамках сетевой инфраструктуры. Программа, о которой идет речь, может функционировать при условии предварительной инсталляции на девайсах, которые управляются посредством ее интерфейсов, специального приложения-агента, о котором мы сказали выше. Оно передает на сервер администратора необходимые данные с использованием протокола SNMP. В свою очередь, на стороне главного ПК функционирует рассматриваемая программа-менеджер, которая осуществляет обработку сведений, поступающих с управляемых девайсов.

Какое ПО применяется для управления сетью по протоколу SNMP?

Какие конкретно программы могут использоваться в качестве управляющих? В принципе, есть решения, адаптированные к внедрению в самых разных операционных системах протокола SNMP — Windows, Solaris. Если говорить о ПО для Windows, то в числе популярных, работающих в данной ОС и задействующих SNMP, — пакет, выпущенный Castle Rock Computing. В свою очередь, для Solaris разработано другое эффективное решение — Sun NetManager. Посредством обоих вариантов может быть выстроена эффективная базирующаяся на протоколе SNMP карта сети. Кроме того, они позволяют осуществлять прямую коммуникацию с MIB.

В рамках соответствующих интерфейсов можно управлять маршрутизаторами различных брендов, которые поддерживают протокол SNMP, Cisco, в частности. Как правило, современные производители сетевых девайсов выпускают документацию по MIB того или иного устройства, в которой отражаются возможности управления соответствующими компонентами инфраструктуры в рамках сети.

Еще одно популярное решение для управления сетевыми девайсами — Zabbix. SNMP — протокол, который данная программа также задействует. Соответствующее решение обладает большим количеством функций.

В части применения SNMP оно, к примеру, позволяет осуществлять эффективный мониторинг сетевых процессов. Обмен данных в рамках протокола SNMP осуществляется посредством специальных сообщений. Рассмотрим их специфику подробнее.

Особенности SNMP-сообщений

К основным сообщениям, обмен которыми может инициировать посредством протокола SNMP сервер администратора, относятся такие команды, как:

GetNextRequest;

GetBulkRequest;

InformRequest.

Сущность 1-й команды заключается в отправке запроса от программы-менеджера к приложению-агенту в целях получения того или иного значения по переменной — одной или по списку. В свою очередь, программа-менеджер получает ответ с определенными значениями.

Специфика 2-й команды заключается в отправке сообщения также от программы-менеджера к приложению-агенту, но в данном случае в целях корректировки переменной — одной или по списку. Приложение-агент принимает изменения, после чего направляет программе-менеджеру новые значения по тем или иным переменным.

Сущность 3-й команды заключается в отправке запроса от программы-менеджера к приложению-агенту определенных команд в целях обнаружения на девайсе всех доступных переменных, а также значений, которые установлены для них. В свою очередь, приложение-агент возвращает ответ, в котором содержится значение одной переменной, а также ссылка на следующую соотносительно с ее позицией в списке. Следующий запрос предполагает передачу данных, отражающих сведения по следующей переменной, а также ссылку на ту, что идет далее в очереди. В дальнейшем алгоритм оборота данных с использованием рассматриваемой SNMP-команды повторяется.

Специфика 4-й команды заключается в том, что по сути она является модернизированной версией сообщения GetNextRequest. Она предполагает, что приложение-агент передаст программе-менеджеру ответ, содержащий данные по нескольким переменным одновременно, начиная с той, что представлена в изначальном запросе.

Сущность 5-й команды — в осуществлении процедуры возврата связанной переменной, а также значений от приложения-агента к программе-менеджеру при использовании 4 типов сообщений, рассмотренных выше. При этом посредством соответствующей команды между девайсами осуществляется обмен сообщениями об ошибке.

Специфика 6-й команды — в осуществлении передачи сообщений от приложения-агента без предварительного запроса со стороны программы-менеджера. В структуре данного сообщения присутствует текущее значение по переменной. Отметим, что получатель команды в данном случае определяется посредством особых конфигураций в рамках базы MIB.

Сущность 7-й команды заключается в том, что она, фактически, соответствует уведомлению об отправке сообщения от программы-менеджера к приложению-агенту и наоборот. Ее применение обусловлено тем, что в сетевой инфраструктуре те или иные сообщения в ряде случаев могут доставляться некорректно. Команда InformRequest, по сути, подтверждает факт успешной передачи команды от одного девайса к другому.

Корректная настройка SNMP во многих случаях требует от администратора повышенного внимания проверке функциональности базы MIB. Рассмотрим то, в чем заключаются ее особенности.

MIB: особенности функционирования базы

Ключевая процедура в рамках функционирования базы MIB — адресация переменных. Осуществляется она с учетом структуры рассматриваемого компонента протокола SNMP. Выглядит база MIB как древообразная схема, состоящая из нескольких элементов, к каждому из которых прикреплен особый идентификатор.

Имя переменной в рамках базы MIB отражает адрес до нее, начиная от корневого каталога. В структуре переменной могут содержаться самые разные сведения, например, о времени работы девайса. В древообразной структуре MIB могут присутствовать как стандартные ветви, которые поддерживаются большинством девайсов, или же те, что добавлены производителем устройства либо организацией, в которой внедряется инфраструктура компьютерной сети. Главное в данном случае — правильно разместить соответствующие наборы переменных.

Так, если они внедряются в структуру MIB временно, то их имеет смысл разместить в разделе experimental. Непосредственно перед утверждением следует присвоить набору переменных отдельный номер. Для этого используется раздел private-enterprises. Это позволит инженерам или администраторам сети, в компетенции которых — SNMP-мониторинг и решение других задач по обеспечению функционирования инфраструктуры, открыть новую ветвь в структуре MIB для того, чтобы размещать переменные только от своей компании.

История появления SMNP

Интересно будет изучить сведения об истории разработки SNMP. Основная программная среда, в которой сейчас задействуется протокол SNMP — Windows. Однако, инициирована была его разработка еще в 1988 году - задолго до того, как операционная система от Microsoft, представленная в привычных интерфейсах, начала завоевывать рынки. Фактически, изначально SNMP разрабатывался для UNIX — семейства операционных систем, предназначенных для решения широкого круга задач по обеспечению функциональности различных компьютерных сетей. Хотя, безусловно, к тому моменту многие эксперты видели потенциал Windows, и не исключено, что разработка универсального сетевого протокола была во многом предопределена фактом потенциального роста популярности новой операционной системы.

Безусловно, был еще один фактор, сыгравший важную роль в ускорении работы над SNMP, — Web. Уже тогда появились первые онлайн-сервисы, и экспертам было понятно, что впереди — активная интеграция сетевых интерфейсов в мировом масштабе.

Так или иначе, крупнейшие производители сетевых девайсов в 1988 году решили, что им необходимо разработать универсальный набор средств, предназначенных для управления устройствами. К тому моменту фирмы выпускали собственные решения для осуществления мониторинга, а также конфигурирования девайсов. Нужна была унификация.

Разработка SNMP: основные инструкции

В августе 1988 года предприятия, выпускающие сетевое оборудование, пришли к консенсусу. В процессе разработки нового протокола были применены некоторые уже действовавшие концепции. Специалисты, которые проводили совместную работу, выявили 3 ключевых документа: RFC 1065, 1066, а также 1067. Впоследствии они были дополнены, и появились новые — RFC 1155, 1156, а также 1157. Данные источники были переработаны, и в 1991 году на их основе была выпущена первая версия протокола SNMP.

Так, документ RFC 1155 содержал в себе инструкции, определяющие:

То, в какой структуре должна отражаться управляющая информация;

То, каковы основные принципы применения синтаксиса при определении имен для переменных.

Документ RFC 1155 был дополнен источником RFC 1212 в части, опять же, синтаксиса переменных. На момент утверждения протокола SMNP был разработан ряд новых документов, таких как RFC 1213. В нем отражался список ключевых переменных, посредством которых должна была осуществляться конфигурация сетевой инфраструктуры.

Источник RFC 1157 содержал параметры, необходимые для:

Определения команд, посредством которых сервер и управляемый объект могли взаимодействовать между собой;

Осуществления обмена trap-сообщениями.

Как только был опубликован и введен протокол SNMP, адаптер, сервер — в принципе, любой девайс, который входил бы в инфраструктуру сети, мог становиться объектом управления, осуществляемого в рамках стандартных процедур. Введение SNMP стало сильнейшим фактором роста мирового рынка сетевого оборудования. Также благодаря стандартизации стало возможным внедрение в самых широких масштабах новых интерфейсов, таких как, например, Ethernet, FDDI.

Резюме

Итак, что это — SNMP, мы узнали. Данная аббревиатура соответствует одному из ключевых сетевых протоколов, которые используются в целях поддержания функциональности современных компьютерных сетей. Данный протокол предполагает осуществление между различными элементами инфраструктуры — управляющими серверами и управляемыми девайсами, обмена стандартизованными сообщениями. При этом производится обращение к базе данных MIB того или иного устройства.

Посредством стандартизованных сообщений в рамках протокола SNMP осуществляются:

Запросы одного или нескольких параметров MIB;

Последовательное прочтение различных значений по тем или иным параметрам, например, табличным;

Установка конкретных значений для одной или же нескольких переменных MIB;

Возврат девайсом ответа на тот или иной запрос другого устройства;

Отправка уведомительных сообщений о тех или иных сетевых процессах.

Алгоритмы MIB могут быть как общие для всех девайсов, так и те, что прописываются производителями для конкретных типов сетевого оборудования.

Что это — SNMP с точки зрения значения для современного IT-рынка? Данная технология, очевидно, в числе важнейших, и во многих случаях не имеющая альтернативы. И это несмотря на ее простоту, которая, однако, стала результатом многолетних разработок и согласований сетевых стандартов при участии ведущих производителей оборудования.

Сетевые коммуникации, в рамках которых задействуются возможности протокола MIB, предполагают использование программ-менеджеров, а также приложений-агентов. Первые направляют различные команды вторым, после чего программное обеспечение девайса осуществляет выполнение определенных алгоритмов. Также осуществляется передача данных по установленным схемам от приложения-агента к программе-менеджеру.

Управление компьютерами сети может осуществляться с главного сервера. Для этого может быть задействована специальная программа, например, Zabbix. SNMP — протокол, поддерживаемый программами, способными работать в разных операционных системах. Изначально SNMP разрабатывался для UNIX, но были созданы виды ПО, которые позволили его применять в ОС Windows, Sun Solaris.

Таким образом, что это — SNMP? Международный стандарт, позволяющий, прежде всего, интегрировать решения от разных производителей. Изначально алгоритмы управления ими бренды задавали свои собственные. Но благодаря разработке SNMP у них появилась возможность задействовать унифицированные команды, что стимулировало спрос на выпускаемые сетевые девайсы, стало эффективным драйвером роста рынка соответствующего типа оборудования.

Уже немало написано о том, что в названии Simple Network Management Protocol слово Simple можно смело писать в кавычках. Протокол SNMP является достаточно простым с точки зрения создания SNMP-агентов, однако на стороне управляющего ПО (SNMP manager) грамотная обработка сложных по структуре данных обычно является нетривиальной задачей.

Мы попытались упростить процесс настройки сбора данных и событий SNMP и позволить пользователям во время этого процесса:

  • Никогда не заглядывать внутрь MIB-файлов
  • Не знать, что такое OID-ы и никогда не оперировать с ними
  • Не пользоваться отдельной SNMP-утилитой для предварительного просмотра данных во время настройки

Шаг 1: добавляем MIB-файлы

Прежде всего необходимо разобраться с MIB-файлами. Описание логики связей между элементами данных и их синтаксиса было в SNMP реализовано при помощи этих файлов с целью уменьшения нагрузки на сеть и упрощения реализации агентов. Пользователи, однако, далеко не всегда хотят разбираться с их внутреннем устройстве.

Модуль SNMP нашей системы AggreGate Network Manager при старте загружает все MIB-файлы, находящиеся в специальной папке сервера, после чего позволяет добавлять новые при помощи простого диалога:

Во время загрузки файлов происходит их автоматическая компиляция. Встроенный редактор MIB-ов с подсветкой синтаксиса имеется лишь на случай появления MIBов, не соответствующих спецификации. Пользоваться им нужно крайне редко.

Редактор MIB-ов



На этом работа с MIB-файлами заканчивается, дальше их названия используются только для логической группировки уже собранных данных. При необходимости, загруженные файлы можно посмотреть и поискать в таблице MIBов, но при обычной работе это также не требуется.

Таблица MIB-ов


Шаг 2: подключаем SNMP-устройство

В случае построения классической системы мониторинга этот шаг обычно не требуется, так как все устройства добавляются в систему автоматически во время периодического обнаружения устройств (network discovery). Тем не менее, во время добавления обнаруженных сканированием сети устройств выполняются примерно те же шаги:

Шаг 3: изучаем снимок устройства

После завершения этапа подключения устройства системе требуется от нескольких секунд до нескольких минут на завершение опроса устройства в рамках выбранных MIB-ов. Когда пиктограмма устройства становится зеленой, можно открывать и изучать так называемый «снимок устройства»:

В этом снимке сосредоточена практически вся суть нашего подхода к работе с данными SNMP. Прежде всего, он всегда содержит «под рукой» все реальные данные устройства. При этом все данные считываются только один раз, последующий опрос идет только по важным метрикам. Полное перечитывание снимка устройства производится раз в сутки, для снижения нагрузки на сеть его можно вообще отключить. Снимок устройства опционально сохраняется в БД при перезапуске системы мониторинга.

Обычно не требуется прибегать к помощи каких-либо внешних утилит когда требуется найти подходящие данные для мониторинга по их описаниям в MIB-файле или значениям. Все данные уже сгруппированы по MIB-файлам, однако можно сгруппировать их и по иерархии OID-ов:

Чтобы посмотреть подробное описание любой метрики или таблицы, содержащееся в MIB-файле, достаточно навести мышкой на описание или значение метрики. Во всплывающей подсказке также виден тип данных SNMP и полный OID:

Если метрика может принимать одно из нескольких числовых значений, описанных в MIB-файле текстовыми константами, в снимке устройства сразу показывается соответствующая текущему значению константа. Полный список констант и их числовых значений доступен через контекстное меню:

При этом текущее числовое значение всегда можно посмотреть во всплывающей подсказке. Для редактируемых метрик все еще проще, можно выбрать константу и посмотреть ее значение прямо в выпадающем списке:

Но наибольшую пользу наш метод работы с данными SNMP приносит при обработке таблиц. Каждая SNMP-таблица показывается в снимке устройств как отдельная метрика табличного типа:

Редактирование данных в таблицах можно производить прямо по время просмотра, например для отключения сетевого интерфейса достаточно поменять значение поля ifAdminStatus в соответствующей строке.

При наведении на заголовок столбца во всплывающей подсказке видно описание поля, полученное из MIB-файла, а также его тип и OID:

Если имеется несколько связанных друг с другом таблиц, например использующих внешние индексы или расширение (augmentation), система автоматически обрабатывает все внутренние связи и сводит данные связанных таблиц в одно целое. В большинстве случаев пользователи даже не подозревают о существовании таких сложностей. Вот, например, как выглядит таблица hrSWRunPerfTable :

На уровне MIB файла эта таблица представляет из себя два столбца (hrSWRunPerfCPU и hrSWRunPerfMem ), расширяющие таблицу hrSWRunTable . В снимке устройства эти таблицы уже объединены, что облегчает анализ данных, построение отчетности и диаграмм, настройку хранения и т.д.

Поскольку единая модель данных платформы AggreGate ориентирована на работу с таблицами, таблицы данных SNMP являются идеальным кандидатом на обработку встроенными средствами. При помощи них реализуется построение топологии L2/L3, анализ данных MPLS TE и MPLS VPN, мониторинг и создание тестов IP SLA, а также сотни более простых задач.

Шаг 4: настраиваем периоды опроса и сроки хранения

AggreGate Network Manager является , поэтому в большинстве случаев после автоматического или ручного добавления устройства периоды опроса и сроки хранения метрик уже преднастроены для всех метрик и таблиц, которые система «понимает», т.е. показывает на инструментальных панелях и анализирует на предмет необходимости генерации тревожных сообщений.

Откорректировать настройки опроса (синхронизации) и хранения метрики можно через ее контекстное меню, либо через настройки аккаунта (для всех метрик сразу).

Настройки опроса и хранения


В диалоге настроек хранения показывается только срок хранения «сырых» данных в обычной базе данных (реляционной или NoSQL, в зависимости от настроек сервера). В большинстве случаев данные SNMP хранятся в кольцевой базе данных (Round-Robin Database, RRD), которая встроена в платформу AggreGate. На тему создания каналов статистики , которые перекладывают метрики и части таблиц в кольцевую БД, будет отдельная статья.

Шаг 5: переходим к обработке и визуализации данных

Когда данные собираются и сохраняются в БД сервера, можно приступать к их использованию для дела, то есть для мониторинга и управления ИТ инфраструктурой. Контекстное меню любой метрики в снимке устройства предоставляет доступ к визардам, позволяющим начать настройку тревог, отчетов, графиков, запросов, инструментальных панелей, и других средств анализа и визуализации.

При помощи этих средств настраивается влияние метрик и таблиц на общесистемные операции поиска причин отказов, анализа производительности, планирования и инвентаризации, управления конфигурациями, и других функций системы. Попутно «рисуются» различные интерфейсы:

В результате

Описанный выше процесс может показаться сложным из-за множества упомянутых подробностей, однако на практике от момента подключения абсолютно нового устройства до появления его специфических данных на стандартных инструментальных панелях проходит всего несколько минут. За это время выход из нашей системы требуется лишь на время поиска специфических MIB-файлов на сайте производителя подключаемого оборудования.

При настройке мониторинга не требуется ручное указание названий MIB-ов, ввод OID-ов и других низкоуровневых идентификаторов. Это делает настройку SNMP-мониторинга достаточно быстрой и легкой.

Безусловно, нам еще есть над чем поработать. Требуется улучшение механизмов выбора индивидуальных метрик, чтобы избежать даже единократного опроса целых MIBов. Есть необходимость исключения из опроса индивидуальных строк и столбцов SNMP-таблиц. Нам интересно было бы услышать и о других недостатках процесса настройки SNMP-мониторинга в нашей системе.

А поподробнее?

Эта статья вообще не касается получения, обработки и отправки ловушек SNMP, работы по SNMP v3, и многих других аспектов.

Для более подробного рассказа мы приглашаем всех хабражителей на вебинар Мониторинг и управление по SNMP , который состоится 26 мая 2015 года в 11:00 по московскому времени. На этом вебинаре мы «вживую» продемонстрируем весь вышеописанный процесс, а также многие другие способы мониторинга сетевого, серверного и нестандартного оборудования при помощи SNMP.

Стратегия SNMP заключается в том, что мониторинг состояния сети с любым значимым уровнем детализации выполняется главным образом путем опроса из центра мониторинга. Ограниченное число незапрашиваемых сообщений (trap - прерывание) обеспечивает синхронизацию и активизирует опросы. Ограничение числа незапрашиваемых сообщений согласуется с задачами обеспечения простоты и минимизации трафика, создаваемого системой сетевого управления.

Из этих цитат, вполне понятно, что запросы с типами TRAP и INFORM это не наиболее часто используемая часть SNMP. Статью для начинающих было бы более уместно иллюстрировать примерами использования гораздо более ходовых GET-запросов.

Вообще я настоятельно рекомендую ознакомиться со всеми RFC, связанными с SNMP перед началом работы. Некоторые аспекты SNMP не очевидны и имеет смысл получить о них представление из первоисточника. Начать ознакомление с материалом можно с wiki .

Первые шаги

Помимо обязательного ознакомления с документацией, важно понимать, для чего мы все это делаем. В практике телекома, наиболее часто встречаются следующие задачи:
  1. Опрос оборудования по SNMP (аккаунтинг, мониторинг)
  2. Управление оборудованием по SNMP (активация)
Задачи, связанные с опросом оборудования сводятся к формированию GET (и как будет показано далее GETNEXT) запросов. Управление оборудованием сводится к отсылке SET-запросов, изменяющих состояние соответствующих переменных на оборудовании (например, таким образом, можно отключить какой либо интерфейс).

Задача SNMP-мониторинга выделяется на общем фоне требованием того, что опрашиваемого оборудования много или очень много. Предположим, что именно эту задачу нам и предстоит решать.

Начнем писать код. В тестовом примере мы обратимся по SNMP к собственному хосту и прочитаем значение переменной, заданной OID-ом 1.3.6.1.2.1.1.3.0 и содержащей значение uptime-а хоста:

Одиночный GET-запрос

package com.acme.ae.tests.snmp; import java.io.IOException; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private Snmp snmp = null; private TransportMapping transport = null; private void test() throws IOException { Target t = getTarget("udp:127.0.0.1/161"); String r = send(t, "1.3.6.1.2.1.1.3.0"); System.out.println(r); } private String send(Target target, String oid) throws IOException { PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(oid))); pdu.setType(PDU.GET); ResponseEvent event = snmp.send(pdu, target, null); if (event != null) { return event.getResponse().get(0).toString(); } else { return "Timeout exceeded"; } } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version1); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } }


Предварительно убедившись, что служба SNMP на нашем хосте работает и запустив код на выполнение, получим искомое значение uptime-а (времени безостановочной работы хоста с момента последней загрузки):

1.3.6.1.2.1.1.3.0 = 2:28:55.06
Используя это значение, можно осуществлять мониторинг. Если мы обнаруживаем, что значением уменьшилось - значит хост успел перезагрузиться с момента очередного опроса. Если хост не ответил в течение заданного таймаута (после нескольких автоматически сделанных попыток) это, скорее всего, означает, что хост не работает. Все просто?

Подсчитали - прослезились

Не совсем. Вспоминаем о том, что нам предстоит выполнять много запросов. Давайте промеряем, сколько запросов мы можем выполнить в секунду? Внесем небольшое исправление в код:

Private void test() throws IOException { Target t = getTarget("udp:127.0.0.1/161"); Long timestamp = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { send(t, "1.3.6.1.2.1.1.3.0"); } System.out.println(1000000L /(System.currentTimeMillis() - timestamp)); }
И запустим его на выполнение:

2463
Почти две с половиной тысячи запросов в секунду! Неплохо?

Не будем торопиться. Мы отправляем запросы на Loopback интерфейс, а он работает несколько быстрее локальной сети. Посмотрим, сколько запросов в секунду мы успеем выполнить к другому хосту в нашей сети:

182
Не дотягиваем даже до двухсот. Вообще говоря, возможно, этого будет достаточно. Все зависит от задачи. Но мы проводили измерения при условии, что опрашиваемый хост доступен. Что будет если хост не ответит?

Будет несколько попыток доступа (в нашем коде мы задали 3) разделенных таймаутом (1000 мсек). Это означает, что за секунду мы не успеем выполнить ни одного запроса. Поскольку не отвечающий хост является не такой уж большой редкостью, это может стать большой проблемой в реальном проекте.

Идем на рекорд

Что с этим можно сделать? Если бы мы имели дело с каким либо синхронным протоколом (например telnet), особого выбора бы у нас не было. Для того, чтобы увеличить производительность, нам пришлось бы одновременно выполнять много потоков. Но SNMP асинхронен по своей природе! Не надо насильственно втискивать его в синхронные рамки.

Как перейти к асинхронному варианту? В нашем случае, довольно просто:

Асинхронные запросы

package com.acme.ae.tests.snmp; import java.io.IOException; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test implements ResponseListener { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private Snmp snmp = null; private TransportMapping transport = null; public void onResponse(ResponseEvent event) { PDU response = event.getResponse(); if (response != null) { System.out.println(response.get(0).toString()); return; } } private void test() throws IOException { Target t = getTarget("udp:192.168.131.253/161"); Long timestamp = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { send(t, "1.3.6.1.2.1.1.3.0"); } System.out.println(1000000L /(System.currentTimeMillis() - timestamp)); } private void send(Target target, String oid) throws IOException { PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(oid))); pdu.setType(PDU.GET); snmp.send(pdu, target, null, this); } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version1); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } }


7142
Запросы все равно что проваливаются в бездонную бочку! Разумеется, ответы будут приходить с задержкой, но приходить они будут тоже довольно быстро. Но как мы узнаем, что хост не ответил?

Очень просто, по истечении заданного количества попыток и таймаутов, SNMP4J вернет нам event, response в котором будет равен null:

Исправленный вариант

requests = new HashSet(); private Long firstTimestamp = null; private long lastTimestamp; public void onResponse(ResponseEvent event) { Integer32 requestId = event.getRequest().getRequestID(); PDU response = event.getResponse(); if (response != null) { lastTimestamp = System.currentTimeMillis(); if (firstTimestamp == null) { firstTimestamp = lastTimestamp; } return; } else { synchronized (requests) { if (requests.contains(requestId)) { System.out.println("Timeout exceeded"); } } } synchronized (requests) { requests.remove(requestId); } } private void test() throws IOException { Target t = getTarget("udp:192.168.131.253/161"); Long timestamp = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { send(t, "1.3.6.1.2.1.1.3.0"); } System.out.println(1000000L /(System.currentTimeMillis() - timestamp)); while (!requests.isEmpty()) { try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } } if (firstTimestamp != null) { System.out.println(1000000L /(lastTimestamp - firstTimestamp)); } } private void send(Target target, String oid) throws IOException { PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(oid))); pdu.setType(PDU.GET); snmp.send(pdu, target, null, this); synchronized (requests) { requests.add(pdu.getRequestID()); } } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version1); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } }


Проанализируем результат выполнения:

9174 283
Мы успеваем сформировать 9174 запросов в секунду, а опрашиваемое устройство успевает обрабатывать запросы со скоростью 283 запроса в секунду. На большую часть запросов оно ответить не успевает (соответственно в логе остаются сообщения «Timeout exceeded»). Разумеется, это не будет проблемой когда мы начнем опрашивать большое количество устройств с разумным интервалом между запросами.

Идем далее

Мы научились получать по SNMP значения скалярных переменных. Но, помимо них, в SNMP есть еще и таблицы (например таблица интерфейсов на устройстве). Как они устроены? Посмотрим MIB-browser:

В OID mgmt.interfaces (1.3.6.1.2.1.2) мы видим скалярную переменную ifNumber (1.3.6.1.2.1.2.1), содержащую количество интерфейсов в таблице, а также набор столбцов. Каждый из столбцов имеет собственный OID. Например столбец содержащий числовой индекс ifIndex интерфейса имеет OID = 1.3.6.1.2.1.2.2.1.1.

Для того, чтобы получить значение этой переменной, необходимо добавить к OID-у индекс интерфейса (например для интерфейса с индексом 123 OID = 1.3.6.1.2.1.2.2.1.1.123). Но как нам получить индексы интерфейсов? Они совсем не обязательно идут по порядку! Например, на моей машине, таблица интерфейсов выглядит так:

Именно для этой цели был придуман запрос GETNEXT. Передавая в этот запрос префикс OID-а, мы получаем OID и значение следующей (в лексикографическом порядке) за этим префиксом переменной. Это означает, что передав префиксы OID-ов столбцов таблицы, мы получим OID-ы и значения первой ее строки. Чтобы получить следующую строку, надо выполнить еще один запрос, передав в него OID-ы, полученные предыдущим запросом. И так до тех пор, пока мы не просмотрим всю таблицу.

Разумеется, с учетом всего сказанного выше, нам следует минимизировать количество запросов (это также необходимо с учетом того, что в рамках одного запроса, согласно RFC, предоставляются консистентные данные, если мы запросим индекс и имя интерфейса двумя последовательными запросами, они возможно не будут соответствовать друг-другу). В рамках 1-ой версии SNMP, мы должны читать всю строку таблицы одним запросом.

Следует заметить, что довольно удобно то, что OID-ы скалярных переменных также представляют собой префиксы. Например, для переменной sysUpTime OID, на самом деле равен 1.3.6.1.2.1.1.3. Мы можем передать его в GETNEXT запрос и получить OID = 1.3.6.1.2.1.1.3.0 вместе с соответствующим значением. Это дает возможность запрашивать скалярные значения вместе с значениями столбцов таблиц, в одном запросе.

Просмотр первой строки таблицы

package com.acme.ae.tests.snmp; import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test implements ResponseListener { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private Snmp snmp = null; private TransportMapping transport = null; private Set requests = new HashSet(); public void onResponse(ResponseEvent event) { Integer32 requestId = event.getRequest().getRequestID(); PDU response = event.getResponse(); if (response != null) { System.out.println(response.toString()); return; } else { synchronized (requests) { if (requests.contains(requestId)) { System.out.println("Timeout exceeded"); } } } synchronized (requests) { requests.remove(requestId); } } private void test() throws IOException { Target t = getTarget("udp:127.0.0.1/161"); send(t, new String {"1.3.6.1.2.1.1.3", "1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2"}); } private void send(Target target, String oids) throws IOException { PDU pdu = new PDU(); for (String oid: oids) { pdu.add(new VariableBinding(new OID(oid))); } pdu.setType(PDU.GETNEXT); ResponseEvent event = snmp.send(pdu, target, null); synchronized (requests) { requests.add(pdu.getRequestID()); } onResponse(event); } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version1); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } }


Запустив этот код на выполнение, мы получим следующий response:

RESPONSE]
Мы получили значение uptime-а, индекс первого интерфейса и его имя, закодированное строкой октетов в шестнадцатеричном представлении. Чтобы получить следующие строки, мы должны выполнять последовательные запросы, передавая ранее полученные OID-ы.

С учетом необходимости поддержки возможности асинхронной обработки, это может стать нетривиальной (но вполне решаемой) задачей. К счастью, во 2-ой версии SNMP были добавлены bulk-запросы, автоматизирующие получение табличных данных и минимизирующие количество отсылаемых при этом запросов. Внесем необходимые изменения в код:

BULK-запрос

package com.acme.ae.tests.snmp; import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.Target; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class Test implements ResponseListener { private final static String SNMP_COMMUNITY = "public"; private final static int SNMP_RETRIES = 3; private final static long SNMP_TIMEOUT = 1000L; private final static int BULK_SIZE = 50; private Snmp snmp = null; private TransportMapping transport = null; private Set requests = new HashSet(); public void onResponse(ResponseEvent event) { Integer32 requestId = event.getRequest().getRequestID(); PDU response = event.getResponse(); if (response != null) { System.out.println(response.toString()); return; } else { synchronized (requests) { if (requests.contains(requestId)) { System.out.println("Timeout exceeded"); } } } synchronized (requests) { requests.remove(requestId); } } private void test() throws IOException { Target t = getTarget("udp:127.0.0.1/161"); send(t, new String {"1.3.6.1.2.1.1.3", "1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2"}); } private void send(Target target, String oids) throws IOException { PDU pdu = new PDU(); for (String oid: oids) { pdu.add(new VariableBinding(new OID(oid))); } pdu.setType(PDU.GETBULK); pdu.setMaxRepetitions(BULK_SIZE); pdu.setNonRepeaters(1); ResponseEvent event = snmp.send(pdu, target, null); synchronized (requests) { requests.add(pdu.getRequestID()); } onResponse(event); } private Target getTarget(String address) { Address targetAddress = GenericAddress.parse(address); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(SNMP_COMMUNITY)); target.setAddress(targetAddress); target.setRetries(SNMP_RETRIES); target.setTimeout(SNMP_TIMEOUT); target.setVersion(SnmpConstants.version2c); return target; } private void start() throws IOException { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } private void stop() throws IOException { try { if (transport != null) { transport.close(); transport = null; } } finally { if (snmp != null) { snmp.close(); snmp = null; } } } public static void main(String args) { Test t = new Test(); try { try { t.start(); t.test(); } finally { t.stop(); } } catch (IOException e) { System.out.println(e.toString()); } } }


Выполнив этот запрос, мы получаем все строки таблицы одним запросом:

Много данных

RESPONSE]


Разумеется, если таблица содержит более затребованных 50-ти строк, вновь (как и для 1-ой версии SNMP) потребуется формировать запросы для получения последующих строк, передавая в них OID-ыполученные для последней строки.

О чем я не рассказал?

В этой статье я не рассказал о многом. Я не рассказал о том, как изменять значения некоторых (не всех) переменных SET-запросами. Я не рассказал о том, что такое TRAP-ы и для чего они нужны. Я ни сказал ни слова о том, как разрабатывать SNMP-агенты. И я ни одним словом не обмолвился о 3-ей версии SNMP и привнесенных ей изменениях.

Но даже того о чем я сказал вполне достаточно, чтобы понять, что SNMP - это не просто.

Введение

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

Управление сетью в объединенных сетях TCP/IP строится на взаимодействии между станцией управления сетью (менеджер) и элементами сети. Элементами сети могут быть любые объекты, которые используют семейство протоколов TCP/IP: хосты, маршрутизаторы, X терминалы, терминальные сервера, принтеры и так далее. На элементах сети должно быть запущено программное обеспечение, которое называется агентом. Станции управления это обычно рабочие станции с цветным монитором и графическим дисплеем, которые отображают то, что происходит с элементами (которые из них работают, а которые нет, объем траффика по различным каналам за единицу времени и так далее).

Обмен данными, как правило, двусторонний: менеджер просит агента сообщить ему определенное значение (например, "сколько было сгенерировано ICMP ошибок о недоступности порта?"), или агент сообщает менеджеру о каком-либо важном событии ("подключенный интерфейс не работает"). У менеджера должна быть возможность установить переменные в агенте ("измени значение TTL по умолчанию на 64"), помимо того, что менеджер должен иметь возможность считывать переменные от агента.

Управление сетями TCP/IP состоит из трех частей.

  1. Информационная база управления (MIB - Management Information Base), которая указывает, какие переменные в элементах сети необходимо обслуживать (информация, которая может быть запрошена и установлена менеджером). RFC 1213 определяет вторую версию, которая называется MIB-II.
  2. Установка общей структуры и схемы идентификации, используемой для обращения к переменным в MIB. Это называется структурой информации управления ( SMI - Structure of Management Information) и описывается в RFC 1155 . Например, SMI указывает, что счетчик (Counter) это неотрицательное целое число, которое изменяется от 0 до 4294967295 и затем снова возвращается в 0.
  3. Протокол, который функционирует между менеджером и элементом, называется простым протоколом управления сетью ( SNMP - Simple Network Management Protocol). RFC 1157 [ Case et al. 1990] описывает этот протокол. Там же подробно описан формат пакетов, с помощью которых осуществляется обмен. Несмотря на то, что в качестве транспортных протоколов могут быть использованы разные протоколы, обычно с SNMP используется UDP.

Эти RFC определяют то, что в настоящее время называется SNMPv1, или просто SNMP, что мы и обсудим в этой главе. В течение 1993 года были опубликованы дополнительные RFC, которые описывают SNMP Version 2 (SNMPv2), который мы опишем в разделе этой главы.

В этой главе мы рассмотрим протокол, который используется для общения между менеджером и клиентом, во-первых, а затем посмотрим какие переменные использует агент. Мы опишем информационную базу данных, поддерживаемую агентом (MIB), рассмотрим группы, которые мы уже описали в тексте: IP, UDP, TCP и так далее. Рассмотрим примеры, соответствующие каждому описанию, а в процессе рассмотрения будем обращаться к концепции протоколов, описанных в предыдущих главах.

Протокол

SNMP определяет всего пять типов сообщений, которыми обмениваются менеджер и клиент.

Получить значение одной или нескольких переменных: оператор get-request. Получить следующую переменную после этой или несколько указанных переменных: оператор get-next-request. (Мы опишем то, что имеем в виду под словом "следующий" позже в этой главе.) Установить значение одной или нескольких переменных: оператор set-request. Выдать значение одной или нескольких переменных: оператор get-response. Это сообщение возвращается агентом менеджеру в ответ на операторы get-request, get-next-request и set-request. Уведомить менеджера, когда что-либо произошло с агентом: оператор trap.

Первые три сообщения отправляются от менеджера к агенту, а последние два от агента к менеджеру. (Мы будем называть первые три оператора как get, get-next и set.) На рисунке 25.1 приведены все пять операторов.

Так как четыре из пяти SNMP сообщений реализуются простой последовательностью запрос-отклик (менеджер отправляет запрос, а агент возвращает отклик), SNMP используют UDP. Это означает, что запрос от менеджера может не прибыть к агенту, а отклик от агента может не прибыть к менеджеру. В этом случае менеджер, возможно, отработает тайм-аут и осуществит повторную передачу.

Рисунок 25.1 Пять операторов SNMP.

Менеджер отправляет эти три запроса на UDP порт 161. Агент отправляет ловушки (trap) на UDP порт 162. Так как используются два разных порта, одна система может выступать в роли менеджера и агента одновременно. (См. в конце главы.)

На рисунке 25.2 показан формат пяти SNMP сообщений, инкапсулированных в UDP датаграмму.

Рисунок 25.2 Формат пяти SNMP сообщений.

На этом рисунке мы указали в байтах только размер IP и UDP заголовков. Это объясняется тем, что для SNMP сообщений используется кодирование - называемое ASN.1 и BER, которые мы опишем позже в этой главе - в зависимости от типа переменных и их значений.

Значение поля version равно 0. Это значение в действительности равно номеру версии минус единица. (Версия SNMP, которую мы описываем, называется SNMPv1.)

На рисунке 25.3 показано значение для типа блока данных протокола (PDU type). ( PDU - это блок данных протокола - Protocol Data Unit, обычно называемый "пакет".)

get-request
get-next-request
set-request
get-response
trap

Рисунок 25.3 Типы PDU сообщений SNMP.

Сообщество (community) это строка символов, в которой содержится пароль в открытом виде. Пароль используется при общении между менеджером и агентом. Обычное значение - 6-символьная строка public.

В операторах get, get-next и set менеджер устанавливает идентификатор запроса (request ID), который возвращается агентом в сообщении get-response. Мы видели этот тип переменной в других UDP приложениях. (Вспомните поле идентификации (identification) DNS на и поле идентификатора транзакции (transaction ID) на .) Это позволяет клиенту (менеджеру в данном случае) сопоставить отклики от сервера (агент) с запросами, которые были отправлены клиентом. Это поле также позволяет менеджеру выдать несколько запросов одному или нескольким агентам, а затем отсортировать полученные отклики.

Статус ошибки (error status) это целое число, которое возвращается агентам и указывает на ошибку. На рисунке 25.4 показаны значения, имена и описания ошибок.

статус ошибки

Описание

noError все в порядке
tooBig клиент не может поместить отклик в одно SNMP сообщение
noSuchName оператор указывает на несуществующую переменную
badValue в операции установки использовано недопустимое значение или сделана ошибка в синтаксисе
readOnly менеджер попытался изменить переменную, которая помечена как "только для чтения"
genErr неопознанная ошибка

Рисунок 25.4 Значения статуса ошибки SNMP.

Если возникла ошибка, индекс ошибки (error index) это целое смещение, указывающее на то, в какой переменной произошла ошибка. Это значение устанавливается агентом только для ошибок noSuchName (нет такого имени), badValue (неверное значение) и readOnly (только для чтения).

Список имен переменных и значений следует в get, get-next и set запросах. Раздел значений игнорируется в операторах get и get-next.

Для оператора trap (PDU type равен 4) формат SNMP сообщения изменяется. Мы опишем поля заголовка ловушки, когда будем описывать этот оператор в разделе этой главы.

Структура управляющей информации

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

  • INTEGER (целое число). Некоторые переменные объявляются как целые без ограничений (например, MTU для интерфейса), некоторые определены с конкретными значениями (например, флаг IP о перенаправлении установлен в 1, если перенаправление включено, или в 2, если перенаправление выключено), а другие определены с их минимальными и максимальными значениями (например, номера портов TCP и UDP находятся в диапазоне от 0 до 65535).
  • OCTET STRING (восьмеричная строка). Строка из 0 или нескольких 8-битных байт. Каждый байт имеет значение от 0 до 255. В кодировании BER, используемом для этих типов данных и для следующего, счетчик количества байт в строке находится перед самой строкой. Эти строки не заканчиваются нулевыми значениями.
  • DisplayString. Строка из 0 или нескольких 8-битных байт, причем каждый байт должен быть символом из набора ASCII NVT . Все переменные этого типа в MIB-II должны содержать не больше чем 255 символов. (Строка нулевой длины допустима.)
  • OBJECT IDENTIFIER (идентификатор объекта). Мы опишем их в следующем разделе.
  • NULL (ноль). Означает, что у соответствующей переменной нет значения. Используется, например, в качестве всех значений для переменных в запросах get или get-next, пока эти переменные запрашиваются, а не устанавливаются.
  • IpAddress (IP адрес). OCTET STRING (восьмеричная строка) длиной 4, с 1 байтом на каждый байт IP адреса.
  • PhysAddress (физический адрес). OCTET STRING (восьмеричная строка), содержит физический адрес (например, 6-байтный Ethernet адрес).
  • Counter (счетчик). Неотрицательное целое число, значение которого увеличивается монотонно от 0 до значения 232-1 (4.294.967.295) и затем вновь возвращается в 0.
  • Gauge (критерий). Неотрицательное целое число в диапазоне от 0 до 232-1, значение которого может увеличиваться или уменьшаться, однако изменения прекращаются по достижении максимального значения. Это означает, что если значение достигнет величины 232-1, критерий будет оставаться в этом значении до тех пор, пока не будет сброшен. Примером может служить переменная MIB tcpCurrEstab: это количество TCP соединений, находящихся в настоящий момент в состоянии ESTABLISHED (установлено) или CLOSE_WAIT (ожидание закрытия).
  • TimeTicks (тики времени). Счетчик, который считает время в сотых долях секунды с какой-либо исходной точки. Различные переменные могут указывать начало счета с различных исходных точек, исходная точка используемая для каждой переменной этого типа и указывается, когда переменная объявляется в MIB. Например, переменная sysUpTime это количество сотых долей секунды, в течение которых агент был включен.
  • SEQUENCE (последовательность). Напоминает структуру в языке программирования С. Например, мы рассмотрим, как в MIB определяется последовательность (SEQUENCE), которая называется UdpEntry и которая содержит информацию об активности конечных точек UDP агента. (Под словом "активность" мы подразумеваем порты, которые используются в настоящее время приложением.) В этой структуре есть две записи:
  1. udpLocalAddress, типа IpAddress, содержащая локальный IP адрес.
  2. udpLocalPort, типа INTEGER, в диапазоне от 0 до 65535, которая содержит локальный номер порта.
  • SEQUENCE OF (последовательность чего). Это определение вектора со всеми элементами, которые имеют тот же самый тип данных. Если каждый элемент имеет простой тип данных, такой как целое, мы имеем простой вектор (одномерный массив). Однако мы увидим, что SNMP использует эти типы данных с каждым элементом вектора, который является последовательностью (SEQUENCE) (структура). Поэтому мы можем считать их двумерными массивами или таблицей. Например, таблица слушающих процессов (listener) UDP называется udpTable, и является последовательностью (SEQUENCE OF) 2-элементной структуры (SEQUENCE) UdpEntry, которую мы только что описали. На рисунке 25.5 показан двумерный массив.

Рисунок 25.5 Таблица listener UDP (udpTable), которая представлена как двумерный массив SNMP.

Количество строк в этой таблице не определяется SNMP, однако мы увидим, что менеджер, используя оператор get-next (раздел этой главы), может определить, что получена последняя строка таблицы. Также, в разделе мы увидим, как менеджер указывает, какую строку таблицы он хочет получить или установить.

Идентификаторы объектов

Идентификатор объекта это тип данных, указывающий на полномочно названный объект. Под словом "полномочно" мы подразумеваем, что эти идентификаторы не назначаются случайным образом, а назначаются некоторыми организациями, которые несут ответственность за группу идентификаторов.

Идентификатор объекта это последовательность целых десятичных чисел, разделенных точками. Эти целые числа представляют собой древовидную структуру, напоминающую DNS () или файловую систему Unix. В вершине, откуда начинается дерево идентификаторов объектов, существует корень без названия.

На рисунке 25.6 показана структура дерева. Все переменные в MIB начинаются с идентификатора объекта 1.3.6.1.2.1.

У каждого узла в дереве также существует текстовое имя. Имя, соответствующее идентификатору объекта 1.3.6.1.2.1, это iso.org.dod.internet.mgmt.mib. Подобная форма записи имен используется для удобства чтения. Имена переменных MIB используемые при обмене пакетами между менеджером и агентом (рисунок 25.2), это цифровые идентификаторы объектов, начинающиеся с 1.3.6.1.2.1.

Рисунок 25.6 Идентификаторы объектов в информационной базе управления.

Помимо идентификаторов объектов mib, приведенных на рисунке 25.6, мы также привели еще один iso.org.dod.internet.private.enterprises (1.3.5.1.4.1). В этом месте находится MIB различных производителей. В Assigned Numbers RFC приведен список около 400 идентификаторов, зарегистрированных ниже этого узла.

Введение в Информационную Базу Управления (MIB)

Информационная база управления ( MIB - Management Information Base) это информационная база данных, которая обслуживается агентом, а менеджер может запросить информацию из этой базы или записать информацию в эту базу. Мы рассмотрим то, что называется MIB-II и описано в RFC 1213 .

Как показано на рисунке 25.6, MIB поделена на группы: system, interfaces, at (трансляция адресов), ip и так далее.

В этом разделе мы опишем только переменные, находящиеся в группе UDP. Это простая группа с небольшим количеством переменных и одной таблицей. В следующих разделах, на примере этой группы мы покажем, как осуществляется идентификация, построение лексикографического порядка и некоторые простые примеры этих характеристик. После чего, в разделе , мы вернемся к MIB и опишем некоторые другие группы в MIB.

На рисунке 25.6 мы показали группу под названием udp, находящуюся ниже mib. На рисунке 25.7 показана структура группы UDP.

Рисунок 25.7 Древовидная структура таблицы IP адресов.

Как мы говорили ранее, группа UDP содержит четыре переменные, и одну таблицу из двух переменных. На рисунке 25.8 приведены четыре переменные.

Тип данных

Описание

udpInDatagrams Counter Количество UDP датаграмм, доставленных пользовательским процессам.
udpNoPorts Counter Количество доставленных UDP датаграмм, для которых не оказалось пользовательского процесса на порте назначения.
udpInErrors Counter Количество недоставленных UDP датаграмм не по причине того, что на порте назначения не оказалось приложения (например, ошибка контрольной суммы UDP).
udpOutDatagrams Counter Количество отправленных UDP датаграмм.

Рисунок 25.8 Переменные в группе udp.

Мы будем использовать этот формат при описании всех переменных MIB в этой главе. Колонка, помеченная как "R/W", пуста, если переменная предназначена только для чтения или содержит точку (face=Symbol>·), если переменную можно читать и записывать. Мы всегда будем включать эту колонку, даже если все переменные в группе только для чтения (как мы видели в группе udp), чтобы напомнить, что ни одна из переменных не может быть установлена менеджером. В случае если тип данных - INTEGER (целый) с ограничением, мы будем указывать верхний и нижний пределы, как сделано для номера порта UDP на следующем рисунке.

На рисунке 25.9 описываются две переменные в udpTable.

Рисунок 25.9 Переменные в udpTable.

Каждый раз, когда мы описываем переменные в SNMP таблице, первая строка рисунка содержит значение "index", используемое для обращения к каждой строке таблицы. Мы покажем некоторые примеры того, как это делается, в следующем разделе.

Диаграммы зависимостей

Здесь приводится взаимосвязь между первыми тремя счетчиками, описанными на рисунке 25.8. Диаграммы зависимостей иллюстрируют взаимосвязь между различными MIB переменными в заданной группе. На рисунке 25.10 показана диаграмма зависимостей для UDP группы.

Рисунок 25.10 Диаграмма зависимостей для группы UDP.

Эта диаграмма показывает, что количество UDP датаграмм, доставленных приложению (udpInDatagrams), можно получить как количество UDP датаграмм, доставленных от IP к UDP, минус udpInErrors, минус udpNoPorts. Количество UDP датаграмм, доставленных в IP (udpOutDatagrams), это количество, переданное в UDP от приложения. Можно сделать вывод, что udpInDatagrams не включает в себя udpInErrors или udpNoPorts.

Эти диаграммы были использованы в процессе разработки MIB, для проверки того, что все пути данных для пакета были учтены. [ Rose 1994] показывает диаграммы зависимостей для всех групп в MIB.

Примеры идентификации

Каждая переменная в MIB должна быть идентифицирована, когда SNMP обращается к ней, чтобы получить или установить ее значение. Во-первых, обращение осуществляется только к листовым узлам (листовой узел в древовидной структуре - любой самый удаленный элемент от корня). SNMP не работает с целыми рядами или колонками таблицы. Возвращаясь к рисунку 25.7, мы видим, что листовыми узлами дерева, являются те четыре, что мы описали на рисунке 25.8, и два на рисунке 25.9. Узлы mib, udp, udpTable и udpEntry не являются листовыми узлами.

Простые переменные

На то, что эта переменная простая, указывает ".0", добавленный к идентификатору объекта переменной. Например, к счетчику udpInDatagrams показанному на рисунке 25.8, c идентификатором объекта 1.3.6.1.2.1.7.1, можно обратиться как 1.3.6.1.2.1.7.1.0. Текстовое имя при подобном обращении будет iso.org.dod.internet.mgmt.mib.udp.udpInDatagrams.0.

Однако обращения к этой переменной обычно делаются в сокращенном виде, udpInDatagrams.0, мы повторим, что name (имя) переменной, которое появляется в сообщении SNMP (рисунок 25.2), это идентификатор объекта 1.3.6.1.2.1.7.1.0.

Рассмотрим идентификацию пунктов таблицы более подробно. Давайте вернемся к таблице слушающего процесса UDP (рисунок 25.7).

Для каждой таблицы в MIB указан один или несколько индексов. Для таблицы слушающего процесса UDP, MIB определяет индекс как комбинацию двух переменных udpLocalAddress (локальный IP адрес) и udpLocalPort (локальный UDP порт), индекс в данном случае - целое число. (Мы показали этот индекс в верхней строке на рисунке 25.9.)

Представьте себе, что в таблице слушающего процесса UDP есть три строки: первая для IP адреса 0.0.0.0 и порта 67, вторая для 0.0.0.0 и порта 161 и третья для 0.0.0.0 и порта 520. На рисунке 25.11 показана эта таблица.

Рисунок 25.11 Простая таблица слушающего процесса UDP.

Из таблицы видно, что система готова принимать UDP датаграммы с любого интерфейса для портов 67 (BOOTP сервер), 161 (SNMP) и 520 (RIP). К трем строкам в таблице можно обратиться, как показано на рисунке 25.12.

Лексикографический порядок

Порядок в MIB основан на расположении идентификаторов объектов. Все записи в MIB таблице расположены в лексикографическом порядке в соответствии с их идентификаторами объектов. Это означает, что шесть переменных, приведенных на рисунке 25.12, расставлены в MIB так, как это показано на рисунке 25.13. В результате можно декларировать два правила.

Строка (ряд)

Идентификатор объекта

Сокращенное имя

Значение


1.3.6.1.2.1.7.5.1.2.0.0.0.0.67
udpLocalAddress.0.0.0.0.67
udpLocalPort.0.0.0.0.67

1.3.6.1.2.1.7.5.1.2.0.0.0.0.161
udpLocalAddress.0.0.0.0.161
udpLocalPort.0.0.0.0.161
1.3.6.1.2.1.7.5.1.1.0.0.0.0.520
udpLocalAddress.0.0.0.0.520
udpLocalPort.0.0.0.0.520

Рисунок 25.12 Пример идентификации строк в таблице слушающего процесса UDP.

Идентификатор объекта (в лексикографическом порядке)

Сокращенное имя

Значение

1.3.6.1.2.1.7.5.1.1.0.0.0.0.67
1.3.6.1.2.1.7.5.1.1.0.0.0.0.161
1.3.6.1.2.1.7.5.1.1.0.0.0.0.520
udpLocalAddress.0.0.0.0.67
udpLocalAddress.0.0.0.0.161
udpLocalAddress.0.0.0.0.520

0.0.0.0
0.0.0.0
0.0.0.0

1.3.6.1.2.1.7.5.1.2.0.0.0.0.67
1.3.6.1.2.1.7.5.1.2.0.0.0.0.161
1.3.6.1.2.1.7.5.1.2.0.0.0.0.520
udpLocalPort.0.0.0.0.67
udpLocalPort.0.0.0.0.161
udpLocalPort.0.0.0.0.520

67
161
520

Рисунок 25.13 Лексикографический порядок таблицы слушающего процесса UDP.

  1. Так переменная udpLocalAddress всегда появляется перед появлением в этой же таблице следующей переменной (udpLocalPort), это означает, что доступ к таблице осуществляется в порядке колонка-строка. Это является результатом лексикографического упорядочивания идентификаторов объектов, а не имен, предназначенных для чтения человеком.
  2. Порядок расположения строк в таблице зависит от значений индексов для таблицы. На рисунке 25.13, 67 лексикографически меньше чем 161, который, в свою очередь, лексикографически меньше чем 520.

На рисунке 25.14 показан порядок колонка-строка для нашего примера таблицы слушающего процесса UDP.

Рисунок 25.14 Таблица слушающего процесса UDP, показанная в порядке колонка-ряд.

Мы еще увидим этот порядок колонка-строка, когда будем использовать оператор get-next в следующем разделе.

Простые примеры

В этой главе мы покажем некоторые простые примеры того, как можно получить значения переменных от SNMP агента. Программное обеспечение, используемое для опроса агента, называется snmpi и взято из системы ISODE. Оба кратко описаны в [ Rose 1994].

Простые переменные

Мы запрашиваем маршрутизатор на предмет двух простых переменных из UDP группы:

sun % snmpi -a gateway -c secret

snmpi> get udpInDatagrams.0 udpNoPorts.0
udpInDatagrams.0=616168 udpInDatagrams.0=616168
udpNoPorts.0=33

snmpi> quit

Опция -a указывает на агента, с которым мы хотим пообщаться, а опция -c указывает SNMP сообщество. Это пароль, устанавливаемый клиентом (snmpi в данном случае), и если сервер (агент на системе gateway) распознает имя сообщества, он ответит на запрос менеджера. Агент может позволить клиентам, принадлежащим к одному сообществу, только чтение своих переменных, а клиентам из другого сообщества чтение и запись.

Программа выводит приглашение snmpi>, после чего мы можем, например, ввести команду get, которая будет преобразована в SNMP сообщение get-request. Затем мы вводим quit. (Во всех следующих примерах последняя команда quit удалена.) На рисунке 25.15 показаны две строки вывода tcpdump для этого примера.

1 0.0 sun.1024 > gateway.161: GetRequest (42)
1.3.6.1.2.1.7.1.0 1.3.6.1.2.1.7.2.0

2 0.348875 (0.3489) gateway.161 > sun.1024: GetResponse (46)
1.3.6.1.2.1.7.1.0=616168
1.3.6.1.2.1.7.2.0=33

Рисунок 25.15 Вывод tcpdump для простого запроса SNMP.

Запрос о двух переменных посылается в одной UDP датаграмме, отклик также прибывает в одной UDP датаграмме.

Мы показали переменные в виде соответствующих им идентификаторов объектов, потому что именно это было отправлено в SNMP сообщениях. Мы должны были указать эти две переменные как 0. Обратите внимание на то, что в отклике всегда возвращается имя переменной (идентификатора объекта). Ниже мы увидим, что это необходимо для работы оператора get-next.

Оператор get-next

Функционирование оператора get-next основано на лексикографическом порядке MIB. Мы начнем следующий пример с запроса следующего идентификатора объекта после udp (не указывая объект, так как это не листовой объект). При этом будет возвращен первый объект группы UDP. Затем мы запросим следующую запись, будет возвращена вторая запись. И наконец, мы повторим это еще раз, чтобы получить третью запись:

sun % snmpi -a gateway -c secret

Snmpi> next udp
udpInDatagrams.0=616318

snmpi> next udpInDatagrams.0
udpNoPorts.0=33

snmpi> next udpNoPorts.0
udpInErrors.0=0

Этот пример показывает, почему оператор get-next должен возвращать имя переменной: мы спрашиваем агента о следующей переменной, и агент возвращает ее имя и значение.

При использовании оператора get-next менеджер осуществляет циклический опрос всех переменных, поддерживаемых агентом (цикл стартует с начала MIB). Другое использование этого оператора - просмотр таблиц.

Доступ к таблице

Мы можем убедиться в том, что таблица имеет организацию колонка-строка, воспользовавшись программой, которая отправляет запросы, для того чтобы пройти через таблицу слушающего процесса UDP. Мы начнем с того, что спросим следующую переменную после udpTable. Так как это не листовой объект, мы не можем указать объект, однако оператор get-next все равно возвращает следующий объект в таблице. Затем мы продолжим движение по таблице, так как агент возвращает следующую переменную, в соответствии с порядком столбец-строка:

sun % snmpi -a gateway -c secret

snmpi> next udpTable
udpLocalAddress.0.0.0.0.67=0.0.0.0

snmpi> next udpLocalAddress.0.0.0.0.67
udpLocalAddress.0.0.0.0.161=0.0.0.0

snmpi> next udpLocalAddress.0.0.0.0.161
udpLocalAddress.0.0.0.0.520=0.0.0.0

snmpi> next udpLocalAddress.0.0.0.0.520
udpLocalPort.0.0.0.0.67=67

snmpi> next udpLocalPort.0.0.0.0.67
udpLocalPort.0.0.0.0.161=161

snmpi> next udpLocalPort.0.0.0.0.161
udpLocalPort.0.0.0.0.520=520

snmpi> next udpLocalPort.0.0.0.0.520
snmpInPkts.0=59 здесь мы закончили просмотр таблицы слушающего процесса UDP

Мы видим, что порядок, возвращенный в данном примере, соответствует порядку, приведенному на рисунке 25.14.

Как менеджер может определить, что он достиг конца таблицы? Так как ответ на оператор get-next содержит имя следующего пункта в MIB после таблицы, менеджер может сказать, когда имя изменилось. В нашем примере последний пункт в таблице слушающего процесса UDP следует за переменной snmpInPkts.

Информационная база управления (продолжение)

А сейчас мы вернемся к описанию MIB. Опишем следующие группы: system (идентификация системы), if (интерфейсы), at (трансляция адресов), ip, icmp и tcp. Также определены дополнительные группы.

Группа system

Группа system довольно проста; она состоит из семи простых переменных (таблиц в этой группе нет). На рисунке 25.16 приведены их имена, типы данных и описания.

Тип данных

Описание

sysDescr DisplayString Текстовое описание пункта.
sysObjectID ObjectID Идентификатор поставщика в поддереве 1.3.6.1.4.1.
sysUpTime TimeTicks Время в сотых долях секунд с того момента, когда часть системы, отвечающая за управление сетевое, была перестартована.
sysContact DisplayString Имя человека, к которому необходимо обратиться, и как его можно найти.
sysName DisplayString Полное имя домена узла ( FQDN) .
sysLocation DisplayString Физическое расположение узла.
sysServices Значение, указывающее на то, какие сервисы предоставляются узлом. Это сумма уровней OSI модели, поддерживаемых узлом. Следующие значения складываются вместе, в зависимости от того, какие сервисы поддерживаются: 0х01 (физический), 0х02 (канальный), 0х04 (сетевой), 0х08 (точка-точка), 0х40 (прикладной).

Рисунок 25.16 Простые переменные группы system.

Мы можем отправить запрос маршрутизатору netb, для того чтобы получить некоторые из этих переменных:

sun % snmpi -a netb -c secret

Snmpi> get sysDescr.0 sysObjectID.0 sysUpTime.0 sysServices.0
sysDescr.0="Epilogue Technology SNMP agent for Telebit NetBlazer"
sysObjectID.0=1.3.6.1.4.1.12.42.3.1
sysUpTime.0=22 days, 11 hours, 23 minutes, 2 seconds (194178200 timeticks)
sysServices.0=0xc

Идентификатор объекта системы находится в группе internet.private.enterprises (1.3.6.1.4.1), в соответствии с рисунком 25.6. Из Assigned Numbers RFC мы можем определить, что следующий идентификатор объекта (12) назначен производителю (Epilogue).

Также мы можем видеть, что переменная sysServices является суммой 4 и 8: этот элемент сети (netb) поддерживает IP уровень (маршрутизация) и транспортный уровень (точка-точка).

Группа interface

Только одна простая переменная определена для этой группы: количество интерфейсов в системе. Рисунок 25.17.

Рисунок 25.17 Простая переменная в группе if.

В этой группе также определена таблица, состоящая из 22 строк. Каждая строка в таблице определяет характеристики каждого интерфейса, как показано на рисунке 25.18.

Таблица интерфейсов, индекс = < IfIndex >

Тип данных

Описание

ifIndex INTEGER Индекс интерфейса, находится в диапазоне между единицей и ifNumber.
ifDescr DisplayString Текстовое описание интерфейса.
ifType INTEGER Тип, например: 6 = Ethernet, 7 = 802.3 Ethernet, 9 = 802.5 Token ring, 23 = PPP, 28 = SLIP и многие другие переменные.
ifMtu INTEGER MTU интерфейса (максимальный блок передачи).
ifSpeed Gauge Скорость в битах в секунду.
ifPhysAddress PhysAddress Физический адрес или строка нулевой длины для интерфейсов без физического адреса (например, последовательные каналы).
ifAdminStatus Желательное состояние интерфейса: 1 = активен, 2 = выключен, 3 = тестируется.
ifOperStatus Текущее состояние интерфейса: 1 = активен, 2 = выключен, 3 = тестируется.
ifLastChange TimeTicks Значение sysUpTime на момент, когда интерфейс вошел в текущее состояние функционирования.
ifInOctets Counter Полное количество принятых байтов, включая символы построения фреймов.
ifInUcastPkts Counter Количество персональных пакетов, доставленных к верхним уровням.
ifInNUcastPkts Counter Количество неперсональных (широковещательных или групповых) пакетов, доставленных к верхним уровням.
ifInDiscards Counter Количество принятых и отброшенных пакетов, даже если в пакете не была обнаружена ошибка (переполнение буферов).
ifInErrors Counter Количество пакетов принятых и отброшенных по причине ошибок.
ifInUnknownProtos Counter Количество принятых и отброшенных пакетов по причине того, что они принадлежали неизвестному протоколу.
ifOutOctets Counter Количество переданных байт, включая символы построения фреймов.
ifOutUcastPkts Counter Количество персональных пакетов, принятых от верхних уровней.
ifOutNUcastPkts Counter Количество неперсональных (широковещательных или групповых) пакетов, принятых от верхних уровней.
ifOutDiscards Counter Количество исходящих пакетов, которые были отброшены, даже если в пакетах не была обнаружена ошибка (переполнение буферов).
ifOutErrors Counter Количество исходящих пакетов, отброшенных по причине ошибок.
ifOutQLen Gauge Количество пакетов, находящихся в выходной очереди.
ifSpecific ObjectID Ссылка на определение MIB конкретно для этого типа среды передачи.

Рисунок 25.18 Переменные в таблице интерфейсов: ifTable.

Мы можем запросить хост sun на предмет некоторых из этих переменных для всех его интерфейсов. Мы ожидаем увидеть три интерфейса (см. главу 3, раздел ), если активизирован SLIP интерфейс:

sun % snmpi -a sun

snmpi> next ifTable во-первых, мы видим, чему равен индекс первого интерфейса
ifIndex.1=1

snmpi> get ifDescr.1 ifType.1 ifMtu.1 ifSpeed.1 ifPhysAddress.1
ifDescr.1="le0"
ifType.1=ethernet-csmacd (6)
ifMtu.1=1500
ifSpeed.1=10000000
ifPhysAddress.1=0x08:00:20:03:f6:42

snmpi> next ifDescr.1 ifType.1 ifMtu.1 ifSpeed.1 ifPhysAddress.1
ifDescr.2="sl0"
ifType.2=propPointToPointSerial (22)
ifMtu.2=552
ifSpeed.2=0
ifPhysAddress.2=0x00:00:00:00:00:00

snmpi> next ifDescr.2 ifType.2 ifMtu.2 ifSpeed.2 ifPhysAddress.2
ifDescr.3="lo0"
ifType.3=softwareLoopback (24)
ifMtu.3=1536
ifSpeed.3=0
ifPhysAddress.3=0x00:00:00:00:00:00

Во-первых, мы получили пять переменных для первого интерфейса, используя оператор get, а затем получили те же пять переменных для второго интерфейса, используя оператор get-next. Последняя команда получает эти же пять переменных для третьего интерфейса и опять с использованием команды get-next.

Тип интерфейса для SLIP канала сообщается как последовательное соединение точка-точка, а не SLIP. Также, не сообщается скорость SLIP канала.

Очень важно понять взаимосвязь между оператором get-next и порядком расположения информации в таблице, а именно колонка-строка. Когда мы задаем next ifDescr.1, возвращается следующая строка таблицы для этой переменной, а не следующую переменную в этой же строке. Однако если бы таблицы хранились в порядке строка-колонка, мы могли подобным образом перейти к следующему появлению заданной переменной.

Группа at

Группа трансляции адресов поддерживается во всех системах, однако ее ценность значительно уменьшилась, после того как стала использоваться MIB-II. С использованием MIB-II, каждая группа сетевых протоколов (например, IP) содержит свою собственную таблицу трансляции адресов. Для IP это ipNetToMediaTable.

В группе at определена только одна таблица из трех строк, как показано на рисунке 25.19.

Мы можем использовать новую команду, существующую в программе snmpi, чтобы получить содержимое таблицы в целом. Мы запросим маршрутизатор с именем kinetics (который предоставляет маршруты между TCP/IP сетью и сетью AppleTalk), выдать полный ARP кэш. Этот вывод будет находиться в лексикографическом порядке в виде пунктов, находящихся в таблице:

Таблица трансляции адресов, индекс = .1.

Тип данных

Описание

atIfIndex INTEGER Номер интерфейса: ifIndex.
atPhysAddress PhysAddress Физический адрес. Установка этого параметра в строку с нулевой длиной приводит к тому, что пункт считается некорректным.
atNetAddress NetworkAddress IP адрес

Рисунок 25.19 Таблица трансляции адресов: atTable.

sun % snmpi -a kinetics -c secret dump at

atIfIndex.1.1.140.252.1.4=1
atIfIndex.1.1.140.252.1.22=1
atIfIndex.1.1.140.252.1.183=1
atIfIndex.2.1.140.252.6.4=2
atIfIndex.2.1.140.252.6.6=2

atPhysAddress.1.1.140.252.1.4=0xaa:00:04:00:f4:14
atPhysAddress.1.1.140.252.1.22=0x08:00:20:0f:2d:38
atPhysAddress.1.1.140.252.1.183=0x00:80:ad:03:6a:80
atPhysAddress.2.1.140.252.6.4=0x00:02:16:48
atPhysAddress.2.1.140.252.6.6=0x00:02:3c:48

atNetAddress.1.1.140.252.1.4=140.252.1.4
atNetAddress.1.1.140.252.1.22=140.252.1.22
atNetAddress.1.1.140.252.1.183=140.252.1.183
atNetAddress.2.1.140.252.6.4=140.252.6.4
atNetAddress.2.1.140.252.6.6=140.252.6.6

С использованием tcpdump можно увидеть следующее. Для того чтобы получить полную таблицу, snmpi, во-первых, выдает get-next для имени таблицы (at в данном примере), чтобы получить первый пункт. Затем печатает первый пункт и выдает get-next. Это продолжается до тех пор, пока не будет получена вся таблица целиком.

На рисунке 25.20 показана подобная таблица.

0xaa:00:04:00:f4:14 140.252.1.4
0x08:00:20:0f:2d:38 140.252.1.22
0x00:80:ad:03:6a:80 140.252.1.183
0x00:02:16:48 140.252.6.4
0x00:02:3c:48 140.252.6.6

Рисунок 25.20 Пример таблицы at (ARP кэш).

Физические адреса AppleTalk с номером интерфейса - 2 имеют 32-битные значения, а не 48-битные, как у привычных Ethernet адресов. Также обратите внимание на то, что существуют запись для нашего маршрутизатора (netb находится по адресу 140.252.1.183), так как kinetics и netb находятся на одном и том же Ethernet кабеле (140.252.1), и kinetics должен использовать ARP, чтобы послать нам SNMP отклик.

Группа ip

Группа ip определяет большое количество переменных и три таблицы. На рисунке 25.21 приведены простые переменные.

Тип данных

Описание

ipForwarding 1 означает, что система перенаправляет IP датаграммы, а 2 означает, что не перенаправляет.
ipDefaultTTL INTEGER Значение TTL по умолчанию, когда его не предоставляет транспортный уровень.
ipInReceives Counter Полное количество IP датаграмм, полученных со всех интерфейсов.
ipInHdrErrors Counter Количество IP датаграмм, отброшенных из-за ошибок в заголовке (например, ошибка контрольной суммы, несовпадение номера версии, истечение TTL и так далее).
ipInAddrErrors Counter Количество IP датаграмм, отброшенных из-за неправильного адреса назначения.
IpForwDatagrams Counter Количество IP датаграмм, для которых была сделана попытка перенаправить.
ipInUnknownProtos Counter Количество локально адресованных IP датаграмм, у которых было неверное поле протокола.
ipInDiscards Counter Количество принятых IP датаграмм, отброшенных из-за недостаточного размера буфера.
ipInDelivers Counter Количество IP датаграмм, доставленных соответствующему модулю протокола.
ipOutRequests Counter Полное количество IP датаграмм, переданных в IP уровень для передачи. Сюда не включены те, которые были посчитаны в ipForwDatagrams.
ipOutDiscards Counter Количество исходящих IP датаграмм, которые были отброшены из-за отсутствия места в буфере.
ipOutNoRoutes Counter Количество IP датаграмм, которые были отброшены из-за того, что не был найден маршрут.
ipReasmTimeout INTEGER Максимальное количество секунд, в течение которого принятые фрагменты ждали повторной сборки.
ipReasmReqds Counter Количество принятых IP фрагментов, которые должны быть собраны.
ipReasmOKs Counter Количество успешно собранных IP датаграмм.
ipReasmFails Counter Количество сбоев в алгоритме повторной сборки IP.
ipFragOKs Counter Количество успешно фрагментированных IP датаграмм.
ipFragFails Counter Количество IP датаграмм, которые необходимо фрагментировать, однако это не было сделано, потому что был установлен флаг "не фрагментировать".
ipFragCreates Counter Количество IP фрагментов, которые были получены при фрагментации.
ipRoutingDiscards Counter Количество пунктов маршрутизации, выбранных для уничтожения, даже если они существовали и были верны.

Рисунок 25.21 Простые переменные группы ip.

Первая таблица в группе ip это таблица IP адресов. Она содержит по одной строке для каждого IP адреса в системе. Каждая строка содержит пять переменных, описанных на рисунке 25.22.

Таблица IP адресов, индекс =

Тип данных

Описание

ipAdEntAddr IpAddress IP адрес для этой строки.
ipAdEntIfIndex INTEGER Соответствующий номер интерфейса: ifIndex.
ipAdEntNetMask IpAddress Маска подсети для этого IP адреса.
ipAdEntBcastAddr Значение младших битов в широковещательном IP адресе. Обычно равно 1.
ipAdEntReasmMaxSize Размер максимальной принятой IP датаграммы для этого интерфейса, которая может быть повторно собрана.

Рисунок 25.22 Таблица IP адресов: ipAddrTable.

Мы можем запросить хост sun, чтобы получить таблицу IP адресов:

sun % snmpi -a sun dump ipAddrTable

ipAdEntAddr.127.0.0.1=127.0.0.1
ipAdEntAddr.140.252.1.29=140.252.1.29
ipAdEntAddr.140.252.13.33=140.252.13.33

ipAdEntIfIndex.127.0.0.1=3 loopback интерфейс, lo0
ipAdEntIfIndex.140.252.1.29=2 SLIP интерфейс, sl0
ipAdEntIfIndex.140.252.13.33=1 Ethernet интерфейс, le0

ipAdEntNetMask.127.0.0.1=255.0.0.0
ipAdEntNetMask.140.252.1.29=255.255.255.0
ipAdEntNetMask.140.252.13.33=255.255.255.224

ipAdEntBcastAddr.127.0.0.1=1 все три используют единичный бит
ipAdEntBcastAddr.140.252.1.29=1 для широковещательного адреса
ipAdEntBcastAddr.140.252.13.33=1

ipAdEntReasmMaxSize.127.0.0.1=65535
ipAdEntReasmMaxSize.140.252.1.29=65535
ipAdEntReasmMaxSize.140.252.13.33=65535

Номера интерфейсов можно сравнить с выводом, полученным на рисунке 25.18, а IP адреса и маски подсетей можно сравнить со значениями, полученными в выводе команды ifconfig в разделе главы 3.

Следующая таблица, приведенная на рисунке 25.23, это таблица IP маршрутизации. (Обратитесь к описанию таблиц маршрутизации, приведенному в разделе главы 9.) В качестве индекса для получения доступа к каждой строке таблицы, используется IP адрес назначения.

На рисунке 25.24 приведена таблица маршрутизации для хоста sun, полученная с помощью команды dump ipRouteTable программы snmpi. Мы удалили все пять показателей маршрутизации, так как все они равны -1, а в заголовках колонок удалили префикс ipRoute для каждого имени переменной.

Таблица маршрутизации IP, индекс =

Тип данных

Описание

ipRouteDest IpAddress IP адрес назначения. Значение 0.0.0.0 указывает на пункт по умолчанию.
ipRouteIfIndex INTEGER Номер интерфейса: ifIndex.
ipRouteMetric1 INTEGER Первичный показатель маршрута. Значение показателя зависит от протокола маршрутизации (ipRouteProto). Значение -1 означает, что маршрут не используется.
ipRouteMetric2 INTEGER
ipRouteMetric3 INTEGER Альтернативный показатель маршрута.
ipRouteMetric4 INTEGER Альтернативный показатель маршрута.
ipRouteNextHop IpAddress IP адрес маршрутизатора следующей пересылки.
ipRouteType INTEGER Тип маршрута: 1=другой, 2=недействующий маршрут, 3=прямой, 4=непрямой.
ipRouteProto INTEGER Протокол маршрутизации: 1=другой, 4=ICMP перенаправление, 8=RIP, 13=OSPF, 14=BGP и другие.
ipRouteAge INTEGER Количество секунд, которое прошло с того момента, когда маршрут был последний раз обновлен или определен как корректный.
ipRouteMask IpAddress Маска, которая должна быть добавлена по логическому И к IP адресу назначения, перед тем как она будет сравнена с ipRouteDest.
ipRouteMetric5 INTEGER Альтернативный показатель маршрута.
ipRouteInfo ObjectID Ссылка на конкретное определение MIB для этого протокола маршрутизации.

Рисунок 25.23 Таблица IP маршрутизации: ipRouteTable.

0.0.0.0 140.252.1.183

непрямой (4)

другой (1)

0.0.0.0
127.0.0.1 127.0.0.1

прямой (3)

другой (1)

255.255.255.255
140.252.1.183 140.252.1.29

прямой (3)

другой (1)

255.255.255.255
140.252.13.32 140.252.13.33

прямой (3)

другой (1)

255.255.0.0
140.252.13.65 140.252.13.35

непрямой (4)

другой (1)

255.255.255.255

Рисунок 25.24 Таблица IP маршрутизации маршрутизатора sun.

Для сравнения здесь приводится таблица маршрутизации IP в формате вывода команды netstat (см. главу 9, раздел ). На рисунке 25.24 таблица маршрутизации приводится в лексикографическом порядке:

sun % netstat -rn
Routing tables
Destination Gateway Flags Refcnt Use Interface
140.252.13.65 140.252.13.35 UGH 0 115 le0
127.0.0.1 127.0.0.1 UH 1 1107 lo0
140.252.1.183 140.252.1.29 UH 0 86 sl0
default 140.252.1.183 UG 2 1628 sl0
140.252.13.32 140.252.13.33 U 8 68359 le0

И последняя таблица для группы ip это таблица трансляции адресов, приведенная на рисунке 25.25. Как мы говорили раньше, группа at в настоящее время практически не используется (как устаревшая), и эта таблица заменяет ее.

Таблица трансляции IP адресов, индекс = .

Имя Тип данных Описание
ipNetToMediaIfIndex INTEGER Соответствующий интерфейс: ifIndex.
ipNetToMediaPhysAddress PhysAddress Физический адрес.
ipNetToMediaNetAddress IpAddress IP адрес.
ipNetToMediaType Тип сопоставления: 1=другой, 2=неиспользуемый, 3=динамический, 4=статический.

Рисунок 25.25 Таблица трансляции IP адресов: ipNetToMediaTable.

Здесь мы приводим ARP кэш системы sun:

Face="Courier New" size=1>

sun % arp -a
svr4 (140.252.13.34) at 0:0:c0:c2:9b:26
bsdi (140.252.13.35) at 0:0:c0:6f:2d:40

и соответствующий SNMP вывод:

Face="Courier New" size=1>

sun % snmpi -a sun dump ipNetToMediaTable

IpNetToMediaIfIndex.1.140.252.13.34=1
ipNetToMediaIfIndex.1.140.252.13.35=1
ipNetToMediaPhysAddress.1.140.252.13.34=0x00:00:c0:c2:9b:26
ipNetToMediaPhysAddress.1.140.252.13.35=0x00:00:c0:6f:2d:40
ipNetToMediaNetAddress.1.140.252.13.34=140.252.13.34
ipNetToMediaNetAddress.1.140.252.13.35=140.252.13.35
ipNetToMediaType.1.140.252.13.34=dynamic(3)
ipNetToMediaType.1.140.252.13.35=dynamic(3)

Группа icmp

Группа icmp состоит из четырех общих счетчиков (общее количество входящих и исходящих ICMP сообщений и количество входящих и исходящих ICMP сообщений с ошибками) и 22-х счетчиков для различных типов ICMP сообщений: 11 счетчиков на входящие сообщения и 11 счетчиков на исходящие сообщения. Это показано на рисунке 25.26.

Для ICMP сообщений с дополнительными кодами (обратитесь к , на котором приведены 15 различных кодов для сообщения о недостижимости пункта назначения) отдельный счетчик для каждого SNMP кода не поддерживается.

Группа tcp

На рисунке 25.27 описаны простые переменные группы tcp. Многие из них соответствуют состояниям TCP, которые показаны на .

Тип данных

Описание

icmpInMsgs Counter Полное количество принятых ICMP сообщений.
icmpInErrors Counter Количество принятых ICMP сообщений с ошибками (например, ошибочная контрольная сумма ICMP).
icmpInDestUnreachs Counter Количество принятых ICMP сообщений о недоступности источника.
icmpInTimeExcds Counter Количество принятых ICMP сообщений об истечении времени.
icmpInParmProbs Counter Количество принятых ICMP сообщений о проблемах с параметром.
icmpInSrcQuenchs Counter Количество принятых ICMP сообщений о подавлении источника.
icmpInRedirects Counter Количество принятых ICMP сообщений о перенаправлении.
icmpInEchos Counter Количество принятых ICMP сообщений с эхо запросом.
icmpInEchoReps Counter Количество принятых ICMP сообщений с эхо откликом.
icmpInTimestamps Counter Количество принятых ICMP сообщений с запросом временной марки.
icmpInTimestampReps Counter Количество принятых ICMP сообщений с откликом временной марки.
icmpInAddrMasks Counter Количество принятых ICMP сообщений с запросом маски адреса.
icmpInAddrMaskReps Counter Количество принятых ICMP сообщений с откликом маски адреса.
icmpOutMsgs Counter Полное количество исходящих ICMP сообщений.
icmpOutErrors Counter Количество ICMP сообщений, которые не были отправлены из-за проблем внутри ICMP (переполнение буферов).
icmpOutDestUnreachs Counter Количество посланных ICMP сообщений о недоступности пункта назначения.
icmpOutTimeExcds Counter Количество посланных ICMP сообщений об истечении времени.
icmpOutParmProbs Counter Количество посланных ICMP сообщений о проблемах с параметром.
icmpOutSrcQuenchs Counter Количество посланных ICMP сообщений о подавлении источника.
icmpOutRedirects Counter Количество посланных ICMP сообщений о перенаправлении.
icmpOutEchos Counter Количество посланных ICMP сообщений с эхо запросом.
icmpOutEchoReps Counter Количество посланных ICMP сообщений с эхо откликом.
icmpOutTimestamps Counter Количество посланных ICMP сообщений с запросом временной марки.
icmpOutTimestampReps Counter Количество посланных ICMP сообщений с откликом временной марки.
icmpOutAddrMasks Counter Количество посланных ICMP сообщений с запросом маски адреса.
icmpOutAddrMaskReps Counter Количество посланных ICMP сообщений с откликом маски адреса.

Рисунок 25.26 Простые переменные группы icmp.

Мы можем запросить некоторые из этих переменных для системы sun:

Face="Courier New" size=1>

sun % snmpi -a sun

Snmpi> get tcpRtoAlgorithm.0 tcpRtoMin.0 tcpRtoMax.0 tcpMaxConn.0
tcpRtoAlgorithm.0=vanj(4)
tcpRtoMin.0=200
tcpRtoMax.0=12800
tcpMaxConn.0=-1

Система SunOS 4.1.3 использует алгоритм тайм-аута и повторной передачи, разработанный Van Jacobson, при этом используемые тайм-ауты находятся в диапазоне от 200 миллисекунд до 12,8 секунд, и не существует фиксированного предела для количества TCP соединений. (Верхняя граница диапазона, составляющая 12,8 секунды, неверна, так как большинство реализаций используют верхний предел в 64 секунды, как мы видели в .)

Группа tcp имеет одну таблицу, таблицу TCP соединений, показанную на рисунке 25.28. Она содержит по одной строке для каждого соединения. Каждая строка содержит пять переменных: состояние соединения, локальный IP адрес, локальный номер порта, удаленный IP адрес и удаленный номер порта.

Тип данных

Описание

tcpRtoAlgorithm INTEGER Алгоритм, используемый для расчета величин тайм-аутов и повторных передач: 1=нет, 2=постоянный RTO, 3=MIL-STD-1778 (), 4=алгоритм Van Jacobson.
tcpRtoMin INTEGER Минимальное значение тайм-аута повторной передачи, в миллисекундах.
tcpRtoMax INTEGER Максимальное значение тайм-аута повторной передачи, в миллисекундах.
tcpMaxConn INTEGER Максимальное количество TCP соединений. Значение -1 обозначает, что эта величина определяется динамически.
tcpActiveOpens Counter Количество переходов от состояния CLOSED к состоянию SYN_SENT.
tcpPassiveOpens Counter Количество переходов от состояния LISTEN к состоянию SYN_RCVD.
tcpAttemptFails Counter Количество переходов от состояния SYN_SENT или SYN_RCVD к состоянию CLOSED, плюс количество переходов от состояния SYN_RCVD к состоянию LISTEN.
tcpEstabResets Counter Количество переходов от состояния ESTABLISHED или CLOSE_WAIT к состоянию CLOSED.
tcpCurrEstab Gauge Количество соединений, находящихся в настоящее время в состоянии ESTABLISHED или CLOSE_WAIT.
tcpInSegs Counter Полное количество принятых сегментов.
tcpOutSegs Counter Полное количество отправленных сегментов, за исключением тех, которые содержали только повторно передаваемые байты.
tcpRetransSegs Counter Полное количество повторно переданных сегментов.
tcpInErrs Counter Полное количество сегментов, принятых с ошибками (например, неверная контрольная сумма).
tcpConnLocalAddress IpAddress Локальный IP адрес. 0.0.0.0 указывает на то, что слушающий процесс готов принять соединение с любого интерфейса.
tcpConnLocalPort Локальный номер порта.
tcpConnRemAddress IpAddress Удаленный IP адрес.
tcpConnRemPort Удаленный номер порта.

Рисунок 25.28 Таблица TCP соединений: tcpConnTable.

Давайте посмотрим эту таблицу на системе sun. Мы показали только часть таблицы, так как очень много серверов (в данном случае слушающие процессы) слушает запросы на соединения. Перед тем как получить таблицу, было установлено два TCP соединения:

Face="Courier New" size=1>

sun % rlogin gemini face=Arial size=2>IP адрес face="Courier New" size=2>gemini равен 140.252.1.11

Face="Courier New" size=1>

sun % telnet localhost IP адрес должен быть 127.0.0.1

Единственный слушающий сервер, как мы показали, это FTP сервер на порте 21:

Face="Courier New" size=1>

sun % snmpi -a sun dump tcpConnTable

TcpConnState.0.0.0.0.21.0.0.0.0.0=listen(2)
tcpConnState.127.0.0.1.23.127.0.0.1.1415=established(5)
tcpConnState.127.0.0.1.1415.127.0.0.1.23=established(5)
tcpConnState.140.252.1.29.1023.140.252.1.11.513=established(5)

tcpConnLocalAddress.0.0.0.0.21.0.0.0.0.0=0.0.0.0
tcpConnLocalAddress.127.0.0.1.23.127.0.0.1.1415=127.0.0.1
tcpConnLocalAddress.127.0.0.1.1415.127.0.0.1.23=127.0.0.1
tcpConnLocalAddress.140.252.1.29.1023.140.252.1.11.513=140.252.1.29

tcpConnLocalPort.0.0.0.0.21.0.0.0.0.0=21
tcpConnLocalPort.127.0.0.1.23.127.0.0.1.1415=23
tcpConnLocalPort.127.0.0.1.1415.127.0.0.1.23=1415
tcpConnLocalPort.140.252.1.29.1023.140.252.1.11.513=1023

tcpConnRemAddress.0.0.0.0.21.0.0.0.0.0=0.0.0.0
tcpConnRemAddress.127.0.0.1.23.127.0.0.1.1415=127.0.0.1
tcpConnRemAddress.127.0.0.1.1415.127.0.0.1.23=127.0.0.1
tcpConnRemAddress.140.252.1.29.1023.140.252.1.11.513=140.252.1.11

tcpConnRemPort.0.0.0.0.21.0.0.0.0.0=0
tcpConnRemPort.127.0.0.1.23.127.0.0.1.1415=1415
tcpConnRemPort.127.0.0.1.1415.127.0.0.1.23=23
tcpConnRemPort.140.252.1.29.1023.140.252.1.11.513=513

Для команды rlogin на хост gemini присутствует только один пункт, так как gemini это удаленный хост. Мы видим только клиентскую часть соединения (локальный порт 1023), однако показаны оба конца Telnet соединения (порт клиента 1415 и порт сервера 23), так как соединение проходит через loopback интерфейс. Также мы можем видеть, что слушающий FTP сервер имеет локальный IP адрес 0.0.0.0, что указывает на то, что он примет соединение с любого интерфейса.

Дополнительные примеры

Сейчас мы вернемся к некоторым проблемам, которые были рассмотрены раньше в этой книге, и попробуем использовать SNMP, для того чтобы понять, что все-таки произошло.

MTU интерфейса

Вернемся к нашему эксперименту, описанному в разделе главы 11, в котором мы пытались определить MTU SLIP канала от netb к sun. Сейчас мы можем использовать SNMP, чтобы получить этот MTU. Во-первых, мы получим номер интерфейса (ipRouteIfIndex) для SLIP канала (140.252.1.29) из таблицы IP маршрутизации. Для этого, мы попадаем в таблицу интерфейсов и получаем MTU (вместе с описанием и типом) канала SLIP:

Face="Courier New" size=1>

sun % snmpi -a netb -c secret

Snmpi> get ipRouteIfIndex.140.252.1.29
ipRouteIfIndex.140.252.1.29=12
snmpi> get ifDescr.12 ifType.12 ifMtu.12
ifDescr.12="Telebit NetBlazer dynamic dial virtual interface"
ifType.12=other(1)
ifMtu.12=1500

Мы видим, что даже для канала, который является SLIP, MTU установлено в Ethernet значение равное 1500, возможно для того, чтобы избежать фрагментации.

Таблицы маршрутизации

Давайте обратимся к нашему обсуждению сортировки адресов, которая осуществляется DNS, приведенному в разделе главы 14. Мы показали, как первый IP адрес, возвращенный DNS сервером, был одним из тех, что принадлежат к той же подсети, что и клиент. Также мы упомянули, что использование другого IP адреса, вполне возможно, будет работать, однако в этом случае все будет менее эффективно. Давайте посмотрим, что произойдет при использовании альтернативного IP адреса. Мы будем использовать SNMP, чтобы посмотреть пункты в таблице маршрутизации, и попробуем объединить вместе несколько концепций, о которых мы рассказывали в предыдущих главах и которые имели отношение к IP маршрутизации.

Хост gemini имеет несколько интерфейсов, два из которых Ethernet интерфейсы. Во-первых, убедимся, что можем получить соединение Telnet на оба адреса:

Face="Courier New" size=1>

sun % telnet 140.252.1.11 daytime
Trying 140.252.1.11 ...
Connected to 140.252.1.11.
Escape character is "^]".
Sat Mar 27 09:37:24 1993
Connection closed by foreign host.

sun % telnet 140.252.3.54 daytime
Trying 140.252.3.54 ...
Connected to 140.252.3.54.
Escape character is "^]".
Sat Mar 27 09:37:35 1993
Connection closed by foreign host.

Мы видим, что нет никакой разницы в соединениях между двумя адресами. Сейчас воспользуемся traceroute, чтобы посмотреть, используются ли различные маршруты к каждому адресу:

sun % traceroute 140.252.1.11
traceroute to 140.252.1.11 (140.252.1.11), 30 hops max, 40 byte packets
1 netb (140.252.1.183) 299 ms 234 ms 233 ms
2 gemini (140.252.1.11) 233 ms 228 ms 234 ms

sun % traceroute 140.252.3.54
traceroute to 140.252.3.54 (140.252.3.54), 30 hops max, 40 byte packets
1 netb (140.252.1.183) 245 ms 212 ms 234 ms
2 swnrt (140.252.1.6) 233 ms 229 ms 234 ms
3 gemini (140.252.3.54) 234 ms 233 ms 234 ms

Мы видим, что при использовании адреса подсети 140.252.3 появляется дополнительная пересылка (маршрутизатор swnrt - это R3 на ). Давайте посмотрим, почему осуществляется эта дополнительная пересылка.

На рисунке 25.29 показаны настройки систем. На основе вывода команды traceroute мы можем сказать, что хост gemini и маршрутизатор swnrt оба подсоединены к двум сетям: 140.252.1 и 140.252.3.

Рисунок 25.29 Топология систем, которые используются в примере.

sun % traceroute -g 140.252.3.54 sun
traceroute to sun (140.252.13.33), 30 hops max, 40 byte packets
1 netb (140.252.1.183) 244 ms 256 ms 234 ms
2 * * *
3 gemini (140.252.3.54) 285 ms 227 ms 234 ms
4 netb (140.252.1.183) 263 ms 259 ms 294 ms
5 sun (140.252.13.33) 534 ms 498 ms 504 ms

Когда используется свободная маршрутизация от источника, маршрутизатор swnrt никогда не отвечает. Если посмотреть на ранний вывод команды traceroute, без маршрутизации от источника, мы увидим, что swnrt является второй пересылкой. Причиной этого может являться то, что маршрутизатор не генерирует ICMP ошибки об истечении времени, когда в датаграмме установлена свободная маршрутизация от источника. Мы видим из этого вывода команды traceroute, что путь возврата от gemini (TTL 3, 4 и 5) проходит непосредственно к netb, а не проходит через маршрутизатор swnrt.

Вопрос, на который нам должен помочь ответить SNMP, заключается в том, что делает пункт таблицы маршрутизации в netb таким, что сеть назначения установлена в 140.252.3? Все дело в том, что netb отправляет пакеты к swnrt, а не непосредственно к gemini. Мы используем команду get, чтобы получить значение маршрутизатора следующей пересылки для этого пункта назначения:

Face="Courier New" size=1>

sun % snmpi -a netb -c secret get ipRouteNextHop.140.252.3.0

IpRouteNextHop.140.252.3.0=140.252.1.6

Пункт таблицы маршрутизации говорит netb послать пакеты на swnrt, что, как мы видим, и происходит.

Почему gemini отправляет пакеты назад непосредственно через netb? Потому что адрес назначения для пакетов, возвращающихся от gemini, установлен в 140.252.1.29, а сеть 140.252.1 подключена непосредственно.

То, что мы видим в этом примере, является результатом политических решений о маршрутизации. Маршрут по умолчанию к сети 140.252.3 проходит через маршрутизатор swnrt, потому что gemini является просто хостом с несколькими интерфейсами, но не выполняет функции маршрутизатора. Это как раз пример хоста с несколькими интерфейсами, который не хочет быть маршрутизатором.

Ловушки (Traps)

Все примеры, которые мы рассмотрели в этой главе, иллюстрируют передачу информации от менеджера к агенту. Однако у агента существует способ сообщить менеджеру о возникновении какого-либо события, о котором менеджер должен знать (см. рисунок 25.1). В этом случае агент посылает менеджеру ловушки (trap). Ловушки отправляются на UDP порт 162 менеджера.

На рисунке 25.2 мы показали формат ловушки PDU. Мы просмотрим все поля в этом сообщении, когда ниже будем рассматривать вывод команды tcpdump.

Определены шесть ловушек, седьмая используется производителем, чтобы установить собственную ловушку. На рисунке 25.30 описываются значения типа ловушки (trap type) в сообщении ловушки (рисунок 25.2).

тип ловушки

Описание

0 coldStart Агент инициализировал себя сам.
1 warmStart Агент повторно инициализировал себя сам.
2 linkDown Состояние интерфейса изменилось с "активизировано" на "выключено" (рисунок 25.18). Первая переменная в сообщении указывает на интерфейс.
3 linkUp Состояние интерфейса изменилось с состояния "выключено" на состояние "активизировано" (рисунок 25.18). Первая переменная в сообщении указывает на интерфейс.
4 authenticationFailure Сообщение было получено от SNMP менеджера из неверного сообщества.
5 egpNeighborLoss EGP узел изменил свое состояние на "выключено". Первая переменная в сообщении содержит IP адрес узла.
6 enterpriseSpecific Обратитесь к полю специализированных кодов за информацией об этой ловушке.

Рисунок 25.30 Типы ловушек.

Мы можем увидеть некоторые ловушки с помощью tcpdump. Стартуем SNMP агента на системе sun и посмотрим, как он генерирует ловушку coldStart. (Агент знает о необходимости посылать ловушки на хост bsdi. Однако на bsdi не стартован менеджер для обработки ловушек, вместо него запущен tcpdump, что позволяет увидеть генерируемые пакеты. Обратитесь к рисунку 25.1, откуда видно, что ловушки посылаются от агента к менеджеру, однако менеджер не посылает подтверждений, поэтому нет необходимости, чтобы менеджер обрабатывал ловушки.) Затем, с использованием программы snmpi, мы посылаем запрос, в котором указано неверное имя сообщества. В ответ на это должна быть сгенерирована ловушка authenticationFailure. На рисунке 25.31 показан вывод.

1 0.0 sun.snmp > bsdi.snmp-trap: C=traps Trap(28)
E:unix.1.2.5 coldStart 20

2 18.86 (18.86) sun.snmp > bsdi.snmp-trap: C=traps Trap(29)
E:unix.1.2.5 authenticationFailure 1907

Рисунок 25.31 Вывод команды tcpdump, соответствующий генерации ловушек SNMP агентом.

Во-первых, необходимо обратить внимание на то, что обе UDP датаграммы, отправленные от SNMP агента (порт 161, печатается как имя snmp), имеют порт назначения 162 (печатается как имя snmp-trap).

Выражение C=traps это имя сообщества в сообщении ловушки. Это опция конфигурации, которая используется агентом в случае ISODE SNMP.

Следующее выражение, Trap(28) в строке 1 и Trap(29) в строке 2, это тип PDU (PDU type) и длина.

Следующее поле вывода для обеих строк - E:unix.1.2.5. Это enterprise: идентификатор системы объекта (sysObjectID). Он находится под узлом 1.3.6.1.4.1 в дереве, приведенном на рисунке 25.6 (iso.org.dod.internet.private.enterprises), таким образом, идентификатор объекта агента равен 1.3.6.1.4.1.4.1.2.5. Его сокращенное имя unix.agents.fourBSD-isode.5. Последняя цифра (5) это номер версии релиза агента ISODE. Это значение указывает на то, какое программное обеспечение агента сгенерировало ловушку.

Следующее поле вывода команды tcpdump это IP адрес агента (140.252.13.33).

Тип ловушки печатается как coldStart в строке 1 и как authenticationFailure в строке 2. Они соответствуют значениям типа ловушки равным 0 и 4 соответственно (рисунок 25.30). Так как эти ловушки не являются специализированными (enterprise), специфичный код (specific code) должен быть равен 0 и поэтому не печатается.

Далее следует поле временной марки (timestamp), которое печатается как 20 и 1907. Это значение TimeTicks, соответствующее количеству сотых долей секунд с момента инициализации агента. В случае ловушки холодного старта, она генерируется через 200 миллисекунд после того, как агент инициализирован. Вывод tcpdump указывает на то, что вторая ловушка появилась через 18,86 секунды после первой, чему соответствует напечатанное значение 1907 сотых долей секунд минус 200 миллисекунд.

Из рисунка 25.2 видно, что сообщение ловушки может содержать переменные, которые агенты хотят отправить менеджеру, однако в наших примерах они не присутствуют.

Формальная спецификация SNMP использует абстрактную форму записи ( ASN.1 - Abstract Syntax Notation 1), и кодирование бит в SNMP сообщениях (рисунок 25.2) на основе основных правил кодирования ( BER - Basic Encoding Rules). В отличие от большинства публикаций, описывающих SNMP, мы специально оставили обсуждение ASN.1 и BER на самый конец. Если рассказать о них в самом начале, читатель может неправильно понять реальное назначение SNMP - управление сетью. В этом разделе мы дадим только краткий обзор этих двух тем. Глава 8 [ Rose 1990] описывает ASN.1 и BER более подробно.

ASN.1 это формальный язык, который описывает данные и характеристики данных. Он не определяет то, как эти данные хранятся или кодируются. Все поля в MIB и SNMP сообщениях описываются с использованием ASN.1. Например, ASN.1 определение типа данных IpAddress из SMI выглядит следующим образом:

IpAddress::=
-- in network-byte order
IMPLICIT OCTET STRING (SIZE(4))

Точно так же, в MIB мы находим следующее определение простых переменных:

udpNoPorts OBJECT-TYPE
SYNTAX Counter
ACCESS read-only
STATUS mandatory
DESCRIPTION
"The total number of received UDP datagrams for which there
was no application at the destination port."
::= { udp 2 }

Определение таблиц, использующих SEQUENCE и SEQUENCE OF, более сложное.

С использованием подобных ASN.1 определений существует множество способов закодировать данные в поток битов при передаче. SNMP использует BER. Для представления маленьких целых чисел, таких как 64, с использованием BER требуется 3 байта. Один байт содержит значение целого, следующий байт говорит, сколько байтов используется, чтобы хранить целое (1), и последний байт содержит двоичное значение.

К счастью, подробности ASN.1 и BER важны только для разработчиков SNMP. Они не обязательны для понимания того, как осуществляется управление сетью.

SNMP версии 2 (SNMP Version 2)

В течение 1993 года было опубликовано 11 RFC, которые определяли новые стандарты SNMP. Первый из них, RFC 1441 [ Case et al. 1993], является введением в SNMP версии 2 (SNMPv2). Две книги также описывают SNMPv2 . В настоящее время существуют две доступные реализации (см. приложение В.3 публикации [ Rose 1994]), однако коммерческие реализации, возможно, не будут широко доступны до 1994 года.

В этом разделе мы опишем основные отличия SNMPv1 от SNMPv2.

Новый тип пакетов get-bulk-request позволяет менеджеру эффективно обрабатывать большие блоки данных. Еще один новый тип пакетов inform-request позволяет одному менеджеру посылать информацию другому менеджеру. Определены два новых MIB: MIB SNMPv2 и MIB SNMPv2-M2M (менеджер-менеджер). SNMPv2 предоставляет улучшенную секретность по сравнению с SNMPv1. В SNMPv1 имя сообщества передается от менеджера к агенту в виде открытого пароля. SNMPv2 предоставляет аутентификацию и расширенную секретность.

Все производители начинают реализовывать агентов, совместимых с SNMPv2, а также появляются управляющие станции, которые могут использовать оба стандарта. [ Routhier 1993] описывает расширения и улучшения SNMPv1, которые призваны обеспечить совместимость и поддержку SNMPv2.

Краткие выводы

SNMP это простой протокол, основанный на запросах и откликах, предназначенный для обмена между SNMP менеджером и SNMP агентом. Информационная база данных управления (MIB) определяет переменные, которые обслуживаются агентом, которые, в свою очередь, менеджер может либо запросить, либо установить. Для определения переменных используется ограниченное количество типов данных.

Все переменные идентифицируются идентификаторами объекта, используется иерархическая схема присвоения имен, которая состоит из длинных строк чисел, которые обычно сокращаются в простые имена, для простоты чтения. Конкретные переменные строятся с помощью добавления переменной к идентификатору объекта.

Большинство SNMP переменных содержится в таблицах, с фиксированными номерами колонок, однако с переменными номерами строк. Фундаментальным для SNMP является схема идентификации, используемая для того, чтобы идентифицировать каждую строку в таблице (в том случае, когда мы не знаем, сколько строк содержится в таблице), и лексикографический порядок (порядок колонка-строка). SNMP оператор get-next является основным для любого SNMP менеджера.

Мы описали следующие группы SNMP переменных: система, интерфейс, трансляция адресов, IP, ICMP, TCP и UDP. Затем показали два примера, один из которых позволил определить MTU интерфейса, а другой - просмотреть таблицу маршрутизации маршрутизатора.

Мы завершили главу рассмотрением SNMP ловушек. Это способ, предоставляющий агенту возможность уведомить менеджера о том, что произошло какое-либо событие, которое будет интересно менеджеру. Здесь же кратко описаны ASN.1 и BER. Две последние темы, скорее всего, являются наиболее сложными аспектами SNMP, однако они необходимы только для разработчиков.

Упражнения

  1. Мы сказали, что использование двух различных портов (161 и 162) позволяет системе запускать как менеджера, так и агента. Что произойдет, если будет использоваться один и тот же порт?
  2. Как Вы можете получить полный список таблицы маршрутизации с использованием get-next?

Сбор информации о сервере и инфраструктуре – очень важная часть работы системного администратора. Существует множество инструментов для сбора и обработки таких данных, и многие из них основаны на технологии SNMP.

SNMP (simple network management protocol, простой протокол сетевого управления) – это стандартный протокол для управления устройствами в IP-сетях. С его помощью серверы могут обмениваться информацией о своем текущем состоянии, а администратор может изменять предварительно определенные значения. Сам протокол очень простой, однако структура основанных на нём программ может оказаться сложной.

Данная статья ознакомит вас с основами протокола SNMP: базовыми понятиями, методами работы, случаями его применения, различными версиями протокола и т.д.

Базовые понятия

Протокол SNMP реализуется на прикладном уровне сетевого стека. Протокол был разработан для согласованного сбора информации из самых разных систем. SNMP использует стандартизированные методы запроса информации и пути.

Существует много различных версий протокола SNMP. Кроме того, протокол частично реализуется некоторыми сетевыми аппаратными устройствами. Наиболее распространённой является версия SNMPv1, но она имеет много уязвимостей; на самом деле, основными причинами её популярности являются её вездесущность и долгое время существования. Вместо неё рекомендуется использовать более безопасную версию SNMPv3.

Сеть на основе SNMP в основном состоит из SNMP-агентов. Агент – это программа, которая собирает информацию об аппаратном устройстве, систематизирует её в предварительно определенные записи, а также отвечает на запросы с помощью протокола SNMP.

Компонент, который запрашивает данные у агентов, называется менеджером SNMP. SNMP-менеджеры получают данные о всех управляемых устройствах и могут выдавать запросы для сбора информации и устанавливать некоторые свойства.

Менеджеры SNMP

Менеджер SNMP – это машина, которая запрашивает информацию, собранную агентами SNMP. Такая машина гораздо проще устроена, чем клиенты, поскольку она просто запрашивает данные.

Менеджером может быть любая машина, которая может отправлять запросы агентам SNMP, предоставляя валидные учётные данные (например, сервер мониторинга); иногда задачи менеджера выполняет сам администратор с помощью простых утилит для быстрого запроса данных.

Почти все команды SNMP предназначены для менеджера. Например:

GetRequest
GetNextRequest
GetBulkRequest
SetRequest
InformRequest
Response

Кроме того, менеджер может отвечать на Trap и Response.

Агенты SNMP

Агенты SNMP выполняют основную работу. Они отвечают за сбор данных о локальной системе, их хранение в удобном для запросов формате, обновление БД management information base (или просто MIB).

MIB – это иерархическая предварительно определенная структура, хранящая информацию, которую можно запросить или добавить. Она доступна для запросов SNMP, исходящих от хоста, предоставившего правильные учетные данные (т.е. менеджера SNMP).

Агент определяет, какие менеджеры могут получить доступ к данным. Также агент может выступать в качестве посредника и передавать информацию на устройства, не настроенные для SNMP-трафика.

Агенты SNMP отвечают на большинство команд протокола, среди которых:

GetRequest
GetNextRequest
GetBulkRequest
SetRequest
InformRequest

Также он может отправлять сообщения Trap.

Кратко о MIB

Management Information Base, или MIB – пожалуй, самый сложный компонент системы SNMP. Это иерархическая глобально стандартизированная база данных, которая следует стандартам агентов и менеджеров системы.

Проще всего структуру MIB можно представить в виде перевёрнутого дерева. Каждая ветвь получает порядковый номер (начиная с 1) и уникальную для этого уровня иерархии строку.

Чтобы сослаться на определённый узел, нужно отследить к нему путь в базе. Идентификаторы узла (номера и строки) можно использовать как адрес. Каждый узел в иерархии обозначается точкой. Таким образом, адрес содержит ряд идентификационных строк или чисел, разделенных точками. Такой адрес называется идентификатором объекта (или OID).

MIB предоставляет стандартные ветки, которые может использовать любое устройство. Однако при внедрении SNMP в свое устройство вы можете создавать пользовательские ветки.

Все стандартные ветки принадлежат одной родительской структуре. Эта ветка определяет информацию для спецификации MIB-2 (это пересмотренный стандарт для совместимых устройств).

Базовый путь к этой ветке:

iso.org.dod.internet.mgmt.mib-2

  • Часть 1.3.6.1 или iso.org.dod.internet – это OID, который определяет интернет-ресурсы.
  • 2 или mgmt определяют подкатегории управления.
  • 1 или mib-2 определяют спецификацию MIB-2.

Запрашивая информацию устройств, вы заметите, что большинство адресов начинается с 1.3.6.1.2.1.

Команды протокола SNMP

Отчасти протокол SNMP популярен благодаря простым командам. Он выполняет всего несколько операций, но они достаточно гибки.

Следующие блоки данных протокола описывают точные типы сообщений, которые поддерживает протокол:

  • Get: это сообщение менеджер отправляет агенту, чтобы запросить значение определённого OID. В ответ этот запрос получает сообщение Response, содержащее все необходимые данные.
  • GetNext: это сообщение позволяет менеджеру запрашивать следующий последовательный объект в MIB. Так можно пересечь структуру MIB, не используя в запросах OID.
  • Set: это сообщение менеджер отправляет агенту для того, чтобы изменить значение переменной. С помощью Set можно управлять информацией о конфигурации или иным образом изменять состояние удаленных хостов. Это единственная операция записи, которую поддерживает протокол.
  • GetBulk: этот запрос работает как несколько запросов GetNext. Менеджер получит ответ максимальный объём данных (учитывая ограничения запроса).
  • Response: агент отправляет это сообщение менеджеру, чтобы передать ему запрашиваемые данные. Если запрашиваемые данные нельзя передать, response будет содержать ошибку с дополнительной информацией. Сообщение response отправляется на любой из вышеперечисленных запросов, а также на сообщение Inform.
  • Trap: это сообщение обычно отправляется агентом менеджеру, чтобы предоставить информацию о событиях, которые происходят на управляемых устройствах.
  • Inform: такое сообщение менеджер отправляет агенту в ответ на trap. Если агент не получит такого сообщения, он будет повторно отправлять сообщения trap.

Версии протокола

С момента выхода протокол SNMP прошел через множество изменений. Первая реализация SNMP, сейчас известная как SNMPv1, появилась в 1988 году и состояла из RFC 1065, RFC 1066 и RFC 1067. Эта версия до сих пор широко поддерживается, однако она имеет множество проблем с безопасностью (например, аутентификация в виде обычного текста), поэтому её использование крайне нежелательно, особенно это касается незащищенных сетей.

Работа над версией 2 данного протокола началась в 1993 году. Эта версия предлагает ряд существенных улучшений представленных ранее стандартов. В этой версии была представлена модель безопасности на основе сторон, которая устраняет уязвимости, связанные с предварительным пересмотром. Тем не менее, новую модель безопасности оказалось достаточно сложно реализовать, потому популярной она не стала.

Поэтому появились дополнительные релизы версии 2, каждый из которых сохранил основную часть усовершенствований версии 2, но изменил модель безопасности. Версия SNMPv2c возобновила модель безопасности на основе сообществ (которая была использована в v1); это была самая популярная версия протокола v2. Другая реализация, SNMPv2u, основана на пользовательской модели безопасности, также не стала популярной.

В 1998 вышла третья версия SNMP (текущая). Она предлагает пользовательскую систему безопасности, которая позволяет устанавливать требования к аутентификации с помощью одной из этих моделей:

  • NoAuthNoPriv: пользователи, подключающиеся на этом уровне, не имеют учётных данных для аутентификации; отправленные и полученные ими сообщения находятся в общем доступе.
  • AuthNoPriv: на этом уровне для подключения нужно пройти аутентификацию, но сообщения не будут зашифрованы.
  • AuthPriv: обязательная аутентификация, сообщения шифруются.

Кроме новых моделей аутентификации был реализован механизм контроля доступа, который управляет доступом пользователей к веткам. Версия 3 также может использовать протоколы безопасности SSH или TLS.

Tags: ,
Поделиться: