Como conectar Zabbix com Asterisk pronto para uso

Em um artigo anterior "Zabbix - expandindo limites macro" Eu lhe disse como receber uma sessão de autorização e substituí-la em uma macro de host local. Neste artigo vou lhe dizer como conectar o Zabbix ao Asterisk sem scripts e software externos.

A ideia de “fazer amigos” destes dois sistemas nasceu há muito tempo, sem instalar software ou scripts adicionais. Uma rápida pesquisa no Google rendeu muitas soluções possíveis, tudo se resumia ao fato de fazer upload dos scripts (em Pyha, Bash, Python, etc.) para o servidor, e você ficará feliz. Eu queria implementar o monitoramento “pronto para usar” - sem scripts externos e instalando software adicional no servidor com monitoramento e PBX.

Passei um total de 4 dias úteis com isso, mas o resultado valeu a pena. Trabalhar através da interface AMI, detecção de baixo nível, gatilhos e, o mais importante, conectar o PBX e todas as outras configurações agora leva cerca de 15 minutos.

O Zabbix 4.4 está disponível, cerca de 100 peças do Asterisk versão 13. Alguns PBXs vêm com a interface web FreePBX, alguns com um console simples, vários truques e integração por meio de um plano de discagem.

Recebendo dados do PABX

O primeiro e principal ponto que precisa ser resolvido é a obtenção de dados sobre peers e registros SIP. Para isso, o PBX possui interfaces de console AGI, AMI, ARI e SSH. Por razões óbvias, não considerei módulos adicionais.

Primeiro precisamos descobrir o que são esses agi, ami, ari...

  • AGI - usando scripts no dialplan. Usado principalmente para gerenciamento de chamadas.
  • AMI - pode fornecer todas as informações necessárias, funciona via porta 5038, semelhante ao Telnet. Nos serve!
  • ARI - moderno, elegante, JSON. As possibilidades são muitas, o formato dos dados é compreensível para o Zabbix, mas para mim não há nada principal: você não pode controlar o registro do sip. Outra desvantagem é que para os pares existem apenas dois estados online/offline, embora existam mais estados e seja útil levá-los em consideração no diagnóstico.
  • O SSH pode fazer tudo, mas às vezes não é permitido por “razões de segurança”. As considerações podem ser diferentes, não vou entrar nelas.

Contudo, com todas as suas deficiências, o IRA cobre 90% de todas as necessidades de monitorização.

Zabbix e Telnet - minha decepção

Conheço bem a AMI, numa época implementei rastreamento de perdas em conversas com divisão por escritórios remotos, gerenciamento de chamadas, etc. Com o Telnet também tudo fica muito claro: abra a conexão, envie os comandos e leia a resposta. Foi o que fiz, mas o resultado me decepcionou.

Telnet no Zabbix não é igual ao console Linux, é um pouco mais simples e adaptado para autorização padrão como login/senha. Se a lógica de autorização for diferente e não houver solicitação de par login/senha, ocorrerá um erro. Após tentativas inúteis de contornar o requisito de autorização, foi útil examinar o código-fonte do módulo Telnet.

Percebi que até que haja uma solicitação tradicional de login e senha, não avançarei. Só por diversão, removi tudo relacionado à autorização do código e reconstruí tudo. Funciona! Mas não atende aos requisitos. Vá em frente…

Voltemos à pesquisa

Reli a documentação do ARI novamente, executei testes adicionais - não há registros de sip aqui. Há festas, há conversas, há calções, mas não há inscrições. Em algum momento até pensei: precisamos mesmo do registro do abutre?

Por uma curiosa coincidência, neste momento chega outra solicitação do usuário, com problema nas chamadas efetuadas. O problema era que o registro do sip estava travando e foi resolvido simplesmente reiniciando o módulo.

asterisk -rx "sip reload"

Seria ótimo acessar a AMI pela web: isso resolveria todos os problemas, pensei. Começo a cavar nessa direção e literalmente a primeira linha de pesquisa leva à documentação oficial do Asterisk, que diz que existe uma opção para minhas tarefas habilitado para web no arquivo /etc/asterisk/manager.conf, que precisa ser definido como SIM, na seção [geral]

Depois disso, por meio de uma solicitação regular na web do formulário http://ats:8089/mxml?action=SIPshowregistry obtemos todas as informações necessárias.

Ao usar a interface FreePBX, você não pode habilitar esta opção via web; você precisa habilitá-la através do console fazendo alterações no arquivo manager.conf. O FreePBX não o apaga quando alterações de configuração são feitas via web.

Trabalho com vários tipos de integrações com Asterisk há muito tempo, mas nunca vi esse recurso mencionado em lugar nenhum. Fiquei surpreso que ninguém descreve esse método de interação com o PBX. Foi até especialmente útil procurar informações sobre este tema: não há praticamente nada ou foi utilizado para tarefas completamente diferentes.

WEB AMI - que tipo de fera?

Adicionando uma opção habilitado para web arquivar gerente.conf forneceu acesso total ao gerenciamento ATS via web. Todos os comandos disponíveis através de uma AMI normal agora estão na web, você pode ouvir eventos do PBX através de um soquete. O princípio de operação não é diferente do console AMI. Após ativar esta opção, você pode entrar em contato com o PABX nos seguintes endereços:

https://ats:8089/manager — uma página web com uma interface simples para testar e enviar solicitações manualmente. Todas as respostas são formatadas em HTML legível. Não é muito adequado para monitoramento.
https://ats:8089/rawman — somente saída de texto, formato semelhante ao console AMI
https://ats:8089/mxml - somente saída de texto, em formato XML. Nos serve!

Como conectar Zabbix com Asterisk pronto para uso

Aí pensei: “Essa é a solução! Agora tudo estará pronto! Espremedor de limão fácil de usar”, mas era muito cedo para se alegrar. Para obter as informações que necessitamos, basta utilizar uma solicitação GET com a ação necessária açao, que em resposta retorna xml com uma lista de todos os cadastros e seus status. Tudo isso é ótimo, mas você precisa de autorização para lembrar a sessão do cookie. Ao testar no navegador, você não pensa nesse processo.

Processo de autorização

Primeiro abordamos o endereço http://ats:8089/mxml?action=login&username=zabbix&secret=zabbix, em resposta, o servidor nos envia um cookie com a sessão de autorização. Esta é a aparência de uma solicitação 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 trabalhar lá você precisa mansession_id="6f5de42c", ou seja, o próprio cookie de autorização.
Conteúdo que você só precisa verificar a resposta "Autenticação aceita" A seguir, para todas as chamadas para o servidor PBX, precisaremos adicionar um cookie de autorização à solicitação.

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

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

Leia como obter um cookie de autorização e utilizá-lo em outras solicitações aqui: “Zabbix - expandindo os limites macro»

Para criar elementos de rastreamento no Zabbix usarei detecção automática.

Detecção automática

Para detectar registros automaticamente e rastrear estados de pares, você precisa entrar em contato com o seguinte endereço: https://ats:8089/mxml?action=SIPshowregistry ou https://ats:8089/mxml?action=SIPpeers

Em resposta, o PBX nos retorna uma 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>

Há muito lixo na resposta, então no pré-processamento filtramos por template XPath: //resposta/genérico[@host]
Então a diversão começa. Para trabalhar com detecção e criar elementos dinamicamente, a resposta deve estar no formato JSON. XML não é compatível com detecções automáticas.

Para converter XML para JSON tive que brincar um pouco com a substituição automática, para a qual fiz um script em JS

Como conectar Zabbix com Asterisk pronto para uso

Um ponto interessante: na resposta ATS, todos os parâmetros estão entre aspas simples, e após a aplicação do template //resposta/genérico[@host] eles são substituídos por duplos.

Para criar elementos, usamos variáveis ​​da resposta XML (agora JSON).

Como conectar Zabbix com Asterisk pronto para uso

Registro SIP

Para registros sip usamos três variáveis: nome de usuário, hospedeiro, porta. Fiquei feliz com o nome do elemento [email protegido]: 5060, não encontrei nenhuma situação em que você precise usar todas as cinco variáveis.

O principal elemento que recebe informações sobre todos os cadastros, Asterisk - AMI SIPshowregistry. Uma vez por minuto ele faz uma solicitação GET para https://ats:8089/mxml?action=SIPshowregistry, após o qual os dados XML de resposta são passados ​​para todos os elementos dependentes para análise. Para cada cadastro eu crio um elemento dependente dele. Isso é conveniente porque recebemos informações atualizadas em uma solicitação, e não para cada solicitação separadamente. Esta implementação tem uma desvantagem significativa - a carga do processador.

Ao testar até 100 elementos dependentes, não notei a carga, mas com 1700 elementos, isso deu uma carga perceptível de 15 segundos no processador. Tenha isso em mente se você tiver um grande número de elementos dependentes.

Como uma opção para “distribuir” a carga ou definir diferentes frequências de pesquisa para um elemento, você pode mover a lógica de processamento para cada elemento separadamente.

Não guardo as informações recebidas no elemento principal. Em primeiro lugar, não vejo necessidade disso e, em segundo lugar, se a resposta for superior a 64K, o Zabbix a corta.

Como usamos uma resposta XML completa para o elemento dependente, precisamos obter o valor desse elemento no pré-processamento. Através XPath é feito assim:
string(//response/generic[@event="RegistryEntry"][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@ estado)
Para status de registro, não usei status de texto, mas os converti em formato numérico usando JavaScript:

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

Pares SIP

Por analogia com os registros SIP, existe um elemento principal do Asterisk - AMI SIPshowregistry, ao qual são adicionados os dependentes.

Isso cria dois elementos dependentes:

  • Status de peer em formato de texto
  • Tempo de resposta do dispositivo - se o status estiver OK, então o tempo de resposta do dispositivo é escrito, caso contrário “-1”

O caminho para o elemento em si é um pouco mais simples XPath:

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

Para o segundo elemento usei JavaScript para separar tempo de resposta do status de peer, uma vez que eles são armazenados juntos:

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

Conclusão

Uma solução pronta para uso pode ser complexa e não imediatamente clara. Aumenta a flexibilidade e portabilidade entre diferentes sistemas

Boa e fácil integração a todos! Modelo e instruções para configuração GitHub.

Fonte: habr.com

Adicionar um comentário