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, [email protected] 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.mib2.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 imprimir imprimir imprimir imprimir ( ( ( ( ( o o o o o . . . . . getLabel ()) getMibNode ()) getMibSymbol ()) getOid ()) 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 )) addMibSource ( '/ path / to / makina_mib / dot / py / folder ' ) loadMibs ( "MAKINA_MIB" ) resolveWithMib ( mvc ) o o o 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 ( , , , , , 0 ))) SnmpEngine () CommunityData ( 'public' , mpModel = 1 ) UdpTransportTarget (( 'demo.snmplabs.com' , 161 )) ContextData () ObjectType ( ObjectIdentity ( 'SNMPv2-MIB' , 'sysObjectID' 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 SNMPv2-MIB SNMPv2-MIB SNMPv2-MIB SNMPv2-MIB SNMPv2-MIB SNMPv2-MIB SNMPv2-MIB SNMPv2-MIB :: :: :: :: :: :: :: :: :: sysUpTime.0 = 280140241 sysContact.0 = SNMP Laboratories, [email protected] sysName.0 = zeus.snmplabs.com sysLocation.0 = Moscú, Rusia sysServices.0 = 72 sysORLastChange.0 = 280140343 sysORID.1 = PYSNMP-MIB :: pysnmpObjects.1 sysORDescr.1 = comentario nuevo 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 imprimir ( oid_iftable imprimir ( oid_iftable imprimir ( oid_iftable . . . . getOid ()) getLabel ()) getMibNode ()) 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.