在前面的文章 我告诉您如何接收授权会话并将其替换为本地主机宏。 在这篇文章中,我将告诉您如何在没有外部脚本和软件的情况下将 Zabbix 与 Asterisk 连接。
让这两个系统“交朋友”的想法很久以前就诞生了,无需安装额外的软件或脚本。 快速谷歌搜索产生了许多可能的解决方案,这一切都归结为将脚本(Pyha、Bash、Python 等)上传到服务器,您会很高兴。 我想实现“开箱即用”的监控 - 无需外部脚本,也无需在具有监控和 PBX 的服务器上安装其他软件。
我总共花了4个工作日来完成这个任务,但结果是值得的。 通过 AMI 接口、低级别检测、触发器以及最重要的是连接 PBX 和所有其他设置,现在大约需要 15 分钟。
Zabbix 4.4已经可用,Asterisk版本100大约有13个。 有些 PBX 带有 FreePBX Web 界面,有些带有裸控制台、一堆技巧并通过拨号方案进行集成。
从 PBX 接收数据
需要解决的第一个也是要点是获取有关对等点和 SIP 注册的数据。 为此,PBX 具有 AGI、AMI、ARI 和 SSH 控制台接口。 由于显而易见的原因,我没有考虑额外的模块。
首先我们需要弄清楚这些agi、ami、ari是什么......
- AGI - 在拨号方案中使用脚本。 主要用于通话管理。
- AMI - 可以提供所有必要的信息,通过端口 5038 工作,类似于 Telnet。 适合我们!
- ARI——现代、时尚、JSON。 有很多可能性,数据格式对于 Zabbix 来说是可以理解的,但对我来说没有主要的事情:你无法控制 sip 注册。 另一个缺点是,对于同行来说,只有在线/离线两种状态,尽管状态有更多,并且在诊断时将它们考虑在内是有用的。
- SSH 可以做所有事情,但有时由于“安全原因”而不允许使用。 考虑的因素可能不同,我就不多说了。
然而,尽管存在种种缺点,ARI 仍能满足 90% 的监控需求。
Zabbix 和 Telnet - 我的失望
我很了解 AMI;有一次,我通过远程办公室、呼叫管理等实现了与部门对话中的丢失跟踪。 使用 Telnet,一切都非常清晰:打开连接、发送命令并读取响应。 我就是这么做的,但结果却令我失望。
Zabbix 的 Telnet 与控制台的 Telnet 不同。 Linux它稍微简单一些,专为标准的登录名/密码验证而设计。如果验证逻辑不同,且未请求登录名/密码对,则会发生错误。在尝试绕过验证要求失败后,我开始研究 Telnet 模块的源代码。
我意识到,除非有传统的登录和密码请求,否则我不会继续前进。 只是为了好玩,我从代码中删除了与授权相关的所有内容并重新组装了所有内容。 作品! 但它不符合要求。 前进…
让我们回到搜索
我再次重新阅读了 ARI 文档,运行了额外的测试 - 这里没有 sip 注册。 有宴会,有谈话,有马裤,但没有登记。 在某些时候我什至想,我们真的需要秃鹫注册吗?
有趣的是,此时用户收到了另一个请求,但出局电话出现了问题。 问题是 sip 注册被冻结,只需重新启动模块即可解决。
asterisk -rx "sip reload"如果能够通过网络访问 AMI,那就太棒了:我想,这将解决所有问题。 我开始朝这个方向挖掘,从字面上看,第一条搜索线通向官方 Asterisk 文档,该文档说我的任务有一个选项 网络功能 在文件中 /etc/asterisk/manager.conf,需要在部分中设置为 YES [一般]
之后,通过表单的常规网络请求 我们得到了所有必要的信息。
使用 FreePBX 界面时,您无法通过 Web 启用此选项;您需要通过控制台更改 manager.conf 文件来启用它。 当通过网络进行配置更改时,FreePBX 不会删除它。
我已经使用各种类型的 Asterisk 集成工作了很长时间,但我从未在任何地方看到过这个功能。 令我惊讶的是,没有人描述这种与 PBX 交互的方法。 查找有关该主题的信息甚至特别有用:几乎没有任何信息,或者它用于完全不同的任务。
WEB AMI - 什么样的野兽?
添加一个选项 网络功能 归档 管理器配置文件 提供通过网络对 ATS 管理的完全访问。 通过常规 AMI 可用的所有命令现在都在网络上,您可以通过套接字侦听来自 PBX 的事件。 操作原理与控制台AMI没有什么不同。 激活此选项后,您可以通过以下地址联系 PBX:
— 具有简单界面的网页,用于测试和手动发送请求。 所有响应都被格式化为可读的 HTML。 不太适合监控。
— 仅文本输出,格式类似于控制台 AMI
- 仅文本输出,采用 XML 格式。 适合我们!

然后我想:“这就是解决办法! 现在一切都准备好了! 容易尿尿的柠檬汁”,但现在高兴还为时过早。 要获取我们需要的信息,使用 GET 请求和必要的操作就足够了 行动,作为响应返回 xml,其中包含所有注册及其状态的列表。 这一切都很棒,但是您需要授权才能记住 cookie 中的会话。 当你在浏览器中测试时,你不会考虑这个过程。
授权流程
首先我们解决地址 ,作为响应,服务器向我们发送一个带有授权会话的 cookie。 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答:
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> 在那里工作你需要 mansession_id="6f5de42c”,即授权 cookie 本身。
您只需检查内容即可找到答案”认证已接受” 接下来,对于对 PBX 服务器的所有调用,我们需要向请求添加授权 cookie。
https://ats:8089/mxml?action=SIPpeers
Host: ats:8089
Connection: close
Cookie: mansession_id="6f5de42c"请阅读如何获取授权 cookie 并在其他请求中使用它:“»
为了在 Zabbix 中创建跟踪元素,我将使用自动检测。
自动检测
要自动检测注册并跟踪对等状态,您需要联系以下地址: или
作为响应,PBX 向我们返回一个 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> 响应中存在大量垃圾,因此在预处理时我们通过模板进行过滤 XPath的: //响应/通用[@host]
然后乐趣就开始了。 要使用检测并动态创建元素,响应必须采用 JSON 格式。 自动检测不支持 XML。
要将 XML 转换为 JSON,我必须使用自动替换,为此我用 JS 编写了一个脚本

有趣的一点:在ATS响应中,所有参数都用单引号括起来,并且在应用模板之后 //响应/通用[@host] 它们被双倍取代。
为了创建元素,我们使用 XML 响应(现在是 JSON)中的变量。

SIP注册处
对于 sip 注册,我们使用三个变量: 用户名, 主持人, 端口。 我对元素的名称很满意 111111@login.mtt.ru:5060,我还没有发现任何需要使用全部五个变量的情况。
接收有关所有注册信息的主要元素, Asterisk - AMI SIPshowregistry。 它每分钟发出一次 GET 请求 ,之后响应 XML 数据将传递到所有依赖元素进行解析。 对于每个注册,我都会创建一个依赖于它的元素。 这很方便,因为我们会在一个请求中收到最新信息,而不是分别收到每个请求的最新信息。 这种实现有一个显着的缺点——处理器的负载。
当测试多达 100 个相关元素时,我没有注意到负载,但对于 1700 个元素,这会给处理器带来明显的 15 秒负载。 如果您有大量依赖元素,请记住这一点。
作为“分散”负载或为元素设置不同轮询频率的选项,您可以将处理逻辑分别移动到每个元素。
我不将收到的信息存储在主元素中。 首先,我认为没有必要这样做,其次,如果响应超过 64K,那么 Zabbix 就会将其切断。
由于我们对依赖元素使用完整的 XML 响应,因此我们需要在预处理中获取该元素的值。 通过 XPath的 这样做是这样的:
string(//response/generic[@event="RegistryEntry"][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@状态)
对于注册状态,我没有使用文本状态,而是使用 JavaScript 将它们转换为数字形式:
switch(value) {
case 'Registered':
return 1;
case 'Unregistered':
return 0;
default:
return -1;
}
SIP 对等体
与 SIP 注册类比,Asterisk 有一个主要元素 - AMI SIPshowregistry,并添加了依赖项。
这将创建两个依赖元素:
- 文本形式的对等状态
- 设备响应时间 - 如果状态正常,则写入设备响应时间,否则“-1”
元素本身的路径稍微简单一些 XPath的:
string(//响应/通用[@objectname="{#SIP_PEER_OBEJECTNAME}"]/@status)
对于第二个元素,我使用 JavaScript 来分隔 响应时间 来自对等状态,因为它们存储在一起:
if(value.substring(0,2) == 'OK'){
return value.match(/(d+)/gm);
}
else {
return -1;
}结论
开箱即用的解决方案可能很复杂并且不能立即清晰。 提高不同系统之间的灵活性和可移植性
祝大家集成愉快、轻松! 模板和设置说明 .
来源: habr.com
