Cómo integrar Zabbix con Asterisk ‘out of the box’

En el artículo anterior «Zabbix — ampliando los límites macro» He explicado cómo obtener la sesión de autorización y utilizarla en un macro local del host. En este artículo, contaré cómo integrar Zabbix con Asterisk sin scripts externos y software.

La idea de «integrar» estos dos sistemas surgió hace tiempo, y sin necesidad de instalar software adicional ni scripts. Una rápida búsqueda en Google mostraba múltiples soluciones, las cuales se reducían a subir scripts (en PHP, Bash, Python, etc.) al servidor y así sería la felicidad. Sin embargo, quería implementar el monitoreo «listo para usar» — sin scripts externos y sin necesidad de instalar software adicional en el servidor que maneja las aplicaciones de monitoreo y la central telefónica.

Estuve trabajando en esto durante 4 días laborales en total, pero el resultado valió la pena. La interacción a través de la interfaz AMI, la detección a bajo nivel, los triggers; y lo más importante, ahora conecta con la central y realiza todas las configuraciones en unos 15 minutos.

Tengo Zabbix 4.4, con aproximadamente 100 unidades de Asterisk de la versión 13. Algunas centrales vienen con la interfaz web FreePBX, otras tienen una consola básica, un montón de trucos y se integran mediante un dialplan.

Obteniendo datos de la central telefónica

El primer y principal aspecto que hay que resolver es la obtención de datos sobre las peer y registros SIP. Para ello, en la central existen interfaces AGI, AMI, ARI y la consola SSH. No consideré módulos adicionales por razones evidentes.

Primero, debemos comprender qué son estos AGI, AMI, ARI…

  • AGI — uso de scripts en el dialplan. Principalmente se utiliza para gestionar las llamadas.
  • AMI — puede proporcionar toda la información necesaria, trabaja a través del puerto 5038 de manera similar a Telnet. ¡Es justo lo que necesitamos!
  • ARI — moderno, a la moda, en formato JSON. Muchas posibilidades, formato de datos comprensible para Zabbix, pero para mí carece de algo importante: no se puede controlar el registro SIP. Otra desventaja es que para peers solo hay dos estados: online/offline, aunque hay más estados que son útiles para el diagnóstico.
  • SSH — puede hacer todo, pero a veces no se permite por «razones de seguridad». Las razones pueden ser diversas, no entraré en detalles.

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

Zabbix y Telnet — mi desilusión

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

Telnet en Zabbix no es como en la consola de Linux, es un poco más simple y está adaptado para la autenticación estándar tipo usuario/contraseña. Si la lógica de autenticación es diferente y no hay solicitud de usuario/contraseña, aparece un error. Después de varios intentos fallidos de eludir el requisito de autenticación, me fue útil revisar el código fuente del módulo Telnet.

Entendí que mientras no haya una solicitud tradicional de usuario con contraseña, no avanzaré más. Por curiosidad, eliminé del código todo lo relacionado con la autenticación, recompilé todo. ¡Funciona! Pero no es adecuado para los requisitos. Vamos a seguir…

Volvamos a la búsqueda

Leí de nuevo la documentación sobre ARI, realicé pruebas adicionales — no hay registros SIP aquí. Hay pares, hay llamadas, hay puentes, no hay registros. En algún momento incluso me pregunté si realmente necesitamos registros SIP.

Por una curiosa coincidencia, en ese momento llega otra solicitud de un usuario, con un problema de llamadas salientes. El problema estaba en el congelamiento del registro SIP y se resolvió con un simple reinicio del módulo.

asterisk -rx "sip reload"

Sería genial poder acceder a AMI a través de la web: eso resolvería todos los problemas, pensé. Comienzo a investigar en esta dirección, y literalmente la primera línea de búsqueda me lleva a la documentación oficial de Asterisk, en la que se dice que para mis tareas hay una opción webenabled en el archivo /etc/asterisk/manager.conf, que debe establecerse en el valor YES, en la sección [general]

Después de esto, a través de una solicitud web estándar del tipo http://ats:8089/mxml?action=SIPshowregistry obtenemos toda la información necesaria.

Al utilizar la interfaz de FreePBX, no se puede habilitar esta opción a través de la web, debe habilitarse a través de la consola, realizando cambios en el archivo manager.conf. FreePBX no la elimina cuando se realizan cambios de configuración a través de la web.

Mientras trabajaba con diferentes integraciones de Asterisk, nunca vi que se mencionara esta función en ningún lugar. Me sorprendió que nadie describiera este método de interacción con el PBX. Incluso busqué información sobre este tema: prácticamente no hay nada o se ha utilizado para tareas completamente diferentes.

WEB AMI — ¿qué es esto?

Agregar la opción webenabled en el archivo manager.conf abría un acceso completo a la gestión de la centralita a través de la web. Todos los comandos disponibles a través del AMI estándar ahora están en la web, se pueden escuchar eventos de la centralita a través de un socket. El principio de funcionamiento no difiere del AMI de consola. Después de activar esta opción, puedes acceder a la centralita en las siguientes direcciones:

https://ats:8089/manager — página web con una interfaz sencilla, para pruebas y envío manual de solicitudes. Todas las respuestas se formatean en un formato HTML legible. No es muy adecuada para monitoreo.
https://ats:8089/rawman — salida solo en texto, el formato es análogo al AMI de consola
https://ats:8089/mxml — salida solo en texto, en formato XML. ¡Nos sirve!

Cómo integrar Zabbix con Asterisk ‘out of the box’

Aquí pensé: «¡Aquí está la solución! ¡Ahora todo estará listo! Es fácil-peasy lemon squeezy», pero todavía era pronto para alegrarse. Para obtener la información que necesitamos, basta con utilizar una solicitud GET con la acción requerida acción, que devuelve XML con la lista de todos los registros y su estado. Todo esto está genial, pero se necesita autorización con recordatorio de sesión desde las cookies. Cuando pruebas en el navegador, no piensas en este proceso.

Proceso de autorización

Al principio, nos dirigimos a la dirección http://ats:8089/mxml?action=login&username=zabbix&secret=zabbix, el servidor nos envía una cookie con la sesión de autorización. Así es como se ve la 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: es-ES,es;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

Para funcionar allí se necesita mansession_id="6f5de42c", es decir, la propia cookie de autorización.
Solo hay que comprobar que la respuesta contiene «Autenticación aceptada». Luego, para todas las solicitudes al servidor de la centralita, necesitaremos añadir la cookie de autorización a la solicitud.

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

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

Cómo obtener la cookie de autorización y usarla en otras solicitudes se puede leer aquí: «Zabbix — ampliando los límites de los macros»

Para crear elementos de seguimiento en Zabbix, utilizaré la autodetección.

Autodetección

Para la autodetección de registros y seguimiento del estado de los pares, es necesario dirigirse a la dirección: https://ats:8089/mxml?action=SIPshowregistry o https://ats:8089/mxml?action=SIPpeers

En respuesta, la centralita nos devuelve un XML:

...









...

La respuesta contiene mucho ruido, por lo que en el preprocesamiento lo filtramos con una plantilla. XPath: //response/generic[@host]
Aquí comienza lo más interesante. Para trabajar con la detección y crear elementos de forma dinámica, es necesario que la respuesta esté en formato JSON. XML no es compatible durante las auto-detecciones.

Para convertir XML a JSON, tuve que jugar un poco con la sustitución automática, para lo cual hice un script en JS.

Cómo integrar Zabbix con Asterisk ‘out of the box’

Un detalle interesante es que en la respuesta de la central telefónica, todos los parámetros están entre comillas simples, y después de aplicar la plantilla, //response/generic[@host] se reemplazan por comillas dobles.

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

Cómo integrar Zabbix con Asterisk ‘out of the box’

SIP Registry

Para las inscripciones SIP, utilizamos tres variables: username, host, port. Me gustaba el nombre del elemento 111111@login.mtt.ru:5060, no encontré situaciones en las que necesitar usar las cinco variables.

El elemento principal que recibe información sobre todas las inscripciones, Asterisk — AMI SIPshowregistry. Cada minuto, realiza una solicitud GET a https://ats:8089/mxml?action=SIPshowregistry, después de lo cual los datos de la respuesta XML se envían a todos los elementos dependientes para su análisis. El elemento para cada inscripción lo creo dependiente de él. Esto es conveniente, ya que obtenemos información actual en una sola solicitud, y no para cada uno por separado. Esta implementación tiene una desventaja significativa: la carga en el procesador.

Durante las pruebas con hasta 100 elementos dependientes, no noté la carga, pero con 1700 elementos, eso provocaba una carga notable de 15 segundos en el procesador. Tenga esto en cuenta si tiene una gran cantidad de elementos dependientes.

Como opción para "dispersar" la carga o establecer diferentes frecuencias de consulta para los elementos, se puede sacar la lógica de procesamiento a cada elemento por separado.

No guardo la información obtenida en el elemento principal. Primero, no veo la necesidad de hacerlo, y en segundo lugar, si la respuesta supera los 64K, Zabbix la recorta.

Dado que usamos una respuesta XML completa para el elemento dependiente, necesitamos obtener el valor de ese elemento en la preprocesación. A través de XPath así es como se hace:
string(//response/generic[@event='RegistryEntry'][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@state)
Para los estados de registro, no utilicé estados textuales, sino que los convertí a una forma numérica mediante JavaScript:

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

Compañeros SIP

De manera similar a los registros SIP, hay un elemento principal en Asterisk — AMI SIPshowregistry, al cual se añaden dependientes.

Aquí se crean dos elementos dependientes:

  • Estado del par en formato de texto
  • El tiempo de respuesta del dispositivo — si el estado es OK, se escribe el tiempo de respuesta del dispositivo, de lo contrario, «-1»

El camino hasta el elemento ya es un poco más sencillo XPath:

string(//response/generic[@objectname="{#SIP_PEER_OBJECTNAME}"]/@status)

Para el segundo elemento utilicé JavaScript para separar el 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

La solución 'fuera de la caja' puede ser compleja y no siempre clara. Aumenta la flexibilidad y portabilidad entre diferentes sistemas.

¡Les deseo a todos una integración fácil y agradable! Plantilla e instrucciones para la configuración en GitHub.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster