Cómo conectar Zabbix con Asterisk listo para usar

En un artículo anterior "Zabbix: ampliando los límites macro" Te dije cómo recibir una sesión de autorización y sustituirla en una macro de host local. En este artículo te diré cómo conectar Zabbix con Asterisk sin scripts ni software externos.

La idea de "hacer amigos" entre estos dos sistemas nació hace mucho tiempo, sin instalar software ni scripts adicionales. Una búsqueda rápida en Google arrojó muchas soluciones posibles, todo se redujo al hecho de que cargue los scripts (en Pyha, Bash, Python, etc.) al servidor y estará satisfecho. Quería implementar el monitoreo "listo para usar", sin scripts externos e instalando software adicional en el servidor con monitoreo y PBX.

Pasé un total de 4 días hábiles con esto, pero el resultado valió la pena. Trabajar a través de la interfaz AMI, la detección de bajo nivel, los activadores y, lo más importante, conectar el PBX y todas las demás configuraciones ahora lleva aproximadamente 15 minutos.

Zabbix 4.4 está disponible, alrededor de 100 piezas de Asterisk versión 13. Algunas PBX vienen con la interfaz web FreePBX, otras con una consola básica, un montón de trucos e integración a través de un plan de marcado.

Recibir datos de la centralita

El primer y principal punto que debe resolverse es la obtención de datos sobre pares y registros SIP. Para ello, la centralita dispone de interfaces de consola AGI, AMI, ARI y SSH. Por razones obvias, no consideré módulos adicionales.

Primero tenemos que descubrir qué son estos agi, ami, ari...

  • AGI: uso de scripts en el plan de marcado. Se utiliza principalmente para la gestión de llamadas.
  • AMI: puede proporcionar toda la información necesaria, funciona a través del puerto 5038, similar a Telnet. ¡Nos sirve!
  • ARI: JSON moderno y de moda. Hay muchas posibilidades, el formato de datos es comprensible para Zabbix, pero para mí no hay nada principal: no se puede controlar el registro sip. Otra desventaja es que para los pares sólo hay dos estados online/offline, aunque hay más estados y es útil tenerlos en cuenta a la hora de diagnosticar.
  • SSH puede hacer de todo, pero a veces no está permitido por “razones de seguridad”. Las consideraciones pueden ser diferentes, no entraré en ellas.

Sin embargo, a pesar de todas sus deficiencias, ARI cubre el 90% de todas las necesidades de seguimiento.

Zabbix y Telnet: mi decepción

Conozco bien a AMI, en algún momento implementé el seguimiento de pérdidas en conversaciones con la división por oficinas remotas, gestión de llamadas, etc. Con Telnet también todo está muy claro: abre la conexión, envía los comandos y lee la respuesta. Eso es lo que hice, pero el resultado me decepcionó.

Telnet en Zabbix no es lo mismo que en la consola de Linux, es un poco más simple y está diseñado para autorizaciones estándar como inicio de sesión/contraseña. Si la lógica de autorización es diferente y no se solicita un par de inicio de sesión/contraseña, se produce un error. Después de intentos inútiles de eludir el requisito de autorización, resultó útil consultar el código fuente del módulo Telnet.

Me di cuenta de que hasta que no haya una solicitud tradicional de inicio de sesión y contraseña, no avanzaré. Solo por diversión, eliminé todo lo relacionado con la autorización del código y lo volví a ensamblar todo. ¡Obras! Pero no cumple con los requisitos. Adelante…

Volvamos a la búsqueda.

Releí la documentación de ARI nuevamente, realicé pruebas adicionales; aquí no hay registros SIP. Hay festines, hay conversaciones, hay calzones, pero no hay inscripciones. En algún momento incluso pensé: ¿realmente necesitamos el registro de buitres?

Por curiosa coincidencia, en este momento llega otra solicitud del usuario, con un problema con las llamadas salientes. El problema era que el registro SIP se congelaba y se solucionó simplemente reiniciando el módulo.

asterisk -rx "sip reload"

Sería fantástico acceder a AMI a través de la web: eso resolvería todos los problemas, pensé. Empiezo a investigar en esta dirección y, literalmente, la primera línea de búsqueda conduce a la documentación oficial de Asterisk, que dice que existe una opción para mis tareas. habilitado para la web en archivo /etc/asterisk/manager.conf, que debe configurarse en SÍ, en la sección [general]

Posteriormente, mediante una solicitud web periódica del formulario http://ats:8089/mxml?action=SIPshowregistry obtenemos toda la información necesaria.

Cuando utiliza la interfaz FreePBX, no puede habilitar esta opción a través de la web; debe habilitarla a través de la consola realizando cambios en el archivo manager.conf. FreePBX no lo borra cuando se realizan cambios de configuración a través de la web.

He trabajado con varios tipos de integraciones de Asterisk durante mucho tiempo, pero nunca había visto esta característica mencionada en ninguna parte. Me sorprendió que nadie describiera este método de interacción con la centralita. Incluso fue especialmente útil buscar información sobre este tema: prácticamente no hay nada o se utilizó para tareas completamente diferentes.

WEB AMI: ¿qué clase de bestia?

Agregar una opción habilitado para la web archivar administrador.conf proporcionó acceso completo a la gestión ATS a través de la web. Todos los comandos disponibles a través de una AMI normal ahora están en la web, puede escuchar eventos desde la PBX a través de un socket. El principio de funcionamiento no es diferente al de la consola AMI. Después de activar esta opción, podrá contactar con la centralita en las siguientes direcciones:

https://ats:8089/manager — una página web con una interfaz sencilla para probar y enviar solicitudes manualmente. Todas las respuestas están formateadas en HTML legible. No muy adecuado para seguimiento.
https://ats:8089/rawman — solo salida de texto, formato similar al AMI de consola
https://ats:8089/mxml - salida de texto únicamente, en formato XML. ¡Nos sirve!

Cómo conectar Zabbix con Asterisk listo para usar

Entonces pensé: “¡Esta es la solución! ¡Ahora todo estará listo! Exprimidor de limón fácil de beber”, pero era demasiado pronto para alegrarse. Para obtener la información que necesitamos basta con utilizar una solicitud GET con la acción necesaria DE ACTUAR!, que en respuesta devuelve xml con una lista de todos los registros y su estado. Todo esto es genial, pero necesitas autorización para recordar la sesión de la cookie. Cuando realiza la prueba en el navegador, no piensa en este proceso.

Proceso de autorización

Primero abordamos la dirección. http://ats:8089/mxml?action=login&username=zabbix&secret=zabbix, en respuesta, el servidor nos envía una cookie con la sesión de autorización. Así es como se ve una solicitud HTTP:

https://ats:8089/mxml?action=login&username=zabbix&secret=zabbix

Host: ats:8089
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1

Respuesta:

GET: HTTP/1.1 200 OK
Server: Asterisk/13.29.2
Date: Thu, 18 Jun 2020 17:41:19 GMT
Cache-Control: no-cache, no-store
Content-type: text/xml
Set-Cookie: mansession_id="6f5de42c"; Version=1; Max-Age=600
Pragma: SuppressEvents
Content-Length: 146

<ajax-response>
<response type="object" id="unknown">
<generic response="Success" message="Authentication accepted"/>
</response>
</ajax-response>

Para trabajar ahí necesitas mansession_id="6f5de42c", es decir, la propia cookie de autorización.
Contenido que solo necesita verificar para obtener la respuesta "Autenticación aceptada" A continuación, para todas las llamadas al servidor PBX, necesitaremos agregar una cookie de autorización a la solicitud.

https://ats:8089/mxml?action=SIPpeers

Host: ats:8089
Connection: close
Cookie: mansession_id="6f5de42c"

Lea cómo obtener una cookie de autorización y utilizarla en otras solicitudes aquí: “Zabbix: expansión de los límites de las macros»

Para crear elementos de seguimiento en Zabbix usaré la detección automática.

Detección automática

Para detectar registros automáticamente y rastrear estados de pares, debe comunicarse con la siguiente dirección: https://ats:8089/mxml?action=SIPshowregistry o https://ats:8089/mxml?action=SIPpeers

Como respuesta la central nos devuelve una respuesta XML:

<ajax-response>
<response type="object" id="unknown">
<generic response="Success" eventlist="start" message="Registrations will follow"/>
</response>
...
<response type="object" id="unknown">
<generic event="RegistryEntry" host="login.mtt.ru" port="5060" username="111111" domain="login.mtt.ru" domainport="5060" refresh="105" state="Registered" registrationtime="1592502142"/>
</response>
<response type="object" id="unknown">
<generic event="RegistryEntry" host="voip.uiscom.ru" port="5060" username="222222" domain="voip.uiscom.ru" domainport="5060" refresh="105" state="Registered" registrationtime="1592502142"/>
</response>
<response type="object" id="unknown">
<generic event="RegistryEntry" host="voip.uiscom.ru" port="5060" username="333333" domain="voip.uiscom.ru" domainport="5060" refresh="105" state="Registered" registrationtime="1592502142"/>
</response>
...
</ajax-response>

Hay mucha basura en la respuesta, por eso en el preprocesamiento la filtramos por plantilla. XPath: //respuesta/genérico[@host]
Entonces comienza la diversión. Para trabajar con la detección y crear elementos dinámicamente, la respuesta debe estar en formato JSON. XML no es compatible con las detecciones automáticas.

Para convertir XML a JSON, tuve que jugar un poco con el reemplazo automático, para lo cual hice un script en JS.

Cómo conectar Zabbix con Asterisk listo para usar

Un punto interesante: en la respuesta ATS, todos los parámetros están entre comillas simples y después de aplicar la plantilla //respuesta/genérico[@host] son reemplazados por dobles.

Para crear elementos, utilizamos variables de la respuesta XML (ahora JSON).

Cómo conectar Zabbix con Asterisk listo para usar

Registro SIP

Para los registros sip utilizamos tres variables: nombre de usuario, fortaleza, Puerto. Estaba contento con el nombre del elemento. [email protected]: 5060, No he encontrado ninguna situación en la que sea necesario utilizar las cinco variables.

El elemento principal que recibe información sobre todos los registros, Asterisco - AMI SIPshowregistry. Una vez por minuto realiza una solicitud GET a https://ats:8089/mxml?action=SIPshowregistry, después de lo cual los datos XML de respuesta se pasan a todos los elementos dependientes para su análisis. Para cada registro creo un elemento dependiente de él. Esto es conveniente porque recibimos información actualizada en una sola solicitud y no para cada solicitud por separado. Esta implementación tiene un inconveniente importante: la carga en el procesador.

Al probar hasta 100 elementos dependientes, no noté la carga, pero con 1700 elementos, esto dio una carga notable en el procesador de 15 segundos. Tenga esto en cuenta si tiene una gran cantidad de elementos dependientes.

Como opción para "repartir" la carga o establecer diferentes frecuencias de sondeo para un elemento, puede mover la lógica de procesamiento a cada elemento por separado.

No almaceno la información recibida en el elemento principal. En primer lugar, no veo la necesidad de esto y, en segundo lugar, si la respuesta es superior a 64K, Zabbix la corta.

Dado que utilizamos una respuesta XML completa para el elemento dependiente, necesitamos obtener el valor de este elemento en el preprocesamiento. A través de XPath se hace así:
string(//response/generic[@event="RegistryEntry"][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@ estado)
Para los estados de registro, no utilicé estados de texto, sino que los convertí a formato numérico usando JavaScript:

switch(value) {
  case 'Registered':
    return 1;
  case 'Unregistered':
    return 0;
  default:
    return -1;
}

Pares SIP

Por analogía con los registros SIP, existe un elemento principal de Asterisk: AMI SIPshowregistry, al que se agregan los dependientes.

Esto crea dos elementos dependientes:

  • Estado de pares en forma de texto
  • Tiempo de respuesta del dispositivo: si el estado es correcto, se escribe el tiempo de respuesta del dispositivo; de lo contrario, “-1”

El camino hacia el elemento en sí es un poco más sencillo. XPath:

cadena(//respuesta/generic[@objectname="{#SIP_PEER_OBEJECTNAME}"]/@status)

Para el segundo elemento utilicé JavaScript para separar tiempo de respuesta del estado del par, ya que se almacenan juntos:

if(value.substring(0,2) == 'OK'){
	return value.match(/(d+)/gm);
}
else {
	return -1;
}

Conclusión

Una solución lista para usar puede ser compleja y no clara de inmediato. Aumenta la flexibilidad y la portabilidad entre diferentes sistemas.

¡Feliz y fácil integración para todos! Plantilla e instrucciones para la configuración. GitHub.

Fuente: habr.com

Añadir un comentario