Вы находитесь на странице: 1из 41

Introducción a SNMP con Python:

PySNMP (Parte 1) - El protocolo y los


comandos
Por Gaël Pegliasco - publicado el 03/03/2016, publicado en 22/04/2016
SNMP es un protocolo de supervisión de red universalmente popular. Este es el estándar
utilizado por casi todos los equipos de red. Le permite monitorear (consultar y modificar)
todos los tipos de hardware, desde el enrutador hasta la impresora, e incluso algunas
cafeteras conectadas.

Introducción - Parte uno


Este tutorial le propone descubrir la biblioteca de Python PySNMP que permite dialogar
con cualquier material compatible con el protocolo del mismo nombre.

Sin embargo, antes de embarcarse en una presentación técnica que describe cómo ejecutar
una consulta "get" o "set" en SNMP v2 o v3, proponemos una presentación de los
conceptos de este protocolo. Esto le permitirá comprender mejor los entresijos de la librería
con el fin de llevarlo al Grial absoluto de su completo dominio.

En esta primera parte presentamos el protocolo SNMP y el uso de comandos del sistema
que le permitirán tocar los conceptos que exponemos.

Al final de este tutorial de 4 partes, normalmente podrás:

 Ejecutar consultas GET / SET


 Enviar trampas
 Cree sondeos para herramientas de supervisión como Nagios , Centreon y otros.
 Crear un agente SNMP
Antes de seguir leyendo este artículo, si es nuevo en el tema, lo invito a leer esta
introducción a la supervisión que le dará las bases técnicas para comprender este trabajo,
así como sus problemas y herramientas a su disposición. Esta lectura te ayudará a ubicar
mejor el lugar de SNMP en este universo. El documento está muy orientado Nagios y
derivados, pero le proporcionará todos los elementos básicos para comprender
correctamente esta disciplina.

plan
 Presentación del protocolo
o SNMP

o MIB
o ASN1
o Marque con agentes usando los comandos del sistema
 pysnmp
o Elementos básicos
o Las solicitudes
o Las tablas
o Usa tus MIB con un agente

¿Qué es SNMP?
SNMP significa Protocolo simple de administración de red

Es un protocolo de gestión de red.

Concretamente permite supervisar el estado de la red de equipos o un parque informático,


así como el material como los servicios:

 Enrutadores, interruptores
 Estaciones de trabajo
 impresoras
 Servicios (mensajería, ftp, ssh, http, proceso, memoria ...)

Por supervisión, es necesario entender "para obtener información" sobre el estado de estos
"elementos". Pero este protocolo también permite llevar a cabo acciones de mantenimiento
como reiniciar un servicio o una máquina, limpiar los cabezales de lectura de una
impresora, etc.
Cómo funciona SNMP

SNMP se basa en la idea de que un sistema de supervisión de red consiste en:

 Nodos administrados, cada uno con un agente


El agente es el servicio (software) que dialoga con los gerentes para intercambiar
información sobre el estado del nodo
 Al menos una estación de administración, el administrador (Network Management
Station)
 Un protocolo para intercambiar información entre los agentes y el NMS, este
protocolo es SNMP

El sitio de wikipedia ofrece una breve presentación de este último en su versión en francés.
La versión en inglés del mismo artículo es mucho más completa y cita el conjunto de RFC
que la describen.

Gerente y agentes (fuente PySNMP )

¿Cómo funciona?

 El administrador envía solicitudes de tipo "GET" a los agentes para recuperar


información sobre un servicio / máquina a través del protocolo SNMP
 También puede enviar solicitudes "SET" para modificar el estado de los servicios y /
o la máquina administrada por el agente
 Los agentes pueden enviar solicitudes de "TRAP" al administrador para informar un
mal funcionamiento
 Los agentes se pueden agrupar a través de un "agente maestro"
 La información accesible y provista por los agentes se organiza en una base de datos
"virtual" llamada MIB.
Esta base está estandarizada.

Intercambio de solicitudes entre el administrador y los agentes (fuente wikipedia )

Eso es todo. Es simple ?

¿Por qué usar SNMP?

 Es un protocolo muy antiguo y es compatible con casi todos los proveedores de


hardware de red.
 Desde las versiones 2 y 3 es seguro, ofrece acceso restringido a cierta información y
se basa en protocolos de encriptación como SSH y TLS (pero con sus propias
bibliotecas y herramientas internas).
 La información contenida en las MIB está estandarizada, es decir que sea cual sea el
dispositivo y su fabricante, se podrá acceder a la misma información en el mismo
lugar y de la misma manera. Y eso es genial:
"Usted es un administrador de red, desea conocer la memoria total y disponible de
una máquina, la obtendrá de la misma forma sea cual sea el sistema operativo (mac /
windows / unix / android) y el hardware utilizado (AMD, ARM, Intel, ...) ". ¿No es
fabuloso?
 Es simple (los agentes son livianos, la complejidad es deportada a nivel de los
gerentes)
 Es independiente de la arquitectura de red y los elementos (PC, impresoras,
enrutadores, ...)
 Es extensible, puede personalizar las bases de datos además de lo que ofrece el
estándar
 Él es robusto. Se basa en UDP o TCP:
Todavía funcionará cuando la red tenga graves problemas de cuello de botella: un
marco de información UDP es liviano.

¿Es tan bueno?

En general, es bastante bueno y, sobre todo, tiene pocos competidores maduros y


generalizados, pero:

 A veces, sin embargo, no es muy simple: los MIB son "legibles por el hombre",
pero para citar a uno de mis colegas, a veces, los que llegan allí no son realmente
humanos.
 El protocolo es simple pero su implementación puede ser mucho más compleja.
 La versión 3 ha implementado su propia capa SSH en lugar de hacer HTTPS (HTTP
sobre SSH). Esto dificulta la comunicación: no hay autonegociación para el cifrado
y debe proporcionar 5 información para crear una conexión segura.
 Algunos competidores están empezando a surgir como WMI y ofrecen un lenguaje
de consulta más rico (WQL).

histórico

 La primera versión del protocolo data de 1989


No ofrece seguridad y utiliza la versión 1 de MIB, que sigue siendo bastante simple
 La segunda versión fue publicada en 1993
o Brinda más seguridad en términos de autenticación y encriptación
o Permite la administración distribuida
o Trae una versión más rica de la MIB (MIB-2)
 La versión 3 fue publicada en 1998
o Trae transacciones cifradas a través de SSH
o Es más modular
En los hechos

 La versión 2 tuvo problemas para comenzar y se hicieron varios "lanzamientos". Es


la versión "2c" que ha ganado. Le aconsejo sobre este tema leyendo esta
presentación de SNMP que describe un poco más estas dificultades de puesta en
marcha y la presentación de PySNMP que toma algunos de estos puntos.
 Versión 3, al igual que la v2 también ha tenido problemas para imponerse. No es
compatible con todos los materiales de hoy aunque ha mejorado. Los problemas de
seguridad se han vuelto muy sensibles hoy en día y es la versión recomendada.
 SNMP domina el mundo TCP / IP y es el estándar recomendado desde mayo de
1990

MIB
Antes de que podamos lanzar nuestras primeras consultas SNMP, es importante entender
qué es una MIB.

La Base de información de gestión es una base de datos "virtual" para organizar


jerárquicamente la información proporcionada por los agentes en el equipo.

Esta no es una base de datos estrictamente hablando como una base de datos relacional.
Existe solo a través del agente que es libre de implementarlo como lo desee. Cuando el
agente no funciona, no hay datos en el MIB. Solo existe la descripción del MIB
(generalmente un archivo de texto).

Un MIB en realidad describe cómo numerar / acceder a la información.

Es el agente (el software) el que almacena (pero debería decir que gestiona) esta
información, que a menudo es "volátil", como quiere.

Es muy importante comprender el punto anterior, que es lo que a menudo dificulta la


comprensión de las MIB por parte de los recién llegados en este protocolo.

Tome el ejemplo de la cantidad de procesos activos en una máquina. Éste está identificado
de manera única por el MIB-II. Pero esta información es solicitada por el agente del sistema
operativo cuando recibe una solicitud para este último, porque estos datos están cambiando
en todo momento. Por lo tanto, no es "almacenado" por el sistema operativo. No es
accesible a través de una consulta SQL. Se proporciona cuando se solicita, y siempre que el
agente no lo haya solicitado al sistema operativo, no está realmente disponible o aún no
existe:

 El gerente le pide la información al agente


 El agente recibe la solicitud y llama a un sistema primitivo para obtenerlo
 El agente devuelve la información al gerente
Es información "volátil" que no es realmente almacenable.

Una gran cantidad de información de MIB es de esta naturaleza, otros a veces se almacenan
en algún lugar, como la persona a cargo de una máquina, el puerto de un servicio o el
estado de una línea de alimentación o un diodo (apagado, encendido) De acuerdo con los
constructores / OS, esta información se almacena físicamente de manera diferente, pero la
MIB se estandariza para la gran mayoría, de modo que el gerente siempre solicita la misma
información de la misma manera. Depende del agente averiguar a dónde ir dependiendo del
material / servicio que se maneja.

Y eso brinda mucha facilidad en la escritura de herramientas de prueba / supervisión. Esta


es una de las grandes fortalezas de este estándar.

MIB-II

Una de las MIB más conocidas es MIB-II, descrita por RFC 1213 .

Se implementa en casi todos los dispositivos TCP / IP.

Tiene diez grupos:

 sistema
 las interfaces
 Traducción de direcciones
 IP
 ICMP
 TCP
 UDP
 EGP "
 transmisión
 y SNMP

Es decir, cualquier información que pueda solicitar sobre MIB-II se colocará en uno de
estos grupos.
Algunos ejemplos de información que puede encontrar en estos conjuntos son:

 la lista de procesos (con información de memoria y CPU);


 velocidades de red;
 el promedio de carga;
 uso de memoria;
 contacto del sistema, tiempo de actividad;
 el uso de espacio en disco;
 las tablas de enrutamiento

Ejemplo de una descripción de un MIB

Finalmente, los mibs se describen en un "lenguaje" llamado ASN.1.

El siguiente ejemplo muestra la información "descripción de la interfaz (red)" como se


describe en ASN.1:

ifDescr OBJETO DE TIPO


SYNTAX DisplayString (SIZE (0..255))
ACCESO solo lectura
ESTADO obligatorio
DESCRIPCIÓN
"Una cadena de texto que contiene información sobre el
interfaz. Esta cadena debe incluir el nombre de
el fabricante, el nombre del producto y la versión
de la interfaz de hardware ".
:: = {ifEntry 2}

Leer la definición de estos datos es bastante comprensible por sí mismo.


Indicamos aquí:

 su nombre, "ifDescr"
 su tipo, "DisplayString", una cadena de hasta 255 caracteres
 su modo de acceso, "solo lectura"
 su estado, "obligatorio"
 finalmente su ubicación en el nodo padre "ifEntry": segundo subelemento del nodo
"ifEntry"

Organización de información en MIB

Para comprender esta descripción "jerárquica" de los datos "ifDescr", aquí hay un gráfico
que representa la jerarquía principal de todas las MIB:
Jerarquía principal de un MIB ( Servicio de Wikipedia )

El gráfico de arriba muestra la estructura jerárquica de las MIB.


Debajo del nodo raíz, señalado ". »Son 3 información numerada:

 CCITT con el número 0


 ISO con el número 1
 ISO - CCITT con el número 2

Debajo del nodo ISO hay 4 información, también numerada:

 estándar, con el número 0


 autoridad de registro, con el número 1
 miembro del cuerpo, con el número 2
 organización, con el número 3

La ruta a la información de la organización bajo "ISO", que se encuentra debajo de la raíz,


será ".1.3" o ".ISO.organization"
Y así enseguida.

Por ejemplo, el acceso a la información "MIB-2" se realizará a través de la ruta


".1.3.6.1.2.1" o ".ISO.organization.DoD.Internet.management.MIB-2"
Y ahora, usted sabe todo sobre las MIB: definen la información en ASN.1, que es accesible
a través de una ruta expresada con números o nombres de información principal.
OIDs

Por lo tanto, la información se numera de acuerdo con su orden en el árbol MIB, estos
números se denominan OID (Object IDentifier).
Aquí hay algunos ejemplos de OID:

 .1.3.6.1.2.1.1 sistema: tiempo de actividad, contacto, nombre


 .1.3.6.1.2.1.2 interfaces: interfaces de red
 .1.3.6.1.2.1.4 enrutamiento ip: ip, etc.
 .1.3.6.1.2.1.5 icmp: errores icmp, descartes ... (icmp es, por ejemplo, ping)
 .1.3.6.1.2.1.6 / 7 tcp o udp: estado de conexión tcp o udp

La pregunta ahora se convierte en "¿cómo encontrar toda la información disponible en un


MIB? "
Las respuestas serán:

 Al leer los estándares y estándares asociados: https://tools.ietf.org/html/rfc1213


 Ejecutando consultas con herramientas SNMP que le permiten navegar por el árbol
completo de una MIB.
 Examinando estos MIB a través de sitios web que tienen la amabilidad de
representarlos fácilmente, como el sitio web de IP MONITOR .

Se observará en este último que el OID " 1.3.6.1.2.1.2.2.1.2 " proporciona la ruta completa
a la información " ifDescr ".
Esto es lo que haremos PySNMP: enviar consultas preguntando el valor de un nodo
(información) ubicado en una ubicación específica en un MIB o cambiando este valor.

Y es todo. O casi. ¿Ves un poco más claro?

La práctica se acerca.

Un universo de MIB

Hay muchos MIB:

 Dependiendo del hardware (enrutador, impresora), la información es diferente.


 Por esta razón, algunos dispositivos o constructores proporcionan sus propios MIB
que definen una rama en el árbol OID, con un número oficial definido por la
Autoridad de números asignados de Internet (IANA).
Por ejemplo, encontramos CISCO en esta rama del árbol:
iso.org.dod.internet.private.entreprise.cisco = 1.3.6.1.4.1.9
En esta ubicación, CISCO es libre de ofrecer MIB describiendo la información de
su propio hardware como lo considere oportuno. Muchas otras compañías hacen lo
mismo, como Alcatel / Nokia por nombrar algunas.
El sitio de IP Monitor tiene muchas bases de datos (mib) para diferentes tipos de
información / materiales / servicios que puede consultar.

Comunidades
El acceso a la información de un MIB se filtra por lo que se llama la "comunidad", excepto
la versión 3 del protocolo.
"Comunidad" es un tipo de palabra compartida, "pública" por defecto.

"Público" puede estar cerca del inicio de sesión "anónimo" disponible en la mayoría de los
servidores ftp.

Una solicitud de información siempre se ejecuta a través de una comunidad.


Dependiendo de la comunidad utilizada, la información recibida será diferente:

 La comunidad "pública" da acceso al nivel de "solo lectura".


 Hay un nivel privado de lectura / escritura (comunidad "privada") que con mayor
frecuencia está deshabilitado (da acceso a toda la configuración del sistema por
escrito)

Por lo tanto, cuando desee acceder o editar la información de un agente, usted:

 enviar una solicitud GET / SET al agente


 proporcionando la ruta de la información deseada, su OID
 proporcionando la comunidad utilizada ("privada" para los cambios)
 proporcionando el nuevo valor de los datos en caso de modificación
 proporcionar la dirección IP / nombre de dominio o ejecutar el agente
 el puerto utilizado es por defecto el puerto 161

Usando el protocolo de línea de comando


Para comprender completamente lo que este protocolo permite, propongo ejecutar los
comandos básicos con las herramientas del sistema.
Esto tocará los mecanismos subyacentes y garantizará que los agentes entiendan sus
consultas antes de escribirlas en Python.

Las órdenes

Antes de lanzar nuestros primeros pedidos, veamos los tipos de solicitudes que el protocolo
propone para permitir que los administradores y agentes intercambien información:

 Obtenga : solicitando el valor de un OID por el administrador al agente


El agente devuelve la información a través de un mensaje tipo Respuesta
 GetNext : solicite la siguiente información en el MIB
Explora una MIB sin saber lo que contiene
 Establecer : cambia el valor asociado con un OID
Cambiar la configuración o cambiar el estado de un host
 GetBulk : solicita un conjunto completo de información en una sola consulta.
Evite multiplicar Get y GetNext
 Respuesta : mensaje enviado por el agente al administrador que contiene la
información solicitada
 Trampa : mensaje enviado por el agente al administrador para informar un
problema
 Informar : mensaje enviado por el gerente para confirmar la recepción de la trampa

Requisitos previos

Para lanzar nuestros primeros pedidos, es necesario tener un agente y un gerente.


Recomiendo este excelente tutorial para dicha instalación en una máquina Linux (tipo
debian).
Para el administrador, puede instalar las herramientas básicas snmp y mib a través de estos
comandos

sudo apt-get install snmp snmp-mibs-downloader


sudo apt-get install smitools libsmi

Entonces necesitas un agente.

Para encontrarlo, puedes:

 Pruebe con una impresora de red o una máquina con una dirección IP
Generalmente son compatibles con el protocolo SNMP
 Instale su propio agente siguiendo el tutorial mencionado anteriormente
 Inicie sus pedidos al agente "demo.snmplabs.com" de acceso libre a través de
Internet, lo cual haremos.

Finalmente, si no tiene la posibilidad de instalar comandos SNMP en su Linux, sepa que la


biblioteca PySNMP ofrece scripts equivalentes puros de Python que puede instalar con el
comando "pip install pysnmp-apps".

El comando "OBTENER"

Acepta varios parámetros, que incluyen:

 "-v": versión del protocolo


 "-c": comunidad
 "-O": formato de salida (prueba a, f, n, s, ...)

Ejemplo:

$ snmpget -v2c -c public -Oa demo.snmplabs.com sysDescr.0


SNMPv2-MIB :: sysDescr.0 = STRING: SunOS zeus.snmplabs.com 4.1.3_U1 1
sun4m

La versión de protocolo a usar es obligatoria, en el comando anterior usamos el protocolo


de la versión 2c y la comunidad "pública".
Solicitamos la información "sysDescr". Para hacer esto agregamos la ruta ".0" que designa
"el valor del nodo sysDescr".

Los otros valores debajo de un nodo (.1, .2, etc.) designan los subelementos de este último.
Por lo tanto, la información puede solicitarse a través de la ruta completa en forma de un
OID digital " 1.3.6.1.2.1.1.1. 0 " (o texto) o mediante el nombre corto. Porque es
normalmente único.

Entonces puede reiniciar el comando de arriba con el OID digital ...

El comando "Obtener siguiente"

Acepta los mismos parámetros que "GET" pero no devuelve el OID solicitado, sino el que
sigue en el árbol. Al agrupar un GET y varios GET NEXT, puede consultar todo el árbol de
un MIB.

$ snmpgetnext -v2c -Oa -c public -Os demo.snmplabs.com sysDescr.0


sysObjectID.0 = OID: empresas.20408
$ snmpgetnext -v2c -On -c public -Os demo.snmplabs.com sysObjectID.0
sysUpTimeInstance = Timeticks: (179062573) 20 días, 17: 23: 45.73

Puede ejecutar GET NEXT en cualquier nodo, por lo que la raíz de un MIB.

Pero caminar un árbol es un trabajo duro.

Comandos "Obtener masiva y caminar"

Para evitar enviar varios comandos "GET" uno después del otro, lo que sobrecarga los
intercambios de red, es posible solicitar consultar varios OID a la vez a través del comando
"GET BULK". Pero no todos los agentes lo admiten.

También puede utilizar el comando "Walk" para navegar por un árbol completo, como lo
haría con "GET" y "GET NEXT". Pero es el comando "WALK" el que los ejecutará por ti.

$ snmpwalk -v2c -On -c public -Os demo.snmplabs.com system


sysDescr.0 = CADENA: SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m
sysObjectID.0 = OID: empresas.20408
sysUpTimeInstance = Timeticks: (179082328) 20 días, 17: 27: 03.28
sysContact.0 = STRING: SNMP Laboratories, info@snmplabs.com
sysName.0 = STRING: zeus.snmplabs.com
sysLocation.0 = STRING: Moscú, Rusia
sysServices.0 = INTEGER: 72
sysORLastChange.0 = Timeticks: (179082382) 20 días, 17: 27: 03.82
sysORID.1 = OID: empresas.20408.1.1
sysORDescr.1 = STRING: nuevo comentario
sysORUpTime.1 = Timeticks: (123) 0: 00: 01.23

Traducir OID

El comando "snmptranslate" se utiliza para traducir los OID del modo numérico al modo de
texto y viceversa.

$ snmptranslate -On SNMPv2-MIB :: sysDescr.0


.1.3.6.1.2.1.1.1.0
$ snmptranslate 1.3.6.1.2.1.1.1.0
SNMPv2-MIB :: sysDescr.0

Edite un OID, el comando "SET"

El comando "snmpset" se usa para modificar el valor de un OID.


Solo está disponible con el protocolo v2 y la comunidad "privada" o el protocolo v3.
El siguiente ejemplo se proporciona para el protocolo v3.

Los parámetros utilizados son:

 "-u": usuario
 "-l": nivel de seguridad para identificarte
 "-a": protocolo de autenticación
(encriptación de contraseña)
 "-A": contraseña de autenticación
 "-x": algoritmo de cifrado para la conexión
 "-X": contraseña / sal para encriptar la conexión

Aquí es donde descubrimos el dolor del protocolo v3 que implementa las conexiones SSH
sin hacer SNMP sobre SSH: no hay autonegociación de algoritmos de cifrado, es necesario
especificar todo ¡por uno mismo! Miserable!

$ snmpget localhost sysLocation.0


SNMPv2-MIB :: sysLocation.0 = STRING: Rouans
$ snmpset -u demo -l authPriv -a MD5 -x DES-pass1 -X pass2 localhost
sysLocation.0 s " Tierra "
SNMPv2-MIB :: sysLocation.0 = CADENA: Tierra
$ snmpget localhost sysLocation.0
SNMPv2-MIB :: sysLocation.0 = CADENA: Tierra
Recomendaciones para usar SNMP y herramientas relacionadas

Las versiones 1 y 2 del protocolo son insuficientemente seguras y nada para el primero.

La protección en la versión 2 del protocolo se realiza solo a través de "comunidades" que


no usan una contraseña. Esto es muy débil como tipo de protección porque solo necesita
saber el nombre de la comunidad para acceder a la información de un material que podría
ser confidencial.

Los agentes de WindowsXP eran especialmente conocidos por ofrecer demasiada


información sensible en su configuración predeterminada, como los inicios de sesión de los
usuarios a los que se podía acceder directamente a través de la comunidad "pública".

En la práctica, el agente proporcionado por las herramientas NetSNMP (en Linux) es


relativamente lento y no está necesariamente muy bien protegido, muchos defectos se
descubren regularmente.

Por lo tanto, sea cual sea la solución elegida, siempre apague el modo anónimo o verifique
cada información provista.

Luego, cree acceso ACLS a cada MIB por usuario para tener control completo sobre quién
puede hacer qué.

Finalmente, no podemos recomendar demasiado privilegiar exclusivamente la versión 3 del


protocolo.

conclusión
Los comandos básicos de SNMP son bastante simples una vez que comprende cómo
manipular los parámetros que utilizan.

Esta primera parte de la iniciación de SNMP debería haberle dado:

 Una comprensión global del protocolo


 Una buena idea sobre cómo acceder y manipular la información MIB, con
comandos del sistema

La segunda parte de este tutorial sobre SNMP y PySNMP está dedicada al descubrimiento
de PySNMP:

 Instalar PySNMP

 Sepa cómo manipular los componentes básicos (OID, Comunidades, Usuarios,


Contextos, ...)
 Ejecutar consultas GET / GETNEXT / SET
La tercera parte de este tutorial lo llevará más lejos en el uso de PySNMP para enseñarle
cómo leer tablas de datos .

Finalmente, la cuarta parte le enseñará cómo crear un agente usando un MIB personalizado.

Introducción a SNMP con Python:


PySNMP (Parte 2) - Uso de la biblioteca
Por Gaël Pegliasco - publicado el 03/03/2016, publicado en 25/04/2016.
SNMP es un protocolo de supervisión de red universalmente popular. Este es el estándar
utilizado por casi todos los equipos de red. Le permite monitorear (consultar y modificar)
todo tipo de hardware, desde el enrutador hasta la impresora, e incluso algunas cafeteras
conectadas. Esta segunda parte del tutorial te presenta la biblioteca PySNMP

introducción
Este tutorial le propone descubrir la biblioteca de Python PySNMP que permite dialogar
con cualquier material compatible con el protocolo del mismo nombre.

En esta segunda parte, presentaremos el uso del protocolo SNMP a través de la biblioteca
PySNMP .

Puede comenzar a aprender directamente de esta segunda parte si ya conoce el protocolo


SNMP.

Sin embargo, si es nuevo en este protocolo, le recomendamos que lea de antemano la


primera parte de este tutorial que le presentará el protocolo SNMP , sus cualidades y
defectos y le proporcionará las herramientas básicas para comenzar a usarlo y usted
propiedad. Sin este conocimiento preliminar, este segundo capítulo puede parecer muy
difícil de entender.

Al final de esta segunda parte, normalmente podrá:


 Para manipular los elementos OID básicos, comunidades, cuentas de usuario,
contextos, ...
 Para usar tus propios MIB
 Ejecute consultas GET / GETNEXT / SET y simule WALKs
 Cree sondeos para herramientas de supervisión como Nagios , Centreon y otros.

plan
 Presentación del protocolo
o SNMP

o MIB
o ASN1
o Las solicitudes
 pysnmp
o Las solicitudes
o Las tablas
o Usa tus MIB con un agente

pysnmp
Ahora que hemos introducido el protocolo SNMP y algunos comandos para usarlo,
finalmente podemos pasar al tema real de este tutorial: ¡la biblioteca PySNMP!
PySNMP es una biblioteca de Python que implementa todas las versiones del protocolo
SNMP por completo en Python.

Sus principales características son:

 Completo: implementa todo el protocolo SNMP (v1 a v3) completamente en Python


 Bastante ligero, alrededor de 15000 líneas de código
 Lo suficientemente simple para cosas simples
 Ampliamente utilizado en la comunidad: 30,000 descargas por mes en Pypi
 Muy útil para escribir nagios / centeron / otras sondas o recuperar información de
SNMP en sus programas de Python
 Le permite escribir sus propios agentes
 A veces es complejo y carece de documentación clara de ciertos elementos tales
como
Instalando PySNMP

La instalación de la biblioteca es simple, es Python:

$ pip install pysnmp

Sin embargo, en máquinas con Windows, el comando "pip" generalmente fallará en la


instalación de "pycrypto" que "pip" quiere compilar. Pero estos últimos a menudo se ven
privados de tales herramientas.
En este caso, instale previamente un binario "pycrypto" desde este sitio o desde este sitio
para Python 3.5 .

Si realmente tiene dificultades, siga este tutorial de instalación de PySNMP en Windows


escrito especialmente a petición de nuestros lectores.

Manipular datos ASN.1

Con PySNMP podrá manipular datos en formato ASN.1 ya que es el utilizado por el
protocolo SNMP.

La biblioteca PySNMP se basa en otra biblioteca: pyasn1 para lograr esto.


La conversión de tipos ASN.1 a python es casi natural:

de pyasn1.type.univ import *
a = Entero ( 21 ) * 2
imprimir ( a )
a = Entero ( - 1 ) + Entero ( 1 )
imprimir ( a )
a = int ( Entero ( 42 ))
imprimir ( a )
a = OctetString ( 'Hello' ) + ',' + OctetString ( hexValue =
'5079534e4d5021' )
imprimir ( a , tipo ( a ))

Comandos básicos

PySNMP ofrece varias funciones de "bajo nivel" para usar el protocolo SNMP, pero se
recomienda utilizar el módulo "hlapi" que significa "API de alto nivel".

Este último ofrece funciones de alto nivel, fácil de configurar para ejecutar los comandos
básicos que se pueden enumerar de esta manera

de la importación pysnmp.hlapi *
l = [ x para x en dir () si 'Cmd' en x ]
imprimir ( l )
ayuda ( 'pysnmp.hlapi.getCmd' )

que muestra
[ 'bulkCmd' , 'getCmd' , 'nextCmd' , 'setCmd' ]
Ayuda sobre la función getCmd en pysnmp . hlapi :
pysnmp . hlapi . getCmd = getCmd ( snmpEngine , authData ,
transportTarget , contextData , * varBinds , ** opciones )
Crea un generador para realizar una o más consultas SNMP GET .

Antes de usar estos comandos, aprenderemos cómo manipular los parámetros que
necesitan:

 Los OID que deseamos consultar / modificar


 Elementos de conexión de comunidad para el protocolo v2 o el usuario para el
protocolo v3
 ...

OIDS

Los OID son los identificadores de la información descrita en las MIB.


Un OID indica la ruta a seguir en el árbol MIB para encontrar la información; ".1.2.3.0"
podría entenderse como:

 ". "
Comenzando desde la plaza central, varias calles te miran.
 "1"
Toma el primero desde la izquierda
Llegas a un lugar nuevo.
 "2"
Varias calles te enfrentan nuevamente.
Toma el segundo a tu izquierda.
Llegas a un lugar nuevo.

 "3"
Varias calles te enfrentan nuevamente.
Toma el tercero a tu izquierda.
Llegas a un lugar nuevo.
 "0"
Hay una placa en el cuadro, contiene tu información.
Si envió un "GET" lo leyó, si envió un "SET" lo cambia.
Camino en el MIB

Un OID está representado por una secuencia de valores numéricos o por una serie de
nombres que designan cada rama atravesada en el MIB.
Si desea obtener más información sobre estos OID, lo invito a leer la documentación de
PySNMP sobre este tema .

Para crear un OID con PySNMP, es necesario crear una instancia de la clase
"ObjectIdentity"

Un OID se puede definir:

 Por una cadena de caracteres


 Por una tupla
 Por su redacción

Estas 4 instancias a continuación definen el mismo objeto

o = ObjectIdentity ( '1.3.6.1.2.1.1.3.0' )
o = ObjectIdentity (( 1 , 3 , 6 , 1 , 2 , 1 , 1 , 3 , 0 ))
o = ObjectIdentity ( 'SNMPv2-MIB' , 'sysUpTime' , 0 )
o = ObjectIdentity ( 'iso.org.dod.internet.mgmt.mib-
2.system.sysUpTime.0' )

Parece simple, pero para usar los problemas comienza:

de la importación pysnmp.hlapi *
o = ObjectIdentity ( '1.3.6.1.2.1.1.3.0' )
imprimir ( o . getLabel ())
imprimir ( o . getMibNode ())
imprimir ( o . getMibSymbol ())
imprimir ( o . getOid ())
imprimir ( o . prettyPrint ())
Seguimiento (última llamada más reciente):
Archivo "<...> / oid_example.py", línea 4, en <módulo>
impresión (o.getLabel ())
Archivo "<...> / site-packages / pysnmp / smi / rfc1902.py", línea 185,
en getLabel
elevar SmiError ('% s no completamente inicializado'% self .__ class
__.__ name__)
pysnmp.smi.error.SmiError: el objeto ObjectIdentity no se ha
inicializado por completo

Pero ¿por qué este error? Los ejemplos de la documentación de PySNMP son bastante
torpes a este respecto:

>>> desde pysnmp.hlapi import *


>>> x = ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' , 'sysDescr' , 0 ),
'Linux i386 box' ))
>>> # ... llamando a la búsqueda MIB ...
>>> x [ 0 ] . prettyPrint ()

Es necesario buscar realmente este OID en la MIB, no es automático porque hay muchas
MIB. PySNMP viene con todo un arsenal de Mibs, pero tienes que decirle dónde
encontrarlos.

¡Y para esa documentación es muy desafortunado porque nunca muestra un ejemplo


real!

Usted tiene el derecho de molestar; Una vez que sus nervios se hayan calmado, recuerde
que es un producto OpenSource y que tiene la suerte de tener acceso al código.
El comando "ayuda" de Python muestra que hay un método "resolveWithMib".

Este método toma como parámetro un objeto "MibViewController".


La función de este controlador es resolver el emparejamiento "OID" / MIB.
La documentación de la clase "MibViewController" es casi inexistente. Esta clase toma un
objeto "MibBuilder" como argumento cuando se crea.
Entonces tienes que ir a ver la clase "MibBuilder"

Pero una pequeña búsqueda en el árbol de PySNMP muestra que aparentemente se obtiene
un "MibViewController" del motor SNMP Engine.
El motor es, de alguna manera, el corazón de la biblioteca PySNMP que le permite
interactuar con los diferentes elementos del protocolo (mensajes, hosts, comunidades, OID,
MIBS, etc.).

Puede tener varios motores para, por ejemplo, trabajar con múltiples MIB.

Nuestro código se convierte en:

de la importación pysnmp.hlapi *

se = SnmpEngine ()
mvc = se . getUserContext ( 'mibViewController' )
o resolveWithMib ( mvc )

o = ObjectIdentity ( '1.3.6.1.2.1.1.3.0' )
imprimir ( o . getLabel ())
imprimir ( o . getMibNode ())
imprimir ( o . getMibSymbol ())
imprimir ( o . getOid ())
imprimir ( o . prettyPrint ())

Por desgracia, todavía no estamos allí ...

Seguimiento (última llamada más reciente):


Archivo "<...> / PySNMP / oid_example.py", línea 7, en <módulo>
o.resolveWithMib (VCM)
Archivo "<...> / site-packages / pysnmp / smi / rfc1902.py", línea 355,
en resolveWithMib
addMibCompiler (mibViewController.mibBuilder,
AttributeError: el objeto 'NoneType' no tiene ningún atributo
'mibBuilder'

El controlador de vista mib no está definido porque no hemos creado un "UserContext".


La solución más simple es, en última instancia, crear nosotros mismos el
"MibViewController":

de la importación pysnmp.hlapi *
desde pysnmp.smi.view import MibViewController

se = SnmpEngine ()
mvc = se . getUserContext ( 'mibViewController' )
si no mvc :
mvc = MibViewController ( ver getMibBuilder ())

o = ObjectIdentity ( '1.3.6.1.2.1.1.3.0' )
o resolveWithMib ( mvc )
imprimir ( o . getLabel ())
imprimir ( o . getMibNode ())
imprimir ( o . getMibSymbol ())
imprimir ( o . getOid ())
imprimir ( o . prettyPrint ())

¡Y eso es todo!

('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2', 'sistema',


'sysUpTime')
MibScalar ((1, 3, 6, 1, 2, 1, 1, 3), TimeTicks ())
('SNMPv2-MIB', 'sysUpTime', (ObjectName ('0'),))
1.3.6.1.2.1.1.3.0
SNMPv2-MIB :: sysUpTime.

El controlador MIB utiliza el MIB PySNMP "generador" predeterminado que almacena las
versiones "pythonized" de MIBS en la subcarpeta de instalación pysnmp: "pysnmp / smi /
mibs /". No dude en echar un vistazo.

Trabaja con tu propia MIB

Para MIB estándar, sabes cómo hacerlo. Pero dirás:

"Sí, pero trabajo con MIB patentadas porque soy un constructor de hardware o utilizo un
hardware específico del fabricante y necesitaría mi propio MIB".
No hay problema, los OID pueden hacerlo por usted.

Supongamos que tiene su propia MIB, como la de abajo, que ha sido tomada de este tutorial
:

MAKINA_MIB DEFINICIONES :: = BEGIN

IMPORTACIONES
OBJETO DE TIPO, Integer32, NOTIFICACIÓN-TIPO, empresas
DESDE SNMPv2-SMI
;

MakinaCorpus OBJECT IDENTIFIER :: = {empresas 3}

dataValue OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS de solo lectura
ESTADO actual
DESCRIPCIÓN "Un conteo de muestra de algo".
:: = {MakinaCorpus 1}

dataDescription OBJETO DE TIPO


SYNTAX OCTET STRING
MAX-ACCESS de solo lectura
ESTADO actual
DESCRIPCIÓN "Una descripción de algo"
:: = {MakinaCorpus 2}

testTrap NOTIFICATION-TYPE
ESTADO actual
DESCRIPCIÓN "Notificación de prueba"
:: = {MakinaCorpus 3}
FIN

En general, las MIB de los fabricantes se almacenan en las "empresas" de OID: iso. org.
dod. Internet . privado Empresas (1.3.6.1.4.1)
El sitio del monitor IP parece mostrar que el subnodo ".3" es libre, por lo que lo elegí para
instalar el Makina MIB anterior, pero podría tomar un subnodo existente.

MakinaCorpus OBJECT IDENTIFIER :: = {empresas 3}

Ahora es necesario compilar esta MIB con PySMI . Normalmente esta biblioteca se instala
con PySNMP, de lo contrario ejecuta "pip install pysmi".
PySNMP viene con varios scripts, incluido "build-pysnmp-mib" que nos hará esta
conversión:

$ build-pysnmp-mib -o MAKINA_MIB.py MAKINA_MIB

Esto generará un archivo "MAKINA_MIB.py" que contiene el código de Python que


implementa esta MIB.

Sin embargo, desde la versión 4.3 de PySNMP, el script "build-pysnmp-mib" se ha quedado


obsoleto y ya no se entrega.

Para compilar su MIB, debe utilizar el script "mibdump.py", que generalmente se instala en
la carpeta "/ usr / local / bin"

$ /path/to/mibdump.py/path/to/ MAKINA_MIB # use ./ MAKINA_MIB si está


en el repositorio correcto para evitar el error mib no encontrado
Repositorios MIB de origen: file: /// path / to / MAKINA_MIB ,
file: /// usr / share / snmp / mibs, http://mibs.snmplabs.com/asn1/@mib@
Pedir prestadas MIB falladas / fallidas de:
http://mibs.snmplabs.com/pysnmp/notexts/@mib@
Ubicaciones de MIB existentes / compiladas: pysnmp.smi.mibs,
pysnmp_mibs
El directorio de destino MIB compilado: / home / <usuario> / .pysnmp /
mibs
...
MIB creadas / actualizadas: MAKINA_MIB
MIB precompilados prestados:
MIB actualizados: SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC
MIB fuente faltante:
MIB ignoradas:
MIB fallidas:

Finalmente, para construir un OID utilizando este último, ahora debe escribir:
o = ObjectIdentity (( 1 , 3 , 6 , 1 , 4 , 1 , 3 , 1 ))
o addMibSource ( '/ path / to / makina_mib / dot / py / folder ' )
o loadMibs ( "MAKINA_MIB" )
o resolveWithMib ( mvc )

imprimir ( o . getLabel ())


imprimir ( o . getMibNode ())
imprimir ( o . getMibSymbol ())
imprimir ( o . getOid ())
imprimir ( o . prettyPrint ())
('iso', 'org', 'dod', 'internet', 'privado', 'empresas',
'MakinaCorpus', 'dataValue')
MibScalar ((1, 3, 6, 1, 4, 1, 3, 1), Integer32 ())
('MAKINA_MIB', 'dataValue', ())
1.3.6.1.4.1.3.1
MAKINA_MIB :: DataValue

Veremos al ejecutar los comandos básicos que también podemos especificar directamente la
fuente ASN.1 en lugar de compilar la MIB. Desde la versión 4.3, PySNMP puede hacerlo
automáticamente en algunos casos.

Otros artículos antes de comenzar


Los comandos "GET", "SET" y "BULK" de la biblioteca PySNMP requieren varios
parámetros:

 El motor SNMP para usar


 Configuración de autenticación, "comunidad" o "usuario"
 El tipo de transporte utilizado (UDP), IPv4 o IPv6 y el puerto (161 por defecto)
 El contexto de ejecución
 Y las variables a manejar (los OID)

El motor SNMP

PySNMP permite el diálogo con todos los componentes SNMP a través de un objeto
"Motor SNMP". Su descripción completa está disponible en la documentación oficial.
Muy a menudo solo necesitas instanciarlo.

de la importación pysnmp.hlapi *
se = SnmpEngine ()

Configuración de autenticación

Este parámetro es:

 Una comunidad para protocolos v1 y v2


 Un usuario (con los 5 parámetros de inicio de sesión, contraseña, contraseña de
algoritmo de cifrado, comunicación de cifrado de sal, comunicación de algoritmo de
cifrado) en el caso del protocolo v3

La comunidad es proporcionada por la clase "CommunityData"

de la importación pysnmp.hlapi *
cv1 = CommunityData ( 'public' , mpModel = 0 ) # SNMPv1
cv2 = CommunityData ( 'public' , mpModel = 1 ) # SNMPv2c

Los usuarios utilizados para las conexiones a través del protocolo v3 se deben instanciar a
través de la clase "UsmUserData" que acepta 5 parámetros:

 nombre de usuario: inicio de sesión de usuario


 authKey: contraseña
 authProtocol: protocolo para encriptar la contraseña
Una tupla que indica la ruta en la MIB que define el protocolo.

En "iso" org. dod. Internet . snmpV2. snmpModules. snmpFrameworkMIB.


snmprameworkAdmin. SnmpAuthProtocols »
Por defecto " usmHMACMD5AuthProtocol »

 privKey: la clave / la sal para el algoritmo de encriptación


 privProtocol: el algoritmo de cifrado.
Una tupla que indica que la ruta en la MIB que define este algoritmo está bajo
"iso". org. dod. Internet . snmpV2. snmpModules. snmpFrameworkMIB.
snmpFrameworkAdmin. snmpPrivProtocols ", o en otro lugar.
PySNMP ofrece 6 algoritmos:
o usmNoPrivProtocol, predeterminado si no hay una clave asociada
o usmDESPrivProtocol, valor predeterminado si no se especifica y clave
asociada
o usm3DESEDEPrivProtocol
o usmAesCfb128Protocol
o usmAesCfb192Protocol
o usmAesCfb256Protocol

Ejemplo:

u = UsmUserData ( 'userlogin'
, authKey = 'authenticationkey'
, privKey = 'encryptionkey'
, privProtocol = usmAesCfb256Protocol )
imprimir ( u )
UsmUserData (userName = 'userlogin', authKey = <AUTHKEY>,
privKey = <PRIVKEY>, authProtocol = (1, 3, 6, 1, 6, 3, 10, 1, 1, 2),
privProtocol = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 2),
securityEngineId = '<DEFAULT>', securityName = 'userlogin')

Tipos de transporte

UDP en IPv4 o IPv6:

Por lo tanto, será una instancia de uno de estos 2 tipos de transporte:

 UdpTransportTarget
 Udp6TransportTarget

Estas 2 clases aceptan varios argumentos:

 El primero es una pareja (dirección IP, puerto).


La dirección es una cadena de caracteres, nombre de host o dirección IP. Use un
entero.
Las direcciones IPv6 deben cumplir con RFC 1924 # section-3
 un tiempo de espera, expresado en segundos, por defecto
 un número máximo para reintentar, predeterminado
 una lista de etiquetas, de acuerdo con RFC 3413 # section-4.1.4

Ejemplo:

t1 = UdpTransportTarget (( 'demo.snmplabs.com' , 161 ))


t2 = Udp6TransportTarget (( 'google.com' , 161 ))
imprimir ( t1 )
imprimir ( t2 )
UdpTransportTarget (('195.218.195.228', 161), timeout = 1, retries = 5,
tagList = b '')
Udp6TransportTarget (('2a00: 1450: 4007: 80e :: 200th', 161), timeout =
1, retries = 5, tagList = b '')

Contextos

Estos son contextos SNMP tal como se define en RFC 3411. # 3.3.1

Con SNMPv1, un agente solo podría manejar un MIB.


Pero hoy en día, algunos dispositivos pueden manejar múltiples MIB, por ejemplo, un
conmutador ATM con múltiples tarjetas, cada una con su propia base.

Por lo tanto, el contexto permite indicar a qué subconjunto de MIB se dirige el agente.

Para crear un contexto, necesita instanciar la clase " ContextData ".


Acepta 2 parámetros:

 ContextEngineId
 O el contextName

OID y ObjectType

Cubrimos los OID en un capítulo anterior.


Sin embargo, cuando envía un comando a través de la biblioteca SNMP, lo hace a través de
la clase " ObjectType ". El objeto estándar encapsula el OID y su valor real (en el caso de
un comando "SET") o devuelve un "GET".
Como parte de un GET, usted solo especifica el OID cuando crea la instancia "ObjectType",
pero a cambio tendrá un ObjectType con el mismo OID y su valor.

ot = ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' , 'sysDescr' ), 'Linux


i386 box' )
ot . resolveWithMib ( mvc )
imprimir ( ot )
SNMPv2-MIB :: sysDescr = Linux i386 box

El comando "OBTENER"
Ahora que hemos revisado todos los elementos necesarios para la llamada de pedidos,
FINALMENTE podremos escribir nuestro primer comando GET
Para enviar un mensaje "OBTENER", use la función "getCmd" enumerada anteriormente.

Finalmente, cuando ejecuta este comando puede solicitar múltiples OID a la vez.
La sintaxis es la siguiente:

pysnmp.hlapi.getCmd ( snmpEngine , authData , transportTarget ,


contextData , * varBinds , ** opciones )

Esta función devuelve una tupla de 4 elementos:

 errorIndication: Un valor considerado "True" si se produjo un error en el motor


 errorStatus: valor considerado "verdadero" para un error de PDU
 errorIndex: el índice de la variable que causó el error (comienza en 0)
 varBinds: una tupla que contiene los valores devueltos por el comando en instancias
de la clase "ObjectType"

O el siguiente comando:

$ snmpget -v1 -c public demo.snmplabs.com sysLocation.0 sysDescr.0

Se puede ejecutar a través del siguiente código de Python:


de la importación pysnmp.hlapi *

data = (
ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' , 'sysLocation' , 0 )),
ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' , 'sysDescr' , 0 ))
)

g = getCmd ( SnmpEngine ()
, CommunityData ( 'public' , mpModel = 0 )
, UdpTransportTarget (( 'demo.snmplabs.com' , 161 ))
, ContextData ()
, * datos )

errorIndication , errorStatus , errorIndex , varBinds = next ( g )

if errorIndication :
print ( errorIndication )
elif errorStatus :
print ( ' % s en % s ' % (
errorStatus . prettyPrint (),
errorIndex y varBinds [ int ( errorIndex ) -
1 ] [ 0 ] o '?'
)

)
else :
para varBind en varBinds :
print ( '=' . join ([ x . prettyPrint () para x en varBind ]))
SNMPv2-MIB :: sysLocation.0 = Moscú, Rusia
SNMPv2-MIB :: sysDescr.0 = SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m

Para ejecutarlo con el protocolo "v2c", simplemente cambie el valor del parámetro
"mpModel = 1" en el objeto de la comunidad.

Para ejecutarlo con el protocolo "v3", reemplace la instancia "CommunityData" con una
instancia "UsmUserData".

La lista de comunidades y usuarios disponibles en el sitio "demo.snmplabs.com" está


disponible en esta URL .
Ejemplo de usuario (usr-sha-des / SHA / authkey1 / DES / privkey1):

UsmUserData ( "usr-sha-des"
, authProtocol = usmHMACSHAAuthProtocol
, authKey = "authkey1"
, privProtocol = usmDESPrivProtocol
, privKey = "privkey1" )

El comando GetNEXT
El comando "GetNEXT" se ejecuta exactamente como un comando "get", con los mismos
parámetros.
Recupera el elemento que sigue al OID pasado como argumento.
de la importación pysnmp.hlapi *
g = nextCmd ( SnmpEngine ()
, CommunityData ( 'public' , mpModel = 1 )
, UdpTransportTarget (( 'demo.snmplabs.com' , 161 ))
, ContextData ()
, ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' , 'sysObjectID'
, 0 )))

errorIndication , errorStatus , errorIndex , varBinds = next ( g )

if errorIndication :
print ( errorIndication )
elif errorStatus :
print ( ' % s en % s ' % (
errorStatus . prettyPrint ()
, errorIndex y varBinds [ int ( errorIndex ) - 1
] [ 0 ] o '?'
)
)
else :
para varBind en varBinds :
print ( '=' . join ([ x . prettyPrint () para x en varBind ]))
SNMPv2-MIB :: sysUpTime.0 = 280102869

Como habrás notado, el comando devuelve un "generador".


Entonces puede devolver la llamada con la función "siguiente" para obtener el siguiente
artículo.
Esto le permite bajar un MIB completo modificando el código anterior, una vez que la
variable "g" crea una instancia.

de la importación pysnmp.hlapi *

g = nextCmd ( SnmpEngine ()
, CommunityData ( 'public' , mpModel = 1 )
, UdpTransportTarget (( 'demo.snmplabs.com' , 161 ))
, ContextData ()
, ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' , 'sysObjectID'
, 0 )))

para errorIndication , errorStatus , errorIndex , varBinds en g :

if errorIndication :
print ( errorIndication )
elif errorStatus :
print ( ' % s en % s ' % (
errorStatus . prettyPrint (),
errorIndex y varBinds [ int ( errorIndex ) - 1 ] [ 0 ] o '?'
)
)
else :
para varBind en varBinds :
print ( '=' . join ([ x . prettyPrint () para x en
varBind ]))
SNMPv2-MIB :: sysUpTime.0 = 280140241
SNMPv2-MIB :: sysContact.0 = SNMP Laboratories, info@snmplabs.com
SNMPv2-MIB :: sysName.0 = zeus.snmplabs.com
SNMPv2-MIB :: sysLocation.0 = Moscú, Rusia
SNMPv2-MIB :: sysServices.0 = 72
SNMPv2-MIB :: sysORLastChange.0 = 280140343
SNMPv2-MIB :: sysORID.1 = PYSNMP-MIB :: pysnmpObjects.1
SNMPv2-MIB :: sysORDescr.1 = comentario nuevo
SNMPv2-MIB :: sysORUpTime.1 = 123

El comando "SET"
El comando "SET" se ejecuta exactamente como un comando "get", con los mismos
parámetros.
Excepto que el ObjectType contiene un segundo argumento: el nuevo valor.

de la importación pysnmp.hlapi *

def show_item ( ):

g = getCmd ( SnmpEngine ()
, CommunityData ( 'public' , mpModel = 1 )
, UdpTransportTarget (( 'demo.snmplabs.com' , 161 ))
, ContextData ()
, ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' ,
'sysORDescr' , 1 )))

errorIndication , errorStatus , errorIndex , varBinds = next ( g )

para varBind en varBinds :


print ( '=' . join ([ x . prettyPrint () para x en
varBind ]))

# Mostrar valor inicial


show_item ()
# Establecer nuevo valor
g = setCmd ( SnmpEngine ()
, UsmUserData ( "usr-sha-des"
, authProtocol = usmHMACSHAAuthProtocol
, authKey = "authkey1"
, privProtocol = usmDESPrivProtocol
, privKey = "privkey1" )
, UdpTransportTarget (( 'demo.snmplabs.com' , 161 ))
, ContextData ()
, ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' , 'sysORDescr' ,
1 ), 'Hola desde Lannion usando el procesador Kalray en Linux' ))

errorIndication , errorStatus , errorIndex , varBinds = next ( g )

print ( errorIndication , varBinds )

show_item ()
SNMPv2-MIB :: sysORDescr.1 = Aquí está mi nueva nota
SNMPv2-MIB :: sysORDescr.1 = Hola desde Lannion usando el procesador
Kalray en Linux

conclusión
Los comandos básicos de SNMP se usan con bastante facilidad una vez que comprende
cómo configurar los diferentes parámetros que requieren.

Esta segunda parte de la iniciación de SNMP y PySNMP debería haberle dado:

 Una comprensión global de los elementos básicos de la biblioteca PySNMP


 Cómo convertir sus MIB ASN.1 a código Python para PySNMP
 Maneras de construir sondas para su software de monitoreo

Todavía tenemos que ver algunos elementos más avanzados como:

Introducción a SNMP con Python:


PySNMP (Parte 3) - Tablas
Por Gaël Pegliasco - publicado el 07/04/2016, publicado el 22/04/2016
SNMP es un protocolo de supervisión de red universalmente popular. Este es el estándar
utilizado por casi todos los equipos de red. Le permite monitorear (consultar y modificar)
todos los tipos de hardware, desde el enrutador hasta la impresora, e incluso algunas
cafeteras conectadas. Esta tercera parte del tutorial le muestra cómo administrar los datos
de la tabla.

introducción
Este tutorial le propone descubrir la biblioteca de Python PySNMP que permite dialogar
con cualquier material compatible con el protocolo del mismo nombre.
En esta tercera parte, le presentamos cómo consultar datos de tipo "tabla" desde la línea de
comando y con la biblioteca PySNMP .

Si no conoce el protocolo SNMP, lo invitamos a leer la primera parte de este tutorial que le
presentará el protocolo SNMP , sus cualidades y defectos, y le proporcionará las
herramientas básicas para comenzar a usarlo y quitárselo. Sin este conocimiento preliminar,
este tercer capítulo puede parecer muy difícil de entender.

Si nunca ha utilizado la biblioteca PySNMP, también lo invitamos a leer la segunda parte de


este tutorial que le brindará los conceptos básicos para usar el protocolo SNMP en Python .

Al final de esta tercera parte, normalmente podrá:

 Consultar tablas de datos en la línea de comando


 Lee tablas de datos SNMP con Python

Las tablas
Parte de la información de MIB se proporciona en forma de tabla.

Por ejemplo, las interfaces de red de un servidor (eth0, wlan0, loopback).


Estas tablas están organizadas como registros. Cada registro o fila en la tabla contiene
varias piezas de información.
Estos registros son accesibles individualmente a través de su índice.

Tome el ejemplo de la entrada " ifTable ", cuyo OID es:

 iso org. dod. Internet . mgmt. mib-2. interfaces. ifTable


 1.3.6.1.2.1.2.2

Su definición de ASN.1 es:

- Las interfaces de tabla


- La tabla de Interfaces contiene información sobre la entidad
- interfaces. Cada subcapa debajo de la capa de internetwork
- de una interfaz de red se considera una interfaz.
ifTable OBJETO DE TIPO
SINTAXIS SECUENCIA DE IfEntry
MAX-ACCESS no accesible
ESTADO actual
DESCRIPCIÓN
La lista de entradas
viene dado por el valor de ifNumber ".
:: = {interfaces 2}

ifEntry OBJETO DE TIPO


SYNTAX IfEntry
MAX-ACCESS no accesible
ESTADO actual
DESCRIPCIÓN
"Una entrada que contiene información de gestión aplicable
a una interfaz particular ".
ÍNDICE {ifIndex}
:: = {ifTable 1}

IfEntry :: =
SECUENCIA {
ifIndex InterfaceIndex,
ifDescr DisplayString,
ifType IANAifType,
ifMtu Integer32,
ifSpeed Gauge32,
ifPhysAddress PhysAddress,
ifAdminStatus INTEGER,
ifOperStatus INTEGER,
ifLastChange TimeTicks,
ifInOctets Counter32,
ifInUcastPkts Counter32,
ifInNUcastPkts Counter32, - obsoleto
ifInDiscards Counter32,
ifInErrors Counter32,
ifInUnknownProtos Counter32,
ifOutOctets Counter32,
ifOutUcastPkts Counter32,
ifOutNUcastPkts Counter32, - obsoleto
ifOutDiscards Counter32,
ifOutErrors Counter32,
ifOutQLen Gauge32, - obsoleto
ifSpecific OBJECT IDENTIFIER - obsoleto
}

Se lee que el elemento "ifTable" es una secuencia de elementos "ifEntry" y que cada
elemento "ifEntry" está indexado por un elemento "ifIndex".
Finalmente, "ifEntry" en sí es una secuencia de muchos elementos como "ifDescr",
"ifType", "ifSpeed", etc.
En otras palabras, "ifTable" es una matriz de líneas de tipo "ifEntry" con múltiples
columnas "ifDescr", "ifType", etc.

Representación de la tabla "ifTable", fuente " etutorials.org "


Podemos ver esto más de cerca con el comando SNMPWALK:

$ snmpwalk -v2c -c public demo.snmplabs.com ifTable


IF-MIB :: ifIndex.1 = INTEGER: 1
IF-MIB :: ifIndex.2 = INTEGER: 2
IF-MIB :: ifDescr.1 = STRING: eth0
IF-MIB :: ifDescr.2 = STRING: eth1
IF-MIB :: ifType.1 = INTEGER: ethernetCsmacd (6)
IF-MIB :: ifType.2 = INTEGER: ethernetCsmacd (6)
IF-MIB :: ifMtu.1 = INTEGER: 1500
IF-MIB :: ifMtu.2 = INTEGER: 1500
IF-MIB :: ifSpeed.1 = Gauge32: 100000000
IF-MIB :: ifSpeed.2 = Gauge32: 100000000
IF-MIB :: ifPhysAddress.1 = CADENA: 0: 12: 79: 62: f9: 40
IF-MIB :: ifPhysAddress.2 = CADENA: 0: 12: 79: 62: f9: 41
IF-MIB :: ifAdminStatus.1 = INTEGER: arriba (1)
IF-MIB :: ifAdminStatus.2 = INTEGER: arriba (1)
IF-MIB :: ifOperStatus.1 = INTEGER: arriba (1)

Es posible encontrar los diferentes registros de la tabla gracias al índice "ifIndex" de las
entradas "ifEntry". Aquí tenemos 2 valores para el índice: 1 y 2, por lo tanto, 2 registros.

Por lo tanto, cada columna del registro "ifEntry" estará asociada a su índice:

 "IfDescr.1" y "ifType.1" para el primer registro.


 "IfDescr.2" y "ifType.2" para el segundo, y así sucesivamente.

De este modo, es posible reconstituir todas las grabaciones mediante el comando


"snmpwalk" y los valores de los índices. Pero es laborioso.
El comando "snmptable" hace esto automáticamente para usted:

$ snmptable -v2c -c public demo.snmplabs.com ifTable


Tabla SNMP: IF-MIB :: ifTable

ifIndex ifDescr ifType ifMtu ifSpeed ifPhysAddress


1 eth0 ethernetCscmac 1500 100000000 0: 12: 79: 62: f9: 40
2 eth1 ethernetCsmacd 1500 100000000 0: 12: 79: 62: f9: 41

Esto puede ser complicado cuando una entrada de tabla es indexada por múltiples índices.

Habrá notado que el valor del índice se encuentra en el OID de cada "columna". Es lo
mismo cuando hay varios índices, están encadenados en el OID, te dejo leer la
documentación de PySNMP en las tablas, lo que explica bastante bien.

Tablas con PySNMP


PySNMP no ofrece un equivalente al comando "snmptable" para leer una tabla.

Pero puede hacerlo de manera muy simple con el comando "nextCmd" si lo configura
correctamente.
Antes de ver cómo hacer esta lectura con buenas prácticas, trataremos de explorar los
diferentes elementos de la MIB "Interfaz" OID (IF-MIB, ifTable) de forma manual y
devolveremos una lista de diccionarios, cada uno con los valores de cada uno. columnas del
nodo "ifEntry".

Esto nos permitirá comprender mejor la mecánica utilizada por PySNMP y nos enseñará a
manipular las sucesivas iteraciones de "nextCmd".

Una vez que implementamos una solución funcional, podemos aplicar algunas
configuraciones adicionales para simplificar la creación de nuestra lista de registros.

Usando el siguiente comando veremos todos los elementos de la entrada (IF-MIB, ifTable):

g = nextCmd ( SnmpEngine ()
, CommunityData ( 'public' , mpModel = 1 )
, UdpTransportTarget (( 'demo.snmplabs.com' , 161 )
, ContextData ()
, ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifTable' ))
, lexicographicMode = False )

Aquí todavía agregamos la opción "lexicographiqueMode = False" que le dice al comando


getNext que no continúe navegando elementos fuera de los que están bajo este OID .
Para construir los elementos "ifEntry" usamos el comando "getNext" como de costumbre:

imprimir ( " \ n Mesa para caminar" )


data = []
dIndex = {}

para errorIndication , errorStatus , errorIndex , varBinds en g :

if errorIndication :
print ( errorIndication )
elif errorStatus :
print ( ' % s en % s ' % (
errorStatus . prettyPrint (),
errorIndex y varBinds [ int ( errorIndex ) - 1 ] [ 0 ] o '?'
)
)
else :
para varBind en varBinds :

imprimir ( varBind )
oid = varBind [ 0 ]
value = varBind [ 1 ]

label = oid . getLabel ()


imprimir ( "Etiqueta:" , etiqueta )
print ( "Símbolo Mib:" , oid . getMibSymbol ())

Esto nos dará un resultado similar a este:


Mesa de caminata
IF-MIB :: ifIndex.1 = 1
Etiqueta: ('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2',
'interfaces', 'ifTable', 'ifEntry', 'ifIndex')
Símbolo Mib: ('IF-MIB', 'ifIndex', (InterfaceIndex (1),))
IF-MIB :: ifIndex.2 = 2
Etiqueta: ('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2',
'interfaces', 'ifTable', 'ifEntry', 'ifIndex')
Símbolo Mib: ('IF-MIB', 'ifIndex', (InterfaceIndex (2),))
IF-MIB :: ifDescr.1 = eth0
Etiqueta: ('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2',
'interfaces', 'ifTable', 'ifEntry', 'ifDescr')
Símbolo Mib: ('IF-MIB', 'ifDescr', (InterfaceIndex (1),))
IF-MIB :: ifDescr.2 = eth1

Este listado nos muestra 2 cosas:

 El número del ifEntry al que pertenece cada propiedad viene proporcionado por el
último elemento de la tupla "Mib Symbol" InterfaceIndex (1) o InterfaceIndex ( 2 )
 El nombre de la propiedad es provisto por el último elemento de la Etiqueta
('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2', 'interfaces', 'ifTable', 'ifEntry', ' ifDescr ')

Así que podemos crear una lista de cada elemento "ifEntry" en un diccionario, de la
siguiente manera:

key = str ( oid . getMibSymbol () [ - 1 ] [ 0 ])


si no es clave en dIndex :
dIndex [ clave ] = {}
datos . append ( dIndex [ clave ])

dIndex [ clave ] [ etiqueta [ - 1 ]] = str ( valor . prettyPrint ())

El código final pasa a ser el siguiente:

de la importación pysnmp.hlapi *
desde pysnmp.smi.view import MibViewController

se = SnmpEngine ()
mvc = se . getUserContext ( 'mibViewController' )
si no mvc :
mvc = MibViewController ( ver getMibBuilder ())
#
# # 1.3.6.1.2.1.2.2 ('iso', 'org', 'dod', 'internet', 'mgmt', 'mib-2',
'interfaces', 'ifTable')
oid_iftable = ObjectIdentity ( 'IF-MIB' , 'ifTable' )
oid_iftable . resolveWithMib ( mvc )

print ( "Root oid" )


imprimir ( oid_iftable . getOid ())
imprimir ( oid_iftable . getLabel ())
imprimir ( oid_iftable . getMibNode ())
imprimir ( oid_iftable . getMibSymbol ())
g = nextCmd ( SnmpEngine ()
, CommunityData ( 'public' , mpModel = 1 )
, UdpTransportTarget (( 'demo.snmplabs.com' , 161 ))
, ContextData ()
, ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifTable' ))
, lexicographicMode = False )

imprimir ( " \ n Mesa para caminar" )


data = []
dIndex = {}

para errorIndication , errorStatus , errorIndex , varBinds en g :

if errorIndication :
print ( errorIndication )
elif errorStatus :
print ( ' % s en % s ' % (
errorStatus . prettyPrint (),
errorIndex y varBinds [ int ( errorIndex ) - 1 ] [ 0 ] o '?'
)
)
else :
para varBind en varBinds :

imprimir ( varBind )

oid = varBind [ 0 ]
value = varBind [ 1 ]

label = oid . getLabel ()


imprimir ( "Etiqueta:" , etiqueta )
print ( "Símbolo Mib:" , oid . getMibSymbol ())
key = str ( oid . getMibSymbol () [ - 1 ] [ 0 ])

si no es clave en dIndex :
dIndex [ clave ] = {}
datos . append ( dIndex [ clave ])

dIndex [ clave ] [ etiqueta [ - 1 ]] = str ( valor .


prettyPrint ())

imprimir ( " \ n Imprimir elementos" )


para ind , elemento en enumerate ( datos ):
print ( "Artículo % s " % ( str ( ind + 1 ), ))
para la clave , valor en el artículo . artículos ():
print ( " % s : % s " % ( clave , valor ))

Con el siguiente resultado final para los elementos "ifEntry":

Impresión de artículos
Artículo 1
ifOutUcastPkts: 11277302
ifInErrors: 0
ifInUcastPkts: 22554581
ifOutErrors: 0
ifOutDiscards: 0
ifInNUcastPkts: 2506064
ifType: 'ethernetCsmacd'
ifSpecific: SNMPv2-SMI :: zeroDotZero
ifSpeed: 100000000
ifPhysAddress: 00: 12: 79: 62: f9: 40
ifOutNUcastPkts: 1253033
ifOperStatus: 'up'
ifIndex: 1
ifInOctets: 275667056
ifDescr: eth0
ifLastChange: 150603818
ifInDiscards: 0
ifOutOctets: 125303333
ifAdminStatus: 'arriba'
ifInUnknownProtos: 125301
ifMtu: 1500
ifOutQLen: 0
Artículo 2
ifOutUcastPkts: 11277305
ifInErrors: 0
ifInUcastPkts: 22554583
ifOutErrors: 0
ifOutDiscards: 0
ifInNUcastPkts: 2506065
ifType: 'ethernetCsmacd'
ifSpecific: SNMPv2-SMI :: zeroDotZero
ifSpeed: 100000000
ifPhysAddress: 00: 12: 79: 62: f9: 41
ifOutNUcastPkts: 1253034
ifOperStatus: 'up'
ifIndex: 2
ifInOctets: 250606431
ifDescr: eth1
ifLastChange: 249303192
ifInDiscards: 0
ifOutOctets: 125303346
ifAdminStatus: 'arriba'
ifInUnknownProtos: 125304
ifMtu: 1500
ifOutQLen: 0

Esta técnica es útil para comprender cómo se organizan los registros en una tabla SNMP y
para reconstruirlos manualmente.
Pero el comando "getNext" hace que sea posible recuperarlos mucho más simplemente al
indicarle qué información queremos leer en las entradas "ifEntry" para cada una de sus
llamadas en lugar de leerlas una a una, como anteriormente.

Para eso es suficiente pasarle el OID que nos interesa en solo 1 vez:

nextCmd ( SnmpEngine (),


CommunityData ( 'public' , mpModel = 0 ),
UdpTransportTarget (( 'demo.snmplabs.com' , 161 )),
ContextData (),
ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifDescr' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifType' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifMtu' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifSpeed' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifType' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifPhysAddress' )),
lexicographicMode = False )

Nuestro programa se convierte en:

de la importación pysnmp.hlapi *

item = 0

para errorIndication , \
errorStatus , \
errorIndex , \
varBinds en nextCmd ( SnmpEngine (),
CommunityData ( 'public' , mpModel = 0 ),
UdpTransportTarget (( 'demo.snmplabs.com' ,
161 )),
ContextData (),
ObjectType ( ObjectIdentity ( 'IF-MIB' ,
'ifDescr' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' ,
'ifType' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' , 'ifMtu'
)),
ObjectType ( ObjectIdentity ( 'IF-MIB' ,
'ifSpeed' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' ,
'ifType' )),
ObjectType ( ObjectIdentity ( 'IF-MIB' ,
'ifPhysAddress' )),
lexicographicMode = False ):

imprimir ( "Artículo" , artículo )


item + = 1

if errorIndication :
print ( errorIndication )
pausa
elif errorStatus :
print ( ' % s en % s ' % (
errorStatus . prettyPrint (),
errorIndex y varBinds [ int ( errorIndex ) - 1 ] [ 0 ] o
'?'
)
)
pausa
else :
para varBind en varBinds :
print ( '=' . join ([ x . prettyPrint () para x en
varBind ]))
Con el siguiente resultado:

Artículo 0
IF-MIB :: ifDescr.1 = eth0
IF-MIB :: ifType.1 = 'ethernetCsmacd'
IF-MIB :: ifMtu.1 = 1500
IF-MIB :: ifSpeed.1 = 100000000
IF-MIB :: ifType.1 = 'ethernetCsmacd'
IF-MIB :: ifPhysAddress.1 = 00: 12: 79: 62: f9: 40
Artículo 1
IF-MIB :: ifDescr.2 = eth1
IF-MIB :: ifType.2 = 'ethernetCsmacd'
IF-MIB :: ifMtu.2 = 1500
IF-MIB :: ifSpeed.2 = 100000000
IF-MIB :: ifType.2 = 'ethernetCsmacd'
IF-MIB :: ifPhysAddress.2 = 00: 12: 79: 62: f9: 41

conclusión
Vimos en esta tercera parte cómo manejar las tablas SNMP con la línea de comandos o la
biblioteca de Python.
PySNMP no tiene un comando especial para navegar por una tabla, por lo que tenemos que
listar todos sus elementos a través de "getNext".

Afortunadamente, es posible recuperar todas las propiedades de una entrada a través de una
sola llamada a "getNext", lo que simplifica enormemente la reconstitución de los registros
de la tabla.

En la cuarta parte de este tutorial, aprenderemos cómo crear agentes.

Вам также может понравиться