Como conectar Zabbix con Asterisk fóra da caixa

Nun artigo anterior "Zabbix: expansión de límites macro" Díxenche como recibir unha sesión de autorización e substituíla nunha macro de host local. Neste artigo vouche dicir como conectar Zabbix con Asterisk sen scripts e software externos.

A idea de "facer amigos" destes dous sistemas naceu hai moito tempo, sen instalar software ou scripts adicionais. Unha rápida búsqueda en Google deu moitas solucións posibles, todo se reducía ao feito de cargar os scripts (en Pyha, Bash, Python, etc.) ao servidor e estarás feliz. Quería implementar a monitorización "fóra da caixa": sen scripts externos e instalar software adicional no servidor con monitorización e PBX.

Pasei un total de 4 días laborables con isto, pero o resultado pagou a pena. Traballar a través da interface AMI, detección de baixo nivel, disparadores e, o máis importante, conectar a PBX e todas as outras configuracións leva agora uns 15 minutos.

Zabbix 4.4 está dispoñible, preto de 100 pezas da versión 13 de Asterisk. Algúns PBX inclúen a interface web FreePBX, algúns cunha consola simple, unha morea de trucos e integración mediante un plan de marcación.

Recepción de datos da PBX

O primeiro e principal punto que hai que resolver é a obtención de datos sobre os compañeiros e rexistros SIP. Para este fin, a central conta con interfaces de consola AGI, AMI, ARI e SSH. Por razóns obvias, non considerei módulos adicionais.

Primeiro temos que descubrir cales son estes agi, ami, ari...

  • AGI - usando scripts no dialplan. Úsase principalmente para a xestión de chamadas.
  • AMI - pode proporcionar toda a información necesaria, funciona a través do porto 5038, semellante a Telnet. Nos convén!
  • ARI - moderno, de moda, JSON. Hai moitas posibilidades, o formato de datos é comprensible para Zabbix, pero para min non hai cousa principal: non podes controlar o rexistro do sorbo. Outra desvantaxe é que para os compañeiros só hai dous estados online/offline, aínda que hai máis estados e é útil telos en conta á hora de diagnosticar.
  • SSH pode facer de todo, pero ás veces non está permitido por "motivos de seguridade". As consideracións poden ser diferentes, non vou entrar nelas.

Non obstante, con todas as súas deficiencias, ARI cobre o 90% de todas as necesidades de vixilancia.

Zabbix e Telnet - a miña decepción

Coñezo ben a AMI; no seu momento implementei o seguimento de perdas nas conversas con división por oficinas remotas, xestión de chamadas, etc. Con Telnet tamén está todo moi claro: abre a conexión, envía os comandos e le a resposta. Iso fixen, pero o resultado decepcionoume.

Telnet en Zabbix non é o mesmo que na consola Linux, é un pouco máis sinxelo e adaptado para a autorización estándar, como inicio de sesión/contrasinal. Se a lóxica de autorización é diferente e non se solicita un par de inicio de sesión/contrasinal, prodúcese un erro. Despois de tentativas inútiles de eludir o requisito de autorización, foi útil mirar o código fonte do módulo Telnet.

Decateime de que ata que non haxa unha solicitude de inicio de sesión e contrasinal tradicional, non seguirei adiante. Só por diversión, quitei do código todo o relacionado coa autorización e volvín montar todo. Funciona! Pero non cumpre cos requisitos. Adiante…

Volvamos á procura

Volvín a ler a documentación de ARI, realicei probas adicionais: aquí non hai rexistros de sorbos. Hai festas, hai conversas, hai calzóns, pero non hai inscricións. Nalgún momento ata pensei, realmente necesitamos o rexistro de voitres?

Por unha divertida coincidencia, neste momento chega outra solicitude do usuario, cun problema coas chamadas saíntes. O problema foi que o rexistro do sorbo estaba conxelado e resolveuse simplemente reiniciando o módulo.

asterisk -rx "sip reload"

Sería xenial acceder a AMI a través da web: iso resolvería todos os problemas, pensei. Comezo a cavar nesta dirección e, literalmente, a primeira liña de busca leva á documentación oficial de Asterisk, que di que hai unha opción para as miñas tarefas. habilitado para a web en arquivo /etc/asterisk/manager.conf, que debe configurarse como SI, na sección [xeral]

Despois diso, a través dunha solicitude web habitual do formulario http://ats:8089/mxml?action=SIPshowregistry recibimos toda a información necesaria.

Cando se utiliza a interface FreePBX, non pode activar esta opción a través da web; cómpre activala a través da consola facendo cambios no ficheiro manager.conf. FreePBX non o borra cando se realizan cambios de configuración a través da web.

Traballei con varios tipos de integracións de Asterisk durante moito tempo, pero nunca vin esta función mencionada en ningún lado. Sorprendeume que ninguén describa este método de interactuar co PBX. Mesmo foi especialmente útil buscar información sobre este tema: practicamente non hai nada ou utilizouse para tarefas completamente diferentes.

WEB AMI - que tipo de besta?

Engadindo unha opción habilitado para a web para arquivar xestor.conf proporcionou acceso completo á xestión de ATS a través da web. Todos os comandos dispoñibles a través dunha AMI normal están agora na web, podes escoitar eventos desde a central a través dun socket. O principio de funcionamento non é diferente do AMI da consola. Despois de activar esta opción, pode poñerse en contacto coa PBX nos seguintes enderezos:

https://ats:8089/manager — unha páxina web cunha interface sinxela para probar e enviar solicitudes manualmente. Todas as respostas teñen formato HTML lexible. Non moi axeitado para o seguimento.
https://ats:8089/rawman — Só saída de texto, formato similar ao AMI da consola
https://ats:8089/mxml - só saída de texto, en formato XML. Nos convén!

Como conectar Zabbix con Asterisk fóra da caixa

Entón pensei: "Esta é a solución! Agora todo estará listo! Espremedor de limón fácil de usar", pero era demasiado cedo para alegrarse. Para obter a información que necesitamos basta con utilizar unha solicitude GET coa acción necesaria acción, que en resposta devolve xml cunha lista de todos os rexistros e o seu estado. Todo isto é xenial, pero necesitas autorización para lembrar a sesión da cookie. Cando probas no navegador, non pensas neste proceso.

Proceso de autorización

Primeiro abordamos o enderezo http://ats:8089/mxml?action=login&username=zabbix&secret=zabbix, en resposta, o servidor envíanos unha cookie coa sesión de autorización. Este é o aspecto dunha solicitude 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

Resposta:

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 traballar alí necesitas mansession_id="6f5de42c", é dicir, a propia cookie de autorización.
Contido que só precisa comprobar a resposta "Autenticación aceptada" A continuación, para todas as chamadas ao servidor PBX, necesitaremos engadir unha cookie de autorización á solicitude.

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

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

Lea como obter unha cookie de autorización e usala noutras solicitudes aquí: "Zabbix - expansión de límites macro»

Para crear elementos de seguimento en Zabbix usarei a detección automática.

Detección automática

Para detectar automaticamente os rexistros e realizar un seguimento dos estados do mesmo, debes contactar co seguinte enderezo: https://ats:8089/mxml?action=SIPshowregistry ou https://ats:8089/mxml?action=SIPpeers

Como resposta, o PBX devolvenos unha resposta 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>

Hai moito lixo na resposta, polo que no preprocesamento filtrámola por modelo XPath: //resposta/genérico[@host]
Entón comeza a diversión. Para traballar coa detección e crear elementos de forma dinámica, a resposta debe estar en formato JSON. XML non é compatible para as deteccións automáticas.

Para converter XML a JSON, tiven que xogar un pouco coa substitución automática, para o que fixen un script en JS

Como conectar Zabbix con Asterisk fóra da caixa

Un punto interesante: na resposta ATS, todos os parámetros están rodeados de comiñas simples e despois de aplicar o modelo //resposta/genérico[@host] substitúense por dobres.

Para crear elementos, usamos variables da resposta XML (agora JSON).

Como conectar Zabbix con Asterisk fóra da caixa

Rexistro SIP

Para os rexistros por sorbo usamos tres variables: nome de usuario, anfitrión, porto. Quedei feliz co nome do elemento [protexido por correo electrónico]: 5060, Non atopei ningunha situación en que necesites usar as cinco variables.

O elemento principal que recibe información sobre todas as inscricións, Asterisk - AMI SIPshowregistry. Unha vez por minuto fai unha solicitude GET a https://ats:8089/mxml?action=SIPshowregistry, despois de que os datos XML da resposta pásanse a todos os elementos dependentes para analizalos. Para cada rexistro creo un elemento dependente del. Isto é conveniente porque recibimos información actualizada nunha única solicitude, e non para cada solicitude por separado. Esta implementación ten un inconveniente importante: a carga do procesador.

Ao probar ata 100 elementos dependentes, non notei a carga, pero con 1700 elementos, isto deu unha carga notable de 15 segundos no procesador. Ten en conta isto se tes un gran número de elementos dependentes.

Como opción para "estender" a carga ou establecer diferentes frecuencias de sondeo para un elemento, pode mover a lóxica de procesamento a cada elemento por separado.

Non gardo a información recibida no elemento principal. En primeiro lugar, non vexo a necesidade diso e, en segundo lugar, se a resposta é superior a 64 K, entón Zabbix corta.

Dado que usamos unha resposta XML completa para o elemento dependente, necesitamos obter o valor deste elemento no preprocesamento. A través XPath Faise así:
string(//response/generic[@event="RegistryEntry"][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@ estado)
Para os estados de rexistro, non usei estados de texto, pero convertínos en formato numérico usando JavaScript:

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

SIP Peers

Por analoxía cos rexistros SIP, hai un elemento principal de Asterisk - AMI SIPshowregistry, ao que se engaden os dependentes.

Isto crea dous elementos dependentes:

  • Estado de iguais en forma de texto
  • Tempo de resposta do dispositivo: se o estado é correcto, escríbese o tempo de resposta do dispositivo; se non, "-1"

O camiño ata o elemento en si é un pouco máis sinxelo XPath:

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

Para o segundo elemento usei JavaScript para separar tempo de resposta desde o estado de igual, xa que se almacenan xuntos:

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

Conclusión

Unha solución lista para usar pode ser complexa e non ser inmediatamente clara. Aumenta a flexibilidade e a portabilidade entre distintos sistemas

Feliz e fácil integración para todos! Modelo e instrucións para a súa configuración GitHub.

Fonte: www.habr.com

Engadir un comentario