I den tidligere artikel har jeg fortalt, hvordan man får en autentifikationssession og indsætter den i en lokal værts-makro. I denne artikel vil jeg beskrive, hvordan man forbinder Zabbix med Asterisk uden eksterne scripts og software.
Ideen om at 'forbinde' disse to systemer er gammel, og det uden at installere ekstra software og scripts. Hurtig googling afslørede mange løsninger, men alt gik ud på at smide scripts (i PHP, bash, Python osv.) på serveren, og så ville lykken være gjort. Jeg ville gerne realisere overvågningen 'out of the box' — uden eksterne scripts og installation af ekstra software på serveren med overvågning og PBX.
Jeg brugte i alt 4 arbejdsdage på dette, men resultatet var det værd. Arbejdning via AMI-grænsefladen, lavniveauopdagelse, triggere, og vigtigst af alt, tilslutningen til PBX og alle andre indstillinger tager nu omkring 15 minutter.
Der er Zabbix 4.4 tilgængelig, cirka 100 Asterisk 13 versioner. Nogle PBX'er har et webinterface som FreePBX, andre har kun en rå konsol med en masse tricks og integration via dialplan.
Hent data fra PBX
Det første og vigtigste spørgsmål, der skal løses, er hentning af oplysninger om peers og SIP-registreringer. Til dette eksisterer der interfaces AGI, AMI, ARI og SSH-konsol i PBX. Yderligere moduler overvejede jeg ikke af åbenlyse grunde.
Først skal vi finde ud af, hvad disse AGI, AMI, ARI... egentlig er.
- AGI — brug af scripts i dialplanen. Primært anvendt til at styre opkald.
- AMI — kan levere alle nødvendige oplysninger, arbejder via port 5038 ligesom Telnet. Det passer os!
- ARI — moderne, trendy, JSON-format. Mange muligheder, dataformatet er forståeligt for Zabbix, men for mig mangler det noget vigtigt: man kan ikke kontrollere SIP-registreringen. En anden ulempe er, at der kun er to tilstande for peers online/offline, selvom der er flere tilstande, og det er nyttigt at tage dem i betragtning under fejlfinding.
- SSH — kan gøre alt, men nogle gange tillades det ikke af 'sikkerhedsmæssige grunde'. Begrundelserne kan være forskellige, og jeg vil ikke dykke ned i dem.
Ikke desto mindre dækker ARI 90% af alle overvågningsbehov trods sine mangler.
Zabbix og Telnet — min skuffelse
Jeg kender AMI godt; på et tidspunkt implementerede jeg sporing af tab i samtaler med opdeling mellem fjernafkoblede kontorer, håndtering af opkald osv. Telnet er også helt klart: åbn forbindelsen, send kommandoer, og læs svaret. Det gjorde jeg, men resultatet skuffede mig.
Telnet i Zabbix er ikke det samme som i Linux-konsollen; det er lidt mere simpelt og skræddersyet til standardgodkendelse som brugernavn/adgangskode. Hvis godkendelseslogikken er anderledes, og der ikke er en anmodning om brugernavn/adgangskode, får man en fejl. Efter forgæves forsøg på at omgå kravene til godkendelse, kiggede jeg på kildekoden til Telnet-modulet.
Jeg indså, at jeg ikke ville komme videre, før der var en traditionel anmodning om logind med adgangskode. Af nysgerrighed fjernede jeg alt, der havde med godkendelse at gøre, og rekonstruerede alt. Det fungerer! Men det opfylder ikke kravene. Lad os komme videre ...
Lad os vende tilbage til søgningen.
Jeg læste dokumentationen om ARI igen, udførte yderligere tests — der er ingen SIP-registreringer her. Der er peer, der er opkald, der er bridge, men der er ingen registreringer. På et tidspunkt overvejede jeg endda, hvor nødvendige SIP-registreringer egentlig er for os.
Som et morsomt sammentræf, i dette øjeblik kom der en ny forespørgsel fra en bruger med problemet med udgående opkald. Problemet var med at SIP-registreringen forblev hængende, og det blev løst med en almindelig genstart af modulet.
asterisk -rx "sip reload"Det ville være fantastisk at kunne anmode om AMI via web; det ville løse alle problemer, tænkte jeg. Jeg begyndte at grave i denne retning, og bogstaveligt talt den første linje i min søgning førte mig til den officielle Asterisk-dokumentation, hvor det nævnes, at der er en mulighed for mine opgaver. webenabled i filen /etc/asterisk/manager.conf, som skal sættes til værdien YES i sektionen [general]
Efter dette, gennem en almindelig webanmodning af typen får vi al den nødvendige information.
Ved brug af FreePBX-grænsefladen kan denne mulighed ikke aktiveres via web; den skal aktiveres gennem konsollen ved at ændre filen manager.conf. FreePBX sletter ikke denne mulighed ved ændringer af konfigurationen via web.
Når jeg har arbejdet med forskellige former for integrationer med Asterisk, har jeg aldrig set, at denne funktion blev nævnt nogen steder. Jeg blev overrasket over, at ingen beskrev denne metode til interaktion med PBX. Selv forsøgte jeg specifikt at finde information om dette emne: praktisk talt intet eksisterer, eller det blev brugt til helt andre formål.
WEB AMI — hvad er det for noget?
Tilføjelse af muligheden webenabled til filen manager.conf åbnede fuld adgang til at administrere PBX'en via web. Alle kommandoer, der er tilgængelige via den normale AMI, er nu tilgængelige i web, og man kan lytte til hændelser fra PBX'en via socket. Driftsprincipperne adskiller sig ikke fra konsol AMI. Efter aktivering af denne funktion kan man tilgå PBX'en på følgende adresser:
— en webside med et simpelt interface, til tests og manuel anmodningssending. Alle svar formateres i et læsevenligt HTML format. Ikke særlig egnet til overvågning.
— kun tekstoutput, formatet er ligesom konsol AMI
— kun tekstoutput, i XML format. Det passer os!

Her tænkte jeg: «Det er løsningen! Nu bliver alt klart! Easy peasy lemon squeezy», men det var for tidligt at glæde sig. For at få de nødvendige oplysninger er det nok at bruge en GET-anmodning med den rigtige handling action, som i svaret returnerer xml med en liste over alle registreringer og deres status. Alt dette er fint, men det kræver godkendelse med sessionshukommelse fra cookie. Når man tester i browseren, tænker man ikke over denne proces.
Godkendelsesprocessen
I starten henvender vi os til adressen , i svaret sender serveren os en cookie med godkendelsessessionen. Sådan ser HTTP-anmodningen ud:
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: da-DK,da;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: 1Svar:
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 For at fungere der kræves mansession_id="6f5de42c", altså selve godkendelsescookien.
Indholdet skal blot kontrolleres for svaret «Authentication accepted». Derefter, ved alle henvendelser til PBX-serveren, skal vi tilføje godkendelsescookien til anmodningen.
https://ats:8089/mxml?action=SIPpeers
Host: ats:8089
Connection: close
Cookie: mansession_id="6f5de42c"Hvordan man får godkendelsescookien og bruger den i andre anmodninger kan læses her: «»
Til oprettelse af sporingsobjekter i Zabbix vil jeg bruge automatisk opdagelse.
Automatisk opdagelse
For automatisk opdagelse af registreringer og overvågning af peer-status, skal man henvende sig til adressen: eller
I svaret returnerer PBX'en os et XML-svar:
...
... Svar indeholder meget støj, så vi filtrerer det i forbehandlingen efter en skabelon XPath: //response/generic[@host]
Herefter begynder det interessante. For at arbejde med opdagelse og dynamisk oprette elementer, skal svaret være i JSON-format. XML understøttes ikke ved automatisk opdagelse.
For at konvertere XML til JSON måtte jeg lege lidt med automatisk udskiftning, til hvilket jeg lavede et script i JS

Et interessant punkt er, at alle parametre i ATC-svaret er indrammet med enkle citationstegn, og efter anvendelse af skabelonen //response/generic[@host] bliver de erstattet med dobbelte.
Til oprettelse af elementer bruger vi variabler fra XML-svaret (nu JSON).

SIP Registry
Til SIP-registreringer bruger vi tre variabler: brugernavn, host, port. Jeg kunne godt lide navnet på elementet 111111@login.mtt.ru:5060, jeg kunne ikke finde situationer, hvor jeg havde brug for at bruge alle fem variabler.
Hovedelementet, der får information om alle registreringer, Asterisk — AMI SIPshowregistry. Én gang i minuttet laver det en GET-anmodning til , hvorefter XML-svarets data sendes til alle afhængige elementer til analyse. Jeg laver et element for hver registrering, der er afhængig af det. Dette er praktisk, da vi får актуalная информация i en enkelt anmodning og ikke for hver enkelt. Denne implementering har en betydelig ulempe — belastning på processoren.
Ved testning af op til 100 afhængige elementer bemærkede jeg ikke belastningen, men ved 1700 elementer forårsagede det en mærkbar 15-sekunders belastning på processoren. Vær opmærksom på dette, hvis du har et stort antal afhængige elementer.
Som et alternativ til at "fordele" belastningen eller indstille forskellige opdateringsfrekvenser for elementet, kan behandlingslogikken tilføres hvert element separat.
Jeg opbevarer ikke den modtagne information i hovedelementet. For det første ser jeg ikke behovet, og for det andet, hvis svaret er større end 64K, så klipper Zabbix det.
Da vi bruger det fulde XML-svar for det afhængige element, skal vi i forbehandlingen hente værdien af dette element. Via XPath gør man det sådan her:
string(//response/generic[@event='RegistryEntry'][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@state)
For registreringsstatusserne brugte jeg ikke tekstlige statusser, men konverterede dem til numerisk værdi ved hjælp af JavaScript:
switch(value) {
case 'Registered':
return 1;
case 'Unregistered':
return 0;
default:
return -1;
}
SIP Peers
Tilsvarende med SIP-registreringer, er der hovedelementet Asterisk — AMI SIPshowregistry, hvortil der tilføjes afhængige.
Her oprettes to afhængige elementer:
- Peer-status i tekstform
- Svarstiden for enheden — hvis status er OK, skrives svaretidspunktet for enheden, ellers '-1'
Selve stien til elementet er allerede lidt lettere XPath:
string(//response/generic[@objectname="{#SIP_PEER_OBJECTNAME}"]/@status)
Til det andet element brugte jeg JavaScript til at adskille svarstiden fra peer-statusen, da de opbevares sammen:
if(value.substring(0,2) == 'OK'){
return value.match(/(d+)/gm);
}
else {
return -1;
}Konklusion
En "out of the box" løsning kan være komplekst og ikke umiddelbart forståeligt. Fleksibiliteten og portabiliteten mellem forskellige systemer øges.
Jeg ønsker alle en behagelig og let integration! Skabelon og instruktion til opsætning på .
Kilde: habr.com
