1.1、什么是Snmp

SNMP是英文"Simple Network Management Protocol"的缩写,中文意思是"简单网络管理协议"。SNMP是一种简单网络管理协议,它属于TCP/IP五层协议中的应用层协议,用于网络管理的协议。SNMP主要用于网络设备的管理。由于SNMP协议简单可靠 ,受到了众多厂商的欢迎,成为了目前最为广泛的网管协议。

SNMP协议主要由两大部分构成:SNMP管理站和SNMP代理。SNMP管理站是一个中心节点,负责收集维护各个SNMP元素的信息,并对这些信息进行处理,最后反馈给网络管理员;而SNMP代理是运行在各个被管理的网络节点之上,负责统计该节点的各项信息,并且负责与SNMP管理站交互,接收并执行管理站的命令,上传各种本地的网络信息。

SNMP的基本思想:为不同种类的设备、不同厂家生产的设备、不同型号的设备,定义为一个统一的接口和协议,使得管理员可以是使用统一的外观面对这些需要管理的网络设备进行管理。通过网络,管理员可以管理位于不同物理空间的设备,从而大大提高网络管理的效率,简化网络管理员的工作。

SNMP采用UDP协议在管理端和agent之间传输信息。 SNMP采用UDP 161端口接收和发送请求,162端口接收trap,执行SNMP的设备缺省都必须采用这些端口。SNMP消息全部通过UDP端口161接收,只有Trap信息采用UDP端口162

参考链接:https://www.cnblogs.com/xdp-gacl/p/3978825.html

1.2、SNMP功能(PDU)

  1. Walk:通过get、get-next、get-bulk等一系列命令来获取设备属性
  2. Trap:设备主动发送消息给NMS

参考链接:https://bbs.csdn.net/topics/391964541?page=1

1.3、工具

1、MIB browser 和 MIB Builder
MIB browser 和 MIB Builder 是用来管理设备和编译生成MIB文件的两个PC端工具。
下载路径:
https://www.mg-soft.si/download.html?product=mibbrowser

2、SNMPUtilG
按照下面这个链接介绍,我们可以实现PC电脑SNMP配置验证
参考链接:https://blog.csdn.net/helloworld2200/article/details/77853352
配置完成后,使用用 SNMPUtilG 工具就可以出现下面的结果
IPC摄像机中的SNMP v3协议
我们通过SnmpUtils工具可以获取PC电脑的OID以及各自的value,说明配置成功。

3、net-snmp
net-snmp包括snmp服务端程序和windows下面的snmp客户端工具集,我们需要将服务端程序移植到嵌入式设备端。并且可以通过客户端工具集进行测试验证
源码交叉编译参考
https://www.cnblogs.com/oloroso/p/4814467.html

上面的参考链接有很详细地说明,下面的内容是我在海思Hi3519V100平台上移植net-snmp 5.8版本的操作
首先是configure配置

#release版本
./configure --host=arm-linux --target=arm-linux --build=i686-linux  --with-cc=arm-hisiv500-linux-gcc --with-ar=arm-hisiv500-linux-ar --prefix=/home/kapoo/tools/net-snmp-5.8/out --exec-prefix=/home/kapoo/tools/net-snmp-5.8/out/bin --disable-embedded-perl --with-default-snmp-version="3"
#debug版本:
./configure --host=arm-linux --target=arm-linux --build=i686-linux  --with-cc=arm-hisiv500-linux-gcc --with-ar=arm-hisiv500-linux-ar --prefix=/home/kapoo/tools/net-snmp-5.8/out --exec-prefix=/home/kapoo/tools/net-snmp-5.8/out/bin --disable-embedded-perl --with-default-snmp-version="3" --enable-debugging

然后是Makefile文件的修改

1)、CPP = gcc -E
改为: CPP = arm-hisiv500-linux-gcc -E
2)、perlmodules 部分注释掉
all:sedscript EXAMPLE.conf standardall net-snmp-config-x net-snmp-create-v3-user perlmodules
这句注释掉 perlmodules
注: make的到最后还是会编译一些app,我的编译环境没有安装perl,所以会报错,但是我不需要这些app,所以没关系,这个时候已经生成了snmpd和libnetsnmp.so了

源码下载路径
http://www.net-snmp.org/download.html

调测和移植

2.1、设备验证

首先,我们针对某款已经集成了snmp服务端的设备进行测试验证。
我们在pc端安装net-snmp工具集之后,执行如下命令:

snmpwalk -v3 -u admin -l auth -a MD5 -A admin1100 10.5.91.87 if

该命令中参数说明如下:

-v3: 表示使用v3版本的snmp协议
-u: 表示鉴权用户名为"admin"
-l: 表示鉴权认证级别,这里只用了鉴权级别,所以后面加"auth"参数
-a: 表示鉴权类型,这里使用的是MD5加密
-A: 鉴权密码
ip: 设备ip地址"10.5.91.87"
if: 这里是设备的OID,指网口信息,可以用描述字符串表示,也可以用序号

执行后出现如下打印

IF-MIB::ifIndex.1 = INTEGER: 1
IF-MIB::ifIndex.2 = INTEGER: 2
IF-MIB::ifDescr.1 = STRING: lo
IF-MIB::ifDescr.2 = STRING: eth0
IF-MIB::ifType.1 = INTEGER: softwareLoopback(24)
IF-MIB::ifType.2 = INTEGER: ethernetCsmacd(6)
IF-MIB::ifMtu.1 = INTEGER: 65536
IF-MIB::ifMtu.2 = INTEGER: 1500
IF-MIB::ifSpeed.1 = Gauge32: 10000000
IF-MIB::ifSpeed.2 = Gauge32: 10000000
IF-MIB::ifPhysAddress.1 = STRING:
IF-MIB::ifPhysAddress.2 = STRING: e4:f1:4c:4:56:23
IF-MIB::ifAdminStatus.1 = INTEGER: up(1)
IF-MIB::ifAdminStatus.2 = INTEGER: up(1)
IF-MIB::ifOperStatus.1 = INTEGER: up(1)
IF-MIB::ifOperStatus.2 = INTEGER: up(1)
IF-MIB::ifLastChange.1 = Timeticks: (0) 0:00:00.00
IF-MIB::ifLastChange.2 = Timeticks: (0) 0:00:00.00
IF-MIB::ifInOctets.1 = Counter32: 810864
IF-MIB::ifInOctets.2 = Counter32: 305385278
IF-MIB::ifInUcastPkts.1 = Counter32: 10687
IF-MIB::ifInUcastPkts.2 = Counter32: 2084255
IF-MIB::ifInNUcastPkts.1 = Counter32: 0
IF-MIB::ifInNUcastPkts.2 = Counter32: 0
IF-MIB::ifInDiscards.1 = Counter32: 0
IF-MIB::ifInDiscards.2 = Counter32: 49908
IF-MIB::ifInErrors.1 = Counter32: 0
IF-MIB::ifInErrors.2 = Counter32: 0
IF-MIB::ifInUnknownProtos.1 = Counter32: 0
IF-MIB::ifInUnknownProtos.2 = Counter32: 0
IF-MIB::ifOutOctets.1 = Counter32: 810864
IF-MIB::ifOutOctets.2 = Counter32: 2789760656
IF-MIB::ifOutUcastPkts.1 = Counter32: 10687
IF-MIB::ifOutUcastPkts.2 = Counter32: 12408247
IF-MIB::ifOutNUcastPkts.1 = Counter32: 0
IF-MIB::ifOutNUcastPkts.2 = Counter32: 0
IF-MIB::ifOutDiscards.1 = Counter32: 0
IF-MIB::ifOutDiscards.2 = Counter32: 0
IF-MIB::ifOutErrors.1 = Counter32: 0
IF-MIB::ifOutErrors.2 = Counter32: 0
IF-MIB::ifOutQLen.1 = Gauge32: 0
IF-MIB::ifOutQLen.2 = Gauge32: 0
IF-MIB::ifSpecific.1 = OID: SNMPv2-SMI::zeroDotZero
IF-MIB::ifSpecific.2 = OID: SNMPv2-SMI::zeroDotZero

从这里的打印,我们可以看出设备能正常返回OID,以及下一个OID的值。说明验证通过。

2.2、移植验证

snmpd的交叉编译和移植过程,在前面的内容中有相关的参考。根据参考中的内容,可以很容易地完成移植工作。然后我们需要使用前文介绍的相关工具集进行功能验证。在验证的过程中,我遇到了以下几个问题,分别记录如下:
问题一:MIB Browser上USM配置不对
因为我们验证的是SNMP v3协议,使用MIB Brower访问设备时,需要设置鉴权用户名和密码。该项需要设置USM用户信息,如下:
IPC摄像机中的SNMP v3协议
这里几个需要注意的地方:
1)、Context name需要和服务端保持一致,我的环境下,这里必须为空
2)、Do not Localize… 这一项不能勾选

问题二:在MIB Browers上面使用加密模式之后出现encrytedPDU privKey Unknow
出现这个问题之后,我进行了抓包测试,捕获的报文内容如下:
IPC摄像机中的SNMP v3协议
但是密码是没问题的,因为在使用的时候snmpwalk命令执行是能正常返回结果的。
关于报文信息,可参考链接:
https://blog.csdn.net/zqixiao_09/article/details/77129684

发现报文使用snmpwalk和设备端返回的报文是一样的,都没有带鉴权和认证参数,初步怀疑是这里的问题。
后来发现我用 snmpwalk的时候命令用错了,应该用:
snmpwalk -v3 -u admin -l authPriv -a MD5 -A admin1100 -x DES -X admin1100 10.5.91.87 if
但是我用成:
snmpwalk -v3 -u admin -l auth -a MD5 -A admin1100 -x DES -X admin1100 10.5.91.87 if
改成 authPriv 之后也是同样的情况,返回如下:
IPC摄像机中的SNMP v3协议
于是我把net-snmp的debug打印打开(在编译之前的configure命令进行修改,增加 --enable-debugging,去掉–enable-mini-agent参数),想从日志上着手,看是否能定位到问题的原因所在。然后我发下了下面这段打印:
IPC摄像机中的SNMP v3协议
从这段打印来看,产生了 USM not in time window 错误,查了对应的代码,函数为 usm_check_and_update_timeliness。如下
IPC摄像机中的SNMP v3协议
可见时间窗口需要在150s以内,即服务端和客户端的时间差需要在该窗口内,而我的设备是没进行时间对时的。所以会出现该问题。设置设备时间之后,问题解决。

问题三:–enable-mini-agent,导致认证之后无法执行下去
由于第一次交叉编译configure的时候,使用了该选项,导致认证通过之后无法获取OID的值。去掉该选项重新编译之后问题解决。

问题四:/var路径下出现了 net-snmp 文件夹和run里面出现了utmp
程序运行之后,/var路径下出现了net-snmp 文件夹和run里面出现了utmp。而在运行时出现下面打印:

read_config:path: config path used for hosts/:/home/kapoo/tools/net-snmp-5.8/out/etc/snmp:/home/kapoo/tools/net-snmp-5.8/out/share/snmp:/home/kapoo/tools/net-snmp-5.8/out/bin/lib/snmp:/root/.snmp (persistent path:/var/net-snmp)

由此可见utmp是自动创建的,需要用来解析config文件,我采用的处理方式是在linux启动之后把他们删掉。

问题五:OID属性写权限的问题
我用MIB Browser 设置节点属性时,都出现不可写的返回,如下图:
IPC摄像机中的SNMP v3协议
于是,我跟踪了代码,找到了如下代码:
IPC摄像机中的SNMP v3协议
应该是这里出了问题,加了打印代码,发现没进到这里来
后来发现原来是在配置文件snmpd.conf里面设置的属性是不可写的,我把该字段从配置文件里面删除,就可写了。

总结起来如果要使OID可写,需要配置如下两点:
1、 账户要设置成rwuser。
2、 不能把该OID的值放在配置文件中进行设置。

补充概念

3.1、OID

常用OID
参考链接 https://blog.csdn.net/a9254778/article/details/51200502
这些OID的返回值可以在snmp.conf中配置,如:
IPC摄像机中的SNMP v3协议
我们在配置文件中可以这么配置:syscontact [email protected]

3.2、安全模式

Transport Security Model (TSM)
User-based Security Model (USM)

代码树

下面是我追踪过的部分代码树

  • _sess_process_packet
    • _sess_process_packet_handle_pdu
      • handle_snmp_packet
    • snmp_parse
      • snmpv3_parse
        • asn_parse_int
    • usm_secmod_process_in_msg
    • usm_process_in_msg
    • usm_parse_security_parameters
    • asn_parse_string
 

来源网络,如有侵犯到您的权益请联系zengyin969@gmail.com进行下架处理