4 SNMP trap

概述

接收 SNMP trap 与查询启用 SNMP 的设备正好相反。

在这种情况下,信息从启用 SNMP 的设备发送到 snmptrapd,并由 Zabbix 服务器或 Zabbix proxy 从文件中收集或“捕获”。

通常,trap 会在某些条件发生变化时发送,agent 连接到服务器的 162 端口(与 agent 端用于查询的 161 端口相对)。使用 trap 可以检测在查询间隔期间发生、并可能被查询数据遗漏的一些短暂问题。

Zabbix 中接收 SNMP trap 的设计是与 snmptrapd 以及将 trap 传递给 Zabbix 的一种机制配合工作的 - 该机制可以是 Bash 或 Perl 脚本,也可以是 SNMPTT。

在配置 Zabbix 之后,设置 trap 监控的最简单方法是使用 Bash 脚本方案,因为现代发行版中通常缺少 Perl 和 SNMPTT,并且它们需要更复杂的配置。不过,此方案使用的是配置为 traphandle 的脚本。 为了在生产系统上获得更好的性能,请使用内嵌 Perl 方案(即带有 do perl 选项的脚本,或 SNMPTT)。

接收 trap 的工作流程:

  1. snmptrapd 接收一个 trap。
  2. snmptrapd 将 trap 传递给接收脚本(Bash、Perl)或 SNMPTT。
  3. 接收端解析、格式化并将 trap 写入文件。
  4. Zabbix SNMP trapper 读取并解析 trap 文件。
  5. 对于每个 trap,Zabbix 会查找所有 SNMP trapper 监控项,这些监控项的主机接口与接收到的 trap 地址匹配。 请注意,匹配时只使用主机接口中选定的 IPDNS
  6. 对于找到的每个监控项,将 trap 与 snmptrap[regexp] 中的正则表达式进行比较。 trap 会被设置为所有匹配监控项的值。 如果未找到匹配的监控项,并且存在 snmptrap.fallback 监控项,则将 trap 设置为该监控项的值。
  7. 如果 trap 未被设置为任何监控项的值,Zabbix 默认会记录未匹配的 trap。 (可通过 Administration > General > Other 中的 Log unmatched SNMP traps 进行配置。)
HA故障转移注意事项

在高可用性(HA)节点切换期间,Zabbix 将在最后一个 ISO 8601 时间戳内的最后一条记录之后继续处理;如果未找到相同的记录,则仅使用时间戳来标识最后的位置。

配置 SNMP trap

此监控项类型需要以下前端配置:

步骤 1:为主机创建 SNMP 接口
  1. 数据采集 > 主机 中,创建主机 或编辑现有主机。
  2. 接口 字段中,选择 SNMP 接口类型。
  3. 输入 IP 地址/DNS 名称和端口号。
  4. 从下拉列表中选择 SNMP 版本:(SNMPv1SNMPv2,或 SNMPv3),并根据所选 SNMP 版本添加接口凭据。

每个接收到的 trap 的地址都会与所有 SNMP 接口的 IP 和 DNS 地址进行比较,以找到对应的主机。

步骤 2:配置监控项
  1. 对于该主机,创建监控项 或编辑现有监控项。
  2. Key 字段中,使用以下 SNMP trap key 之一:

    • snmptrap[regexp] - 捕获所有与 regexp 参数中指定的正则表达式匹配的 SNMP trap;如果未指定 regexp,则捕获任意 trap。
      该参数支持用户宏和全局正则表达式。
      返回值:SNMP trap。
      此监控项只能为 SNMP 接口设置。
    • snmptrap.fallback - 捕获所有未被该接口的任何 snmptrap[] 监控项捕获的 SNMP trap。
      返回值:SNMP trap。
      此监控项只能为 SNMP 接口设置。

目前不支持多行正则表达式匹配。

  1. 信息类型 设置为 日志,以便解析时间戳。其他格式(如 数值)也可以接受,但可能需要自定义 trap 处理程序。

设置 SNMP trap 监控

配置 Zabbix 服务器/proxy

要读取 trap,必须配置 Zabbix 服务器或 proxy,以启动 SNMP trapper 进程,并指向由 SNMPTT 或 Bash/Perl trap 接收器写入的 trap 文件。 为此,请编辑配置文件(zabbix\_server.confzabbix\_proxy.conf):

StartSNMPTrapper=1
SNMPTrapperFile=[TRAP FILE]

如果使用了 systemd 参数 PrivateTmp,则此文件很可能无法在 /tmp 中正常工作。

配置 Bash trap 接收器

要求:仅需 snmptrapd。

可以使用一个 Bash trap 接收器 脚本,通过 trapper 文件将 trap 从 snmptrapd 传递到 Zabbix 服务器。要进行配置,请在 snmptrapd 配置文件(snmptrapd.conf)中添加 traphandle 选项,参见示例

可能需要重新启动 snmptrapd,才能使其加载配置更改。

配置 Perl trap 接收器

要求:Perl、使用 --enable-embedded-perl 编译的 Net-SNMP(自 Net-SNMP 5.4 起默认已启用)

可以使用 Perl trap 接收器(请查看 misc/snmptrap/zabbix\_trap\_receiver.pl)将 trap 直接从 snmptrapd 传递到 Zabbix 服务器。 配置方法如下:

  • 将 Perl 脚本添加到 snmptrapd 配置文件(snmptrapd.conf)中,例如:
perl do "[FULL PATH TO PERL RECEIVER SCRIPT]";
  • 配置接收器,例如:
$SNMPTrapperFile = '[TRAP FILE]';
$DateTimeFormat = '[DATE TIME FORMAT]';

可能需要重启 snmptrapd 才能使其读取配置更改。

如果脚本名称没有加引号,snmptrapd 将拒绝启动,并显示类似如下的消息:

Regexp modifiers "/l" and "/a" are mutually exclusive at (eval 2) line 1, at end of line
Regexp modifier "/l" may not appear twice at (eval 2) line 1, at end of line
配置 SNMPTT

首先,应配置 snmptrapd 以使用 SNMPTT。

为了获得最佳性能,SNMPTT 应配置为守护进程,并使用 snmptthandler-embedded 将 trap 传递给它。 请参阅 配置 SNMPTT 的说明。

当 SNMPTT 配置为接收 trap 后,配置 snmptt.ini

  1. 启用 NET-SNMP 包中的 Perl 模块:
net_snmp_perl_enable = 1
  1. 将 trap 记录到 Zabbix 将读取的 trap 文件中:
log_enable = 1
log_file = [TRAP FILE]
  1. 设置日期时间格式:
date_time_format = %Y-%m-%dT%H:%M:%S%z

net-snmp-perl 包已在 RHEL 8.0-8.2 中移除;在 RHEL 8.3 中重新添加。 有关更多信息,请参阅 已知问题

现在将 trap 格式化为 Zabbix 可识别的格式(编辑 snmptt.conf):

  1. 每个 FORMAT 语句都应以 ZBXTRAP [address] 开头,其中 [address] 将与 Zabbix 上 SNMP 接口的 IP 和 DNS 地址进行比较。 例如:
EVENT coldStart .1.3.6.1.6.3.1.1.5.1 "Status Events" Normal
FORMAT ZBXTRAP $aA Device reinitialized (coldStart)
  1. 有关 SNMP trap 格式的更多信息,请参见下文。

不要使用未知 trap - Zabbix 将无法识别它们。 可以通过在 snmptt.conf 中定义一个通用事件来处理未知 trap:

EVENT general .* "General event" Normal
SNMP trap 格式

所有自定义的 Perl trap 接收器和 SNMPTT trap 配置都必须按以下方式格式化 trap:

[timestamp] [the trap, part 1] ZBXTRAP [address] [the trap, part 2]

其中

  • [timestamp] - 采用 %Y-%m-%dT%H:%M:%S%z 格式的时间戳。
  • ZBXTRAP - 表示此行中开始了一个新 trap 的标头。
  • [address] - 用于查找此 trap 所属主机的 IP 地址。

请注意,在处理过程中,ZBXTRAP[address] 会从消息中被截取掉。 如果 trap 的格式不同,Zabbix 可能会以意外的方式解析这些 trap。

示例 trap:

2024-01-11T15:28:47+0200 .1.3.6.1.6.3.1.1.5.3 Normal "Status Events" localhost - ZBXTRAP 192.168.1.1 Link down on interface 2. Admin state: 1. Operational state: 2

这将为 IP=192.168.1.1 的 SNMP 接口生成如下 trap:

2024-01-11T15:28:47+0200 .1.3.6.1.6.3.1.1.5.3 Normal "Status Events"
localhost - Link down on interface 2. Admin state: 1. Operational state: 2

系统要求

建议install MIB files,以确保监控项值以正确的格式显示。 如果没有MIB文件,可能会出现格式化问题的情况,例如以HEX格式而非UTF-8显示数值,或相反的情况。

大文件支持

Zabbix 对 SNMP trapper 文件有较大的 file 支持。Zabbix 可读取的最大 file 大小为 2\^63(即 8 EiB)。请注意,文件系统可能会对 file 大小施加更低的限制。

日志轮转

Zabbix 不提供任何日志轮转系统 - 这应由用户自行处理。日志轮转应先重命名旧文件,之后再删除它,以确保不会丢失任何 trap:

  1. Zabbix 在上次已知位置打开 trap 文件,并进入步骤 3。
  2. Zabbix 通过将 inode 编号与已定义 trap 文件的 inode 编号进行比较,检查当前打开的文件是否已轮转。 如果没有打开的文件,Zabbix 会重置上次位置并返回步骤 1。
  3. Zabbix 读取当前打开文件中的数据,并设置新位置。
  4. 解析新数据。如果这是已轮转的文件,则关闭该文件并返回步骤 2。
  5. 如果没有新数据,Zabbix 休眠 1 秒,然后返回步骤 2。
文件系统

由于 trap 文件的实现方式,Zabbix 需要文件系统支持 inode,以便区分文件(该信息通过 stat() 调用获取)。

使用不同 SNMP 协议版本的设置示例

此示例使用 snmptrapd 和一个 Bash 接收脚本将 trap 转发到 Zabbix 服务器。

设置:

  1. 配置 Zabbix 以启动 SNMP trapper 并设置 trap 文件。将以下内容添加到 zabbix_server.conf
StartSNMPTrapper=1
SNMPTrapperFile=/var/lib/zabbix/snmptraps/snmptraps.log
  1. 将 Bash 脚本下载到 /usr/sbin/zabbix_trap_handler.sh
curl -o /usr/sbin/zabbix_trap_handler.sh https://raw.githubusercontent.com/zabbix/zabbix-docker/7.0/templates/scripts/snmptraps/zabbix_trap_handler.sh

如有必要,请调整脚本中的 ZABBIX_TRAPS_FILE 变量。 若要使用默认值,请先创建父目录:

mkdir -p /var/lib/zabbix/snmptraps
  1. 将以下内容添加到 snmtrapd.conf(请参见可工作的 示例
traphandle default /bin/bash /usr/sbin/zabbix_trap_handler.sh

可能需要重启 snmptrapd 才能使其读取配置更改。

  1. 创建 一个 SNMP 监控项 TEST(请注意初始 配置要求):

    类型: SNMP trap
    信息类型: 日志
    主机接口: SNMP 127.0.0.1
    键值: snmptrap["linkUp"]
    日志时间格式: yyyyMMdd.hhmmss

请注意,这里使用的是 ISO 8601 日期和时间格式。

  1. 接下来,我们将为所选的 SNMP 协议版本配置 snmptrapd,并使用 snmptrap 工具发送测试 trap。
SNMPv1, SNMPv2

SNMPv1 和 SNMPv2 协议依赖于“community string”认证。在下面的示例中,我们将使用“secret”作为 community string。它必须与 SNMP trap 发送端设置为相同的值。

请注意,尽管 SNMPv2 仍然在生产环境中被广泛使用,但它不提供任何加密和真正的发送端认证。数据以明文形式发送,因此这些协议版本只能用于安全环境,例如私有网络,绝不应在任何公共网络或第三方网络上使用。

SNMP 版本 1 现在实际上已经很少使用,因为它不支持 64 位计数器,并且被认为是遗留协议。

要启用接收 SNMPv1 或 SNMPv2 trap,应在 snmptrapd.conf 中添加以下行。 请将 secret 替换为 SNMP trap 发送端上配置的 SNMP community string:

authCommunity log,execute,net secret

接下来,我们可以使用 snmptrap 发送测试 trap。在此示例中,我们将使用常见的“link up” OID:

snmptrap -v 2c -c secret localhost '' linkUp.0
SNMPv3

SNMPv3 解决了 SNMPv1/v2 的安全问题,并提供认证和加密。 您可以使用 MD5 或多种 SHA 认证方法,以及 DES/多种 AES 作为加密算法。

要启用接收 SNMPv3,请向 snmptrapd.conf 添加以下行:

createUser -e 0x8000000001020304 traptest SHA mypassword AES
authuser log,execute traptest

请注意 execute 关键字,它允许为此用户安全模型执行脚本。

snmptrap -v 3 -n "" -a SHA -A mypassword -x AES -X mypassword -l authPriv -u traptest -e 0x8000000001020304 localhost 0 linkUp.0

如果您希望使用 AES192 或 AES256 等强加密方法,请使用 5.8 及以上版本的 net-snmp。 您可能需要使用 configure 选项 --enable-blumenthal-aes 重新编译它。 较旧版本的 net-snmp 不支持 AES192/AES256。 另请参见:强认证或加密

验证

在这两个示例中,您都会在 /var/lib/zabbix/snmptraps/snmptraps.log 中看到类似的行:

2024-01-30T10:04:23+0200 ZBXTRAP 127.0.0.1
UDP: [127.0.0.1]:56585->[127.0.0.1]:162
DISMAN-EVENT-MIB::sysUpTimeInstance = 2538834
SNMPv2-MIB::snmpTrapOID.0 = IF-MIB::linkUp.0

Zabbix 中的监控项值将为:

2024-01-30 10:04:23 2024-01-30 10:04:21 

2024-01-30T10:04:21+0200 UDP: [127.0.0.1]:56585->[127.0.0.1]:162
DISMAN-EVENT-MIB::sysUpTimeInstance = 2538834
SNMPv2-MIB::snmpTrapOID.0 = IF-MIB::linkUp.0

Perl 示例:

2024-01-30T11:42:54+0200 ZBXTRAP 127.0.0.1
PDU INFO:
  receivedfrom                   UDP: [127.0.0.1]:58649->[127.0.0.1]:162
  notificationtype               TRAP
  version                        1
  community                      public
  errorstatus                    0
  transactionid                  1
  requestid                      2101882550
  messageid                      0
  errorindex                     0
VARBINDS:
  DISMAN-EVENT-MIB::sysUpTimeInstance type=67 value=Timeticks: (457671) 1:16:16.71
  SNMPv2-MIB::snmpTrapOID.0      type=6  value=OID: IF-MIB::linkUp.0

另请参阅