Wie man Zabbix ohne Zusatzaufwand mit Asterisk verbindet

Im vorherigen Artikel „Zabbix – die Makrogrenzen erweitern“ habe ich erklĂ€rt, wie man eine Authentifizierungssitzung erhĂ€lt und diese in das lokale Makro des Hosts einfĂŒgt. In diesem Artikel werde ich erklĂ€ren, wie man Zabbix ohne externe Skripte und Software mit Asterisk verbindet.

Die Idee, diese beiden Systeme zu verbinden, kam schon vor einiger Zeit auf, und zwar ohne die Installation zusĂ€tzlicher Software und Skripte. Eine schnelle Google-Suche ergab viele Lösungsmöglichkeiten, die alle darauf hinausliefen, Skripte (in PHP, Bash, Python usw.) auf den Server zu laden, und dann wĂŒrde alles gut werden. Ich wollte jedoch die Überwachung „out of the box“ umsetzen – ohne externe Skripte und die Installation zusĂ€tzlicher Software auf dem Server mit der Überwachung und der Telefonanlage.

Ich habe insgesamt 4 Arbeitstage damit verbracht, aber das Ergebnis war es wert. Die Arbeit ĂŒber die AMI-Schnittstelle, die Low-Level-Erkennung, Trigger und vor allem dauert die Verbindung zur Telefonanlage und alle anderen Einstellungen jetzt nur noch etwa 15 Minuten.

Es steht Zabbix 4.4 zur VerfĂŒgung, etwa 100 StĂŒck Asterisk der Version 13. Einige Telefonanlagen kommen mit der WeboberflĂ€che FreePBX, andere mit einer einfachen Konsole, vielen Tricks und der Integration ĂŒber den Dialplan.

Daten von der Telefonanlage abrufen

Der erste und wichtigste Punkt, den es zu lösen gilt, ist der Erhalt von Daten ĂŒber Peers und SIP-Registrierungen. DafĂŒr gibt es in der Telefonanlage die Schnittstellen AGI, AMI, ARI und die SSH-Konsole. ZusĂ€tzliche Module habe ich aus verstĂ€ndlichen GrĂŒnden nicht betrachtet.

ZunÀchst muss man verstehen, was diese AGI, AMI, ARI
 sind.

  • AGI – die Verwendung von Skripten im Dialplan. Wird hauptsĂ€chlich zur Steuerung von Anrufen verwendet.
  • AMI – kann alle benötigten Informationen bereitstellen und arbeitet ĂŒber den Port 5038 Ă€hnlich wie Telnet. Das passt zu uns!
  • ARI – modern, schick, JSON-basiert. Viele Möglichkeiten, das Datenformat ist in einem verstĂ€ndlichen Format fĂŒr Zabbix, aber fĂŒr mich fehlt das Wichtigste: man kann die SIP-Registrierung nicht kontrollieren. Ein weiterer Nachteil ist, dass es fĂŒr Peers nur zwei ZustĂ€nde gibt: online/offline, obwohl es mehr ZustĂ€nde gibt und es nĂŒtzlich ist, diese bei der Diagnose zu berĂŒcksichtigen.
  • SSH – kann alles, wird aber manchmal aus „SicherheitsgrĂŒnden“ nicht bereitgestellt. Die GrĂŒnde dafĂŒr können unterschiedlich sein, ich werde sie hier nicht erörtern.

Dennoch deckt ARI trotz aller seiner Nachteile 90 % aller Anforderungen an die Überwachung ab.

Zabbix und Telnet – meine EnttĂ€uschung

Ich kenne AMI gut, ich habe zu meiner Zeit die Überwachung von Verlusten in GesprĂ€chen mit dem Fokus auf entfernte BĂŒros, Anrufmanagement usw. implementiert. Mit Telnet ist auch alles klar: Verbindung öffnen, Befehle senden und Antworten lesen. Das habe ich gemacht, aber das Ergebnis hat mich enttĂ€uscht.

Das Telnet von Zabbix ist nicht das gleiche wie in der Linux-Konsole; es ist etwas einfacher und auf die Standardautorisierung wie Benutzername/Passwort angepasst. Wenn die Autorisierungslogik anders ist und keine Abfrage von Benutzername/Passwort erfolgt, tritt ein Fehler auf. Nach vergeblichen Versuchen, das Autorisierungsverlangen zu umgehen, habe ich die Quellcodes des Telnet-Moduls angesehen.

Ich verstand, dass ich nicht weiterkomme, solange die traditionelle Abfrage nach Benutzername und Passwort nicht erfolgt. Aus Interesse habe ich alles, was die Autorisierung betrifft, aus dem Code entfernt und alles neu kompiliert. Es funktioniert! Aber es erfĂŒllt die Anforderungen nicht. Gehen wir weiter


Kehren wir zur Suche zurĂŒck.

Ich habe die Dokumentation zu ARI erneut durchgelesen und zusĂ€tzliche Tests durchgefĂŒhrt - es gibt hier keine SIP-Registrierungen. Es gibt Peers, es gibt GesprĂ€che, es gibt Bridges, aber keine Registrierungen. Irgendwann habe ich sogar darĂŒber nachgedacht, ob wir wirklich so sehr auf SIP-Registrierungen angewiesen sind.

Durch einen lustigen Zufall kommt in diesem Moment eine weitere Anfrage von einem Benutzer mit dem Problem der ausgehenden Anrufe. Das Problem lag in einer Blockade der SIP-Registrierung und wurde mit einem einfachen Neustart des Moduls gelöst.

asterisk -rx "sip reload"

Es wĂ€re großartig, ĂŒber das Web auf AMI zuzugreifen: das wĂŒrde alle Probleme lösen, dachte ich. Ich beginne in diese Richtung zu graben, und die erste Suchzeile fĂŒhrt direkt zur offiziellen Asterisk-Dokumentation, die besagt, dass es fĂŒr meine Anforderungen eine Option gibt. webenabled in der Datei /etc/asterisk/manager.conf, die auf YES gesetzt werden muss, im Abschnitt [general]

Nach dieser Änderung ĂŒber eine normale Webanfrage in der Art von http://ats:8089/mxml?action=SIPshowregistry bekommen wir alle notwendigen Informationen.

Bei der Verwendung der FreePBX-Schnittstelle kann diese Option ĂŒber das Web nicht aktiviert werden; sie muss ĂŒber die Konsole aktiviert werden, indem Änderungen an der Datei manager.conf vorgenommen werden. FreePBX löscht diese nicht bei Änderungen der Konfiguration ĂŒber das Web.

So lange ich mit verschiedenen Arten von Asterisk-Integrationen gearbeitet habe, habe ich nie gesehen, dass diese Funktion irgendwo erwĂ€hnt wird. Es hat mich ĂŒberrascht, dass niemand diese Methode der Interaktion mit der TK-Anlage beschreibt. Selbst bei gezielter Suche nach Informationen zu diesem Thema gibt es praktisch nichts oder sie wurden fĂŒr ganz andere Aufgaben verwendet.

WEB AMI – was ist das fĂŒr ein Tier?

HinzufĂŒgen der Option webenabled in die Datei manager.conf ermöglichte den vollstĂ€ndigen Zugriff auf die Steuerung der PBX ĂŒber das Web. Alle Befehle, die ĂŒber das klassische AMI verfĂŒgbar sind, sind jetzt im Web verfĂŒgbar, man kann Ereignisse von der PBX ĂŒber einen Socket anhören. Das Prinzip funktioniert genauso wie beim Konsolen-AMI. Nach Aktivierung dieser Option kann die PBX ĂŒber die folgenden Adressen angesprochen werden:

https://ats:8089/manager — eine Webseite mit einfacher BenutzeroberflĂ€che, fĂŒr Tests und manuelles Senden von Anfragen. Alle Antworten werden in lesbarem HTML-Format formatiert. Zum Monitoring ist es nicht sehr geeignet.
https://ats:8089/rawman — nur Textausgabe, das Format ist Ă€hnlich dem Konsolen-AMI
https://ats:8089/mxml — nur Textausgabe, im XML-Format. Das passt uns!

Wie man Zabbix ohne Zusatzaufwand mit Asterisk verbindet

Hier dachte ich: „Das ist es – die Lösung! Jetzt wird alles bereit sein! Easy peasy lemon squeezy“, aber es war noch zu frĂŒh, sich zu freuen. Um die benötigten Informationen zu erhalten, reicht es aus, eine GET-Anfrage mit der richtigen Aktion zu verwenden, Aktion, die als Antwort XML mit einer Liste aller Registrierungen und deren Status zurĂŒckgibt. Das ist alles großartig, aber es wird eine Authentifizierung benötigt, die die Sitzung aus Cookies speichert. Wenn man im Browser testet, denkt man nicht an diesen Prozess.

Der Authentifizierungsprozess

ZunÀchst wenden wir uns an die Adresse http://ats:8089/mxml?action=login&username=zabbix&secret=zabbix, als Antwort sendet uns der Server ein Cookie mit der Authentifizierungssitzung. So sieht die HTTP-Anfrage aus:

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

Antwort:

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

Um dort zu arbeiten, benötigt man mansession_id="6f5de42c", das ist das Authentifizierungscookie selbst.
Der Inhalt muss nur auf die Antwort „Authentifizierung akzeptiert“ geprĂŒft werden. Danach mĂŒssen wir bei allen Anfragen an den PBX-Server das Authentifizierungscookie zu den Anfragen hinzufĂŒgen.

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

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

Wie man das Authentifizierungscookie erhĂ€lt und in anderen Anfragen verwendet, lesen Sie hier: „Zabbix — erweiterbare Makrogrenzen»

FĂŒr die Erstellung von Überwachungsobjekten in Zabbix werde ich die automatische Erkennung verwenden.

Automatische Erkennung

FĂŒr die automatische Erkennung von Registrierungen und zur Überwachung des Status der Peers muss man sich an die Adresse wenden: https://ats:8089/mxml?action=SIPshowregistry oder https://ats:8089/mxml?action=SIPpeers

Als Antwort gibt die PBX uns eine XML-Antwort zurĂŒck:

...









...

Im Antworttext gibt es viel Unnötiges, deshalb filtern wir es im Preprocessing nach einem Muster. XPath: //response/generic[@host]
Jetzt wird es interessant. Um mit der Erkennung zu arbeiten und Elemente dynamisch zu erstellen, muss die Antwort im JSON-Format vorliegen. XML wird bei automatischen Erkennung nicht unterstĂŒtzt.

Um XML in JSON umzuwandeln, musste ich ein wenig mit automatischen Ersetzungen experimentieren, dafĂŒr habe ich ein Skript in JS erstellt.

Wie man Zabbix ohne Zusatzaufwand mit Asterisk verbindet

Ein interessanter Punkt ist, dass in der Antwort der TK alle Parameter in einfachen AnfĂŒhrungszeichen gefasst sind, die nach der Anwendung des Musters //response/generic[@host] in doppelte AnfĂŒhrungszeichen umgewandelt werden.

FĂŒr die Erstellung von Elementen verwenden wir Variablen aus der XML-Antwort (jetzt JSON).

Wie man Zabbix ohne Zusatzaufwand mit Asterisk verbindet

SIP-Registry

FĂŒr SIP-Registrierungen verwenden wir drei Variablen: username, host, port. Der Name des Elements hat mir gefallen. 111111@login.mtt.ru:5060, ich habe keine FĂ€lle gefunden, in denen alle fĂŒnf Variablen benötigt werden.

Das Hauptelement, das Informationen ĂŒber alle Registrierungen erhĂ€lt, Asterisk — AMI SIPshowregistry. Einmal pro Minute sendet es eine GET-Anfrage an https://ats:8089/mxml?action=SIPshowregistry, wonach die Daten der XML-Antwort an alle abhĂ€ngigen Elemente zur Analyse ĂŒbergeben werden. Ich erstelle die Elemente fĂŒr jede Registrierung, die von ihm abhĂ€ngig sind. Das ist praktisch, da wir aktuelle Informationen mit einer einzigen Anfrage erhalten, und nicht fĂŒr jede einzelne. Diese Implementierung hat einen wesentlichen Nachteil — die CPU-Belastung.

Bei Tests mit bis zu 100 abhĂ€ngigen Elementen habe ich keine Belastung bemerkt, aber bei 1700 Elementen war dies eine spĂŒrbare Belastung von 15 Sekunden auf die CPU. Bitte beachten Sie dies, wenn Sie eine große Anzahl abhĂ€ngiger Elemente haben.

Eine Möglichkeit, die Last zu verteilen oder eine unterschiedliche Abfragedauer fĂŒr das Element festzulegen, besteht darin, die Logik der Verarbeitung in jedes Element einzeln auszulagern.

Die erhaltenen Informationen speichere ich nicht im Hauptelement. Erstens sehe ich dafĂŒr keinen Bedarf, und zweitens, wenn die Antwort mehr als 64K betrĂ€gt, schneidet Zabbix sie ab.

Da fĂŒr das abhĂ€ngige Element die komplette XML-Antwort verwendet wird, mĂŒssen wir im Preprocessing den Wert dieses Elements abrufen. Durch XPath geschieht dies so:
string(//response/generic[@event="RegistryEntry"][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@state)
FĂŒr die Registrierungsstatus habe ich keine Textstatus verwendet, sondern sie mithilfe von JavaScript in numerische Werte umgewandelt:

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

SIP Peers

Analog zu den SIP-Registrierungen gibt es das Hauptelement Asterisk – AMI SIPshowregistry, an das abhĂ€ngige Elemente angehĂ€ngt werden.

Hier werden zwei abhÀngige Elemente erstellt:

  • Der Status des Peers in Textform
  • Die Antwortzeit des GerĂ€ts – wenn der Status OK ist, wird die Antwortzeit des GerĂ€ts angegeben, andernfalls „-1“

Der Pfad zum Element ist bereits etwas einfacher XPath:

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

FĂŒr das zweite Element habe ich JavaScript verwendet, um die Antwortzeit vom Peer-Status zu trennen, da sie zusammen gespeichert werden:

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

Fazit

Eine „Out-of-the-Box“-Lösung kann komplex und nicht sofort verstĂ€ndlich sein. Die FlexibilitĂ€t und PortabilitĂ€t zwischen verschiedenen Systemen steigt.

Allen eine angenehme und einfache Integration! Vorlage und Anleitung zur Einrichtung bei GitHub.

Quelle: habr.com

60GB SSD 8Gb DDR4