Wie Zabbix problemlos mit Asterisk zusammenarbeitet

Im vorherigen Artikel «Zabbix – Makro-Grenzen erweitern» Ich habe erzählt, wie man eine Autorisierungssitzung erhält und diese in das lokale Host-Makro 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 integrieren, entstand schon vor einiger Zeit, ohne dass zusätzliche Software oder Skripte installiert werden mussten. Eine schnelle Google-Suche lieferte viele Lösungsvorschläge, aber alle liefen darauf hinaus, dass man Skripte (in PHP, Bash, Python usw.) auf den Server laden sollte, um glücklich zu sein. Ich wollte jedoch das Monitoring 'out of the box' umsetzen – ohne externe Skripte und ohne zusätzliche Software auf dem Überwachungs- und Telefonserver.

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 braucht man jetzt nur noch etwa 15 Minuten für die Verbindung mit der Telefonanlage und alle anderen Einstellungen.

Vorhanden ist Zabbix 4.4, mit etwa 100 Asterisk 13 Systemen. Einige Telefonanlagen verfügen über die Web-Oberfläche FreePBX, andere haben nur eine einfache Konsole, zahlreiche Tricks und Integrationen über den Dialplan.

Daten aus der Telefonanlage abrufen

Der erste und wichtigste Punkt, der geklärt werden muss, ist der Zugriff auf Daten zu Peers und SIP-Registrierungen. Hierfür bietet die Telefonanlagen verschiedene Schnittstellen wie AGI, AMI, ARI und die SSH-Konsole. Zusätzliche Module habe ich aus offensichtlichen Gründen nicht betrachtet.

Zunächst gilt es, zu verstehen, was diese AGI, AMI, ARI ... wirklich sind.

  • AGI – die Nutzung von Skripten im Dialplan. Hauptsächlich wird es zur Steuerung von Anrufen verwendet.
  • AMI – liefert alle notwendigen Informationen und arbeitet über den Port 5038 analog zu Telnet. Das passt uns!
  • ARI – modern, trendig, JSON-basiert. Bietet viele Möglichkeiten, die Datenformate sind verständlich für Zabbix, aber es fehlt mir das Entscheidende: Die Kontrolle über SIP-Registrierungen ist nicht möglich. Ein weiterer Nachteil ist, dass es für Peers nur zwei Zustände gibt: online/offline, obwohl es mehr Zustände gibt, die zur Diagnose nützlich wären.
  • SSH – kann alles, wird aber manchmal aufgrund von "Sicherheitsüberlegungen" nicht gewährt. Die Gründe können unterschiedlich sein, ich möchte sie nicht weiter analysieren.

Dennoch deckt ARI mit all seinen Mängeln 90 % aller Bedürfnisse im Monitoring ab.

Zabbix und Telnet – meine Enttäuschung.

Ich kenne AMI gut, zu meiner Zeit habe ich die Verlustverfolgung in Gesprächen mit Remote-Büros, das Anrufmanagement usw. implementiert. Auch bei Telnet ist alles klar: Verbindung öffnen, Befehle senden und Antwort lesen. Das habe ich auch gemacht, aber das Ergebnis hat mich enttäuscht.

Telnet in Zabbix ist nicht dasselbe wie in der Linux-Konsole, es ist etwas einfacher und auf die Standard-Authentifizierung mit Benutzername/Passwort ausgelegt. Ist die Authentifizierungslogik anders und wird kein Benutzername/Passwort-Paar angefragt, erscheint ein Fehler. Nach erfolglosen Versuchen, die Authentifizierungsanforderung zu umgehen, habe ich beschlossen, die Quelldateien des Telnet-Moduls anzusehen.

Ich habe verstanden, dass ich ohne die traditionelle Anfrage nach Benutzername und Passwort nicht weiterkomme. Aus Interesse habe ich alles, was mit Authentifizierung zu tun hat, aus dem Code entfernt und alles neu kompiliert. Es funktioniert! Aber es entspricht nicht den Anforderungen. Weiter geht's...

Zurück zur Suche

Ich habe die Dokumentation zu ARI nochmals 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, wie wichtig uns SIP-Registrierungen wirklich sind?

Durch einen lustigen Zufall kommt gerade in diesem Moment eine Anfrage von einem Benutzer herein, der ein Problem mit ausgehenden Anrufen hat. Das Problem lag an einem Hängenbleiben der SIP-Registrierung und konnte durch einen einfachen Neustart des Moduls gelöst werden.

asterisk -rx "sip reload"

Es wäre großartig, über das Web auf das AMI zuzugreifen: das würde alle Probleme lösen, dachte ich. Also begann ich, in diese Richtung zu forschen, und die erste Suchzeile führte mich zur offiziellen Dokumentation von Asterisk, wo stand, dass für meine Bedürfnisse eine Option verfügbar ist webenabled in der Datei /etc/asterisk/manager.conf, die auf YES gesetzt werden muss, im Abschnitt [general]

Danach erhalten wir über eine normale Webanfrage des Typs http://ats:8089/mxml?action=SIPshowregistry alle notwendigen Informationen.

Bei der Verwendung der FreePBX-Oberfläche kann diese Option über das Web nicht aktiviert werden; sie muss über die Konsole eingeschaltet werden, indem Änderungen in der Datei manager.conf vorgenommen werden. FreePBX löscht sie nicht bei Änderungen der Konfiguration über das Web.

So viel 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 Interaktionsmethode mit der Telefonanlage beschreibt. Ich habe sogar gezielt nach Informationen zu diesem Thema gesucht: es gibt praktisch nichts oder es wurde für völlig andere Aufgaben verwendet.

WEB AMI – was ist das für ein Ding?

Option hinzufügen webenabled in die Datei manager.conf öffnet den vollständigen Zugriff zur Verwaltung der Telefonanlage über das Web. Alle Kommandos, die normalerweise über das klassische AMI verfügbar sind, können jetzt im Web genutzt werden, man kann Ereignisse von der Telefonanlage über einen Socket hören. Das Prinzip ist das gleiche wie beim Konsolen-AM.

https://ats:8089/manager – eine Webseite mit einer einfachen Benutzeroberfläche, geeignet für Tests und manuelles Senden von Anfragen. Alle Antworten werden in lesbarem HTML-Format angezeigt. Nicht ideal für Monitoring.
https://ats:8089/rawman – nur Textausgabe, das Format ähnelt dem des Konsolen-AMI.
https://ats:8089/mxml – nur Textausgabe im XML-Format. Das passt uns!

Wie Zabbix problemlos mit Asterisk zusammenarbeitet

Hier dachte ich: „Das ist es – die Lösung! Jetzt wird alles bereit sein! Ganz einfach“, aber ich hatte noch zu früh Freude. Um die benötigten Informationen zu erhalten, genügt es, eine GET-Anfrage mit der entsprechenden Aktion zu verwenden. Aktion, die als Antwort ein XML mit einer Liste aller Registrierungen und deren Status zurückgibt. Das klingt alles gut, aber es ist eine Autorisierung erforderlich, die eine Sitzung aus Cookies speichert. Wenn man im Browser testet, denkt man nicht über diesen Prozess nach.

Der Autorisierungsprozess

Zunächst wenden wir uns an die Adresse http://ats:8089/mxml?action=login&username=zabbix&secret=zabbix, auf die der Server uns ein Cookie mit der Autorisierungssitzung zusendet. 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: de-DE,de;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

Für die Arbeit dort benötigen Sie mansession_id="6f5de42c", das heißt das Cookie für die Autorisierung.
Der Inhalt muss nur auf das Vorhandensein der Antwort „Authentifizierung akzeptiert“ überprüft werden. Bei allen Anfragen an den Asterisk-Server müssen wir den Authorization-Cookie zur Anfrage hinzufügen.

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

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

Wie man den Authorization-Cookie erhält und in anderen Anfragen verwendet, lesen Sie hier: „Zabbix — die Grenzen von Makros erweitern»

Zur Erstellung von Tracking-Elementen in Zabbix werde ich die Auto-Entdeckung verwenden.

Auto-Entdeckung

Für die Auto-Entdeckung von Registrierungen und die Überwachung des Status von Peers muss die folgende Adresse aufgerufen werden: https://ats:8089/mxml?action=SIPshowregistry oder https://ats:8089/mxml?action=SIPpeers

Die Asterisk-Software sendet uns eine XML-Antwort zurück:

...









...

Im Antworttext finden sich viele irrelevante Informationen, daher filtern wir sie in der Vorverarbeitung nach einem Muster. XPath: //response/generic[@host]
Jetzt wird es wirklich spannend. Um mit der Erkennung zu arbeiten und Elemente dynamisch zu erstellen, muss die Antwort im JSON-Format vorliegen. XML wird bei der automatischen Erkennung nicht unterstützt.

Um XML in JSON zu konvertieren, musste ich ein wenig mit automatischen Ersetzungen experimentieren, wofür ich ein Skript in JS erstellt habe.

Wie Zabbix problemlos mit Asterisk zusammenarbeitet

Ein interessanter Punkt ist, dass im Antworttext der Telefonanlage alle Parameter in einfachen Anführungszeichen stehen, und nach der Anwendung des Musters //response/generic[@host] werden sie durch doppelte Anführungszeichen ersetzt.

Für die Erstellung der Elemente verwenden wir Variablen aus der XML-Antwort (jetzt JSON).

Wie Zabbix problemlos mit Asterisk zusammenarbeitet

SIP-Registry

Für SIP-Registrierungen verwenden wir drei Variablen: Benutzername, host, port. Ich war mit dem Namen des Elements zufrieden. 111111@login.mtt.ru:5060, Situationen, in denen alle fünf Variablen benötigt werden, habe ich nicht gefunden.

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, nachdem die XML-Antwortdaten an alle abhängigen Elemente zur Analyse übergeben werden. Jedes Element für jede Registrierung wird von ihm abhängig gemacht. Dies ist praktisch, da wir die aktuellen Informationen mit einer einzigen Anfrage erhalten und nicht für jedes Element einzeln. Bei dieser Implementierung gibt es jedoch einen wesentlichen Nachteil – die Belastung des Prozessors.

Bei Tests mit bis zu 100 abhängigen Elementen habe ich keine merkliche Belastung festgestellt, aber bei 1700 Elementen war dies eine spürbare 15-sekündige Belastung für den Prozessor. Bitte beachten Sie dies, wenn Sie eine große Anzahl abhängiger Elemente haben.

Eine Möglichkeit, die Last zu „verstreuen“ oder eine unterschiedliche Abfragefrequenz für jedes Element festzulegen, besteht darin, die Logik der Verarbeitung in jedes Element separat zu verlagern.

Die erhaltenen Informationen speichere ich nicht im Hauptelement. Erstens sehe ich dafür keine Notwendigkeit und zweitens, wenn die Antwort mehr als 64kB beträgt, kürzt Zabbix sie.

Da wir für das abhängige Element die vollständige XML-Antwort verwenden, müssen wir im Preprocessing den Wert dieses Elements abrufen. Über XPath so geht das:
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 textbasierten Status verwendet, sondern sie mithilfe von JavaScript in Zahlen umgewandelt:

switch(value) {
  case 'Registriert':
    return 1;
  case 'Nicht registriert':
    return 0;
  default:
    return -1;
}

SIP-Teilnehmer

Analog zu den SIP-Registrierungen gibt es das Hauptelement Asterisk — AMI SIPshowregistry, zu dem abhängige Elemente hinzugefügt werden.

Hier werden zwei abhängige Elemente erstellt:

  • Der Status des Teilnehmers im Textformat
  • Die Antwortzeit des Geräts — wenn der Status OK ist, wird die Antwortzeit des Geräts angezeigt, andernfalls „-1“

Der Pfad zum Element ist bereits etwas einfacher XPath:

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

Für das zweite Element habe ich JavaScript verwendet, um die Antwortzeit vom Status des Teilnehmers 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.

Ich wünsche allen eine angenehme und einfache Integration! Vorlage und Anleitung zur Einrichtung auf GitHub.

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster