上篇数据中心网络设备管理(一)中介绍了如何使用snmp get 获取设备信息,网管要在尽量短的时间内获取到设备告警,使用snmp get来获取设备告警,需要网管设置轮询来实现,如果设置轮询时间为5min,告警就有可能在设备发生故障5分钟后才被网管发现,如果设置轮询时间颗粒度过短,就增加了网络流量,增大设备处理数据压力,而snmp trap为网管被动接收设备的告警信息,设备出现告警,会自动给网管发送告警消息。

以华为设备为例进行配置snmp trap
snmp-agent trap type base-trap //配置trap类型为base-trapsnmp-agent //使能snmp-agentsnmp-agent sys-info version all //兼容V1、V2C、V3版本snmp-agent trap source Loopback0 //设置Trap源地址为Loopback0snmp-agent mib-view included proxyping mib-2snmp-agent target-host trap address udp-domain 网管ip params securityname 团体字 v2c
接下来进行抓包,分析SNMP trap报文内容,通过tcpdump进行抓包,查看包的形式
sudo tcpdump -i 网卡 udp port 162 -w snmp.pcap
使用wireshark及trapbuffer的一条数据进行分析
time device_name %%01CONFIGURATION/6/hwCfgChgNotify(t):CID=0x80cb000c-OID=1.3.6.1.4.1.2011.5.25.191.3.1;Configuration changed. (CurrentCfgChgSeqID=676, CfgChgSeqIDReveralCount=0, CfgChgTableMaxItem=10000, CfgBaselineTime=2020-01-16 时间)
wireshark 分析抓包

variable-bindings为6项,对应分别对应
| 参数名称 | 参数含义 |
|---|---|
| TIMETICKS | 可以理解为时间戳 |
| OID | MIB中的告警号标识 |
| CurrentCfgChgSeqID | 系统配置变更标识。 |
| CfgChgSeqIDReveralCount | 配置变更流水号反转次数。 |
| CfgChgTableMaxItem | 系统可以保存的配置变更点数目。 |
| CfgBaselineTime | 系统配置的基线时间。 |
明白trap消息格式后,就可以通过程序作为snmp trap的服务器,并根据snmp trap格式还原告警。我这里使用python进行实现
from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcherfrom pysnmp.carrier.asynsock.dgram import udpfrom pyasn1.codec.ber import decoderfrom pysnmp.proto import apidef cb_fun(self,transport_dispatcher, transport_domain, transport_address, whole_msg): # 处理Trap信息的函数,返回处理后的字典信息while whole_msg:msg_ver = int(api.decodeMessageVersion(whole_msg))print(msg_ver)#打印下报文def snmp_trap_receiver(self,if_ip,port): # 创建snmp_trap_receiver服务器,监听发送来的SNMP Trap信息transport_dispatcher = AsynsockDispatcher() # 创建实例transport_dispatcher.registerRecvCbFun(self.cb_fun) # 调用处理Trap信息的函数# UDP/IPv4transport_dispatcher.registerTransport(udp.domainName, udp.UdpSocketTransport().openServerMode((if_ip,port)) # 绑定到本地地址与UDP/162号端口)transport_dispatcher.jobStarted(1) # 开始工作print("[SNMP Trap Receiver Started]")try:transport_dispatcher.runDispatcher() # 运行except Exception as e:transport_dispatcher.closeDispatcher()print(e)if __name__ == '__main__':snmp_trap_receiver(0.0.0.0,162)
在设备上造一条告警出来后,打印snmp trap报文,为下一步分析做准备
Message:version=version-2ccommunity=data=PDUs:snmpV2-trap=SNMPv2TrapPDU:request-id=37471error-status=noErrorerror-index=0variable-bindings=VarBindList:VarBind:name=1.3.6.1.2.1.1.3.0=_BindValue:value=ObjectSyntax:application-wide=ApplicationSyntax:timeticks-value=45719668VarBind:name=1.3.6.1.6.3.1.1.4.1.0=_BindValue:value=ObjectSyntax:simple=SimpleSyntax:objectID-value=1.3.6.1.4.1.2011.5.25.191.3.1VarBind:name=1.3.6.1.4.1.2011.5.25.191.1.1.0=_BindValue:value=ObjectSyntax:simple=SimpleSyntax:integer-value=676VarBind:name=1.3.6.1.4.1.2011.5.25.191.1.2.0=_BindValue:value=ObjectSyntax:simple=SimpleSyntax:integer-value=0VarBind:name=1.3.6.1.4.1.2011.5.25.191.1.3.0=_BindValue:value=ObjectSyntax:simple=SimpleSyntax:integer-value=10000VarBind:name=1.3.6.1.4.1.2011.5.25.191.1.4.0=_BindValue:value=ObjectSyntax:simple=SimpleSyntax:string-value=time
使用分割将这6项的值全部提取出来
def analysis(msg_ver):if msg_ver in api.protoModules: # 如果版本兼容p_mod = api.protoModules[msg_ver]else: # 如果版本不兼容,就打印错误print('Unsupported SNMP version %s' % msg_ver)returnreq_msg, whole_msg = decoder.decode(whole_msg, asn1Spec=p_mod.Message(), # 对信息进行解码)print(req_msg)req_pdu = p_mod.apiMessage.getPDU(req_msg)if req_pdu.isSameTypeWith(p_mod.TrapPDU()):if msg_ver == api.protoVersion1: # SNMPv1的特殊处理方法,可以提取更加详细的信息var_binds = p_mod.apiTrapPDU.getVarBindList(req_pdu)else: # SNMPv2c的处理方法var_binds = p_mod.apiPDU.getVarBindList(req_pdu)result_dict = {} # 每一个Trap信息,都会整理返回一个字典for x in var_binds: # 打印详细Trap信息result = {}for x, y in x.items():# print(x, y.prettyPrint()) # 最原始信息打印y = {ObjectName: 9} 1.3.6.1.2.1.1.3.0# 处理信息到字典if x == "name":id = y.prettyPrint() # 把name写入字典的键else:bind_v = [x.strip() for x in y.prettyPrint().split("\n")]for v in bind_v:print(v)if "=" in v:result[v.split('=')[0]] = v.split('=')[1]result_dict[id] = resultprint(result_dict)
根据提取出来的值和snmp trap对应OID告警模板进行拼接,就可以还原设备告警了,本条告警模板如下:
Configuration changed. (CurrentCfgChgSeqID=[CurrentCfgChgSeqID], CfgChgSeqIDReveralCount=[CfgChgSeqIDReveralCount], CfgChgTableMaxItem=[CfgChgTableMaxItem], CfgBaselineTime=[CfgBaselineTime])设备当前运行的配置发生改变。
其他告警模板可以在华为官网对应设备文档中找到,这样当设备发生故障或因某些原因导致系统进入不正常的工作状态时,就网管可以被动收到设备产生事件和告警信息。
参考:
https://bbs.csdn.net/topics/391964541?page=1
https://support.huawei.com/carrierindex/zh/anony/index.html
https://stackoverflow.com/questions/33752602/listen-traps-with-pysnmp




