În articolul anterior Am explicat cum să obținem o sesiune de autentificare și să o integrăm în macro-ul local al gazdei. În acest articol, voi descrie cum să integrezi Zabbix cu Asterisk fără scripturi externe și software.
Ideea de a "integra" aceste două sisteme a apărut demult, fără a instala software suplimentar și scripturi. O căutare rapidă pe Google oferă multe soluții, toate reducându-se la a încărca scripturi (în PHP, Bash, Python etc.) pe server, și va fi fericire. Totuși, voiam să implementez monitorizarea "din cutie" - fără scripturi externe și fără a instala software suplimentar pe serverul de monitorizare și pe PBX.
Am muncit la asta în total patru zile lucrătoare, dar rezultatul a meritat. Lucrul prin interfața AMI, descoperire de nivel inferior, trigger-e și, cel mai important, acum conectarea PBX-ului și toate celelalte setări durează doar 15 minute.
Am Zabbix 4.4, aproximativ 100 de Asterisk-uri versiunea 13. Unele PBX-uri vin cu o interfață web FreePBX, altele cu o consolă simplă, plină de trucuri și integrarea prin dialplan.
Obținem date din PBX
Primul și cel mai important moment care trebuie rezolvat este obținerea datelor despre peers și înregistrările SIP. Pentru aceasta, PBX-urile au interfețele AGI, AMI, ARI și consola SSH. Modulele suplimentare nu au fost luate în considerare din motive evidente.
Mai întâi, trebuie să înțelegem ce reprezintă aceste AGI, AMI, ARI....
- AGI - utilizarea scripturilor în dialplan. Este folosită în principal pentru gestionarea apelurilor.
- AMI - poate oferi toate informațiile necesare, funcționează prin portul 5038, similar cu Telnet. Este ceea ce ne trebuie!
- ARI - modern, la modă, bazat pe JSON. Multe posibilități, format de date într-o formă comprehensibilă pentru Zabbix, dar ceea ce îmi lipsește este controlul asupra înregistrării SIP. Un alt dezavantaj este că pentru peers există doar două stări: online/offline, deși există mai multe stări și ar fi util să le luăm în considerare în diagnosticare.
- SSH - poate face totul, dar uneori nu este permis din „motive de securitate”. Motivele pot fi variate, nu le voi analiza.
Cu toate acestea, în ciuda tuturor dezavantajelor sale, ARI acoperă 90% din toate necesitățile de monitorizare.
Zabbix și Telnet - dezamăgirea mea
AMI îl cunosc bine, la vremea mea am realizat urmărirea pierderilor în conversațiile cu împărțirea pe birouri remote, gestionarea apelurilor etc. Cu Telnet totul este clar: deschizi conexiunea, trimiți comenzi și citești răspunsul. Așa am și procedat, dar rezultatul m-a dezamăgit.
Telnet-ul din Zabbix nu este același cu cel din consola Linux, este puțin mai simplu și adaptat pentru autentificarea standard de tip utilizator/parolă. Dacă logica autentificării este alta, și nu există cererea perechii utilizator/parolă, apare o eroare. După încercări nereușite de a evita cerința autentificării, am început să privesc codul sursă al modulului Telnet.
Am înțeles că până nu va exista cererea tradițională de utilizator și parolă, nu voi avansa. De curiozitate, am eliminat din cod tot ce ținea de autentificare, recompilând tot. Funcționează! Dar nu corespunde cerințelor. Continuăm mai departe…
Ne întoarcem la căutare
Am recitit încă o dată documentația despre ARI, am efectuat teste suplimentare — nu există înregistrări SIP. Există perechi, există apeluri, există poduri, dar înregistrări nu sunt. La un moment dat m-am gândit chiar, cât de necesare sunt, de fapt, înregistrările SIP?
Dintr-o întâmplare amuzantă, în acel moment primesc o nouă solicitare de la un utilizator, cu problema apelurilor externe. Problema era legată de blocarea înregistrării SIP și s-a rezolvat printr-o simplă repornire a modulului.
asterisk -rx "sip reload"Ar fi grozav să accesez AMI prin web: asta ar rezolva toate problemele, m-am gândit. Încep să cercetez în această direcție, și practic prima linie de căutare duce la documentația oficială Asterisk, care spune că pentru sarcinile mele există opțiunea webenabled în fișierul /etc/asterisk/manager.conf, care trebuie setată la valoarea YES, în secțiunea [general]
După asta, printr-o cerere web obișnuită de tipul obținem toate informațiile necesare.
Când folosim interfața FreePBX, nu putem activa această opțiune prin web, trebuie să o activăm prin consolă, modificând fișierul manager.conf. FreePBX nu o șterge la modificările de configurare prin web.
Cât am lucrat cu diferite tipuri de integrare Asterisk, niciodată nu am văzut menționată această funcție. M-a surprins că nimeni nu descrie această metodă de interacțiune cu PBX-ul. Chiar am căutat informații despre acest subiect: practic nimic nu există sau a fost folosit pentru sarcini complet diferite.
WEB AMI — ce este acest lucru?
Adăugarea opțiunii webenabled în fișier manager.conf oferă acces complet la gestionarea PBX-ului prin web. Toate comenzile disponibile prin AMI obișnuit sunt acum disponibile în web, iar evenimentele de la PBX pot fi ascultate prin socket. Principiul de funcționare nu diferă de AMI-ul din consolă. După activarea acestei opțiuni, PBX-ul poate fi accesat la următoarele adrese:
— pagina web cu o interfață simplă, pentru teste și trimiterea manuală de cereri. Toate răspunsurile sunt formatate într-o formă HTML lizibilă. Nu este foarte potrivit pentru monitorizare.
— doar ieșire text, format similar cu AMI-ul din consolă.
— doar ieșire text, în format XML. Ne convine!

Aici m-am gândit: „Iată-l – soluția! Acum va fi totul gata! Ușor ca un dovleac”, dar bucuria a fost prematură. Pentru a obține informațiile necesare, este suficient să folosim o cerere GET cu acțiunea dorită action, care returnează un XML cu lista tuturor înregistrărilor și starea acestora. Este totul grozav, dar este necesară autentificarea cu reținerea sesiunii din cookie. Atunci când testezi în browser, nu te gândești la acest proces.
Procesul de autentificare
La început, ne adresăm la adresa , serverul ne trimite un cookie cu sesiunea de autentificare. Iată cum arată cererea 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: ro-RO,ro;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: 1Răspuns:
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 Pentru a funcționa acolo, este necesar mansession_id="6f5de42c", adică cookie-ul de autentificare.
Conținutul trebuie doar să verifice existența răspunsului „Authentication accepted”. Mai departe, la toate apelurile către serverul PBX, va trebui să adăugăm cookie-ul de autentificare în cerere.
https://ats:8089/mxml?action=SIPpeers
Host: ats:8089
Connection: close
Cookie: mansession_id="6f5de42c"Cum să obții cookie-ul de autentificare și să-l folosești în alte cereri, citește aici: „»
Pentru a crea elemente de urmărire în Zabbix, voi folosi auto-detectarea.
Auto-detectare
Pentru auto-detectarea înregistrărilor și urmărirea stării perechilor, este necesar să ne adresăm la adresa: sau
În răspuns, PBX-ul ne returnează un răspuns XML:
...
... În răspuns există multe date inutile, de aceea le filtrăm în preprocesare conform unui șablon XPath: //response/generic[@host]
Aici începe partea interesantă. Pentru a lucra cu detectarea și a crea dinamic elemente, răspunsul trebuie să fie în format JSON. XML nu este suportat în cazurile de auto-detectare.
Pentru a transforma XML în JSON, a trebuit să mă joc puțin cu înlocuirea automată, pentru care am creat un script în JS

Un aspect interesant este că, în răspunsul de la PSTN, toate parametrii sunt înconjurați de apostroafe, iar după aplicarea șablonului //response/generic[@host] ele sunt înlocuite cu ghilimele duble.
Pentru a crea elemente, utilizăm variabilele din răspunsul XML (acum JSON).

SIP Registry
Pentru înregistrările SIP folosim trei variabile: username, host, port. Mă mulțumea denumirea elementului 111111@login.mtt.ru:5060, nu am găsit situații în care să fie necesare toate cinci variabile.
Elementul principal care obține informații despre toate înregistrările Asterisk — AMI SIPshowregistry. Odată pe minut, face o cerere GET la , după care datele din răspunsul XML sunt transmise tuturor elementelor dependente pentru analiză. Creez elementul pentru fiecare înregistrare ca fiind dependent de el. Este convenabil, deoarece obținem informația actualizată dintr-o singură cerere, nu pentru fiecare în parte. Această implementare are un dezavantaj semnificativ — sarcina pe procesor.
În timpul testării cu până la 100 de elemente dependente, nu am observat o sarcină notabilă, dar la 1700 de elemente, aceasta provoacă o sarcină de 15 secunde pe procesor. Țineți cont de acest lucru, dacă aveți un număr mare de elemente dependente.
Ca opțiune pentru a "distribui" sarcina sau a stabili o frecvență diferită de interogare a elementului, logica de procesare poate fi desfăcută în fiecare element separat.
Informațiile primite nu le stochez în elementul principal. În primul rând, nu văd necesitatea, iar în al doilea rând, dacă răspunsul este mai mare de 64K, Zabbix îl va tăia.
Deoarece pentru elementul dependent folosim răspunsul XML complet, trebuie să obținem valoarea acestui element în preprocesare. Prin XPath asta se face astfel:
string(//response/generic[@event="RegistryEntry"][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@state)
Pentru statusurile înregistrărilor nu am folosit statusuri textuale, ci le-am transformat în formă numerică cu ajutorul JavaScript:
switch(value) {
case 'Registered':
return 1;
case 'Unregistered':
return 0;
default:
return -1;
}
SIP Peers
Analog cu înregistrările SIP, există un element principal Asterisk — AMI SIPshowregistry, la care se adaugă cele dependente.
Aici se creează două elemente dependente:
- Statusul peer-ului în formă text
- Timpul de răspuns al dispozitivului — dacă statusul este OK, se scrie timpul de răspuns al dispozitivului, altfel se trece «-1»
Calea către element este deja puțin mai simplă XPath:
string(//response/generic[@objectname="{#SIP_PEER_OBEJECTNAME}"]/@status)
Pentru al doilea element am folosit JavaScript pentru a separa timpul de răspuns de statusul peer-ului, deoarece sunt stocate împreună:
if(value.substring(0,2) == 'OK'){
return value.match(/(d+)/gm);
}
else {
return -1;
}Concluzie
Soluția „din cutie” poate fi complexă și nu întotdeauna clară. Crește flexibilitatea și portabilitatea între diferite sisteme.
O integrare plăcută și ușoară tuturor! Șablonul și instrucțiunile de configurare pe .
Sursa: habr.com
