一、环境
要求:在设备上添加自己的节点(1.3.6.1.4.1.716),可以实现读取设备的主要信息;
硬件设备:设备A ip:192.168.55.55,设备B ip192.168.55.66,PC(Windows 10) ip:192.168.6.185,由于个人和设备不在同一办公区,故PC通过ssh远程访问。
二、安装配置SNMP
1.安装
安装方式有在线安装和离线安装两种,本次以代理端使用net-snmp-5.8版本,管理端在线安装net-snmp-5.5版本。在线安装比较简单,使用yum指令就可以;离线安装过程make时可能因为缺少部分安装包或者文件报错,按错误提示处理就行。建议在代理端使用离线安装的方式,开始在代理端用yum安装,运行自己的服务就失败,说没有权限打开数据库、共享内存等,后来换成离线安装就好了,遇到相同问题可以尝试这个方法规避。
1.离线安装
离线安装下载网址:net-snmp - Browse /net-snmp at SourceForge.net
安装过程可参考:centos下安装snmp服务_YYilion的博客-CSDN博客_centos安装snmp
2.在线安装
安装过程可参考:CentOS6.5下SNMP安装_我本不是菜鸟的技术博客_51CTO博客
2.配置snmpd.conf
上边的另两个链接包含安装和配置。
管理端安装并启动就可以,snmpd.conf不配置也没事。代理端按照自身需求配置就可以,下面的配置主要用来控制访问的范围,第一行的view的意思就是所有验证符合的都可以访问 .1 包含的节点,就相当于访问根节点。
# Make at least snmpwalk -v 1 localhost -c public system fast again.
# name incl/excl subtree mask(optional)
view all included .1
view systemview included .1.3.6.1.2.1.1
view systemview included .1.3.6.1.2.1.25.1.1
启动服务:
1.使用yum指令安装:service snmpd start (restart)
centos6用service的指令,centos7及以后用将service 换为systemctl ,后续不再赘述。
2.使用离线安装:snmpd -c /usr/local/net-snmp/share/snmp/snmpd.conf (写自己snmpd.conf路径就好)
关闭服务
1.使用yum指令安装:service snmpd stop
2.使用离线安装:ps aux | grep snmp | grep -v grep | awk '{print $2}'
运行后使用 ps aux | grep snmpd | grep -v grep 查看snmpd运行情况,结果如下就说明snmpd服务运行成功。
root 22527 0.0 0.0 206140 12592 ? S Sep15 3:29 snmpd -c /usr/local/net-snmp/share/snmp/snmpd.conf
扫描二维码关注公众号,回复: 14782308 查看本文章
启动好之后可以先在设备自身用snmpwalk测试,没问题的话在用其他设备测试。
snmpv2:snmpwalk -v 2c -c public 192.168.55.55 sysName
snmpv3:snmpwalk -v3 -u name -l authPriv -a MD5 -A @123 -x DES -X pass 192.168.55.55 sysName
(添加用户时的指令:net-snmp-create-v3-user -ro -a @123 -A MD5 -x pass -X DES name ,添加的v3用户权限是只读,把 -ro换成-rw就是读写权限)
获取到的结果类似如下:
SNMPv2-MIB::sysName.0 = STRING: sml.localdomain
要是自身测试就获取不到,原因如下:
1.节点不在查询范围;
2.查询使用的指令对应的用户信息和密码等不匹配
其他设备获取不到的排错方法:
1.ping:确保双方可以互相ping通;
2.检查设备的防火墙状态(至少保证161端口允许通过。如果两设备在不同局域网,还要考虑公司的公网会不会拦截);
三、添加代理
首先,添加代理节点的方法有三种:
1.静态加载,将生成的.c和.h文件加入到相应的位置,重新编译snmp库,优点是不需要修改配置文件,缺点是每次添加都得重新编译;
2.动态加载,将生成的.c和.h文件再编译成.so库,修改snmpd.conf配置文件。优点是每次添加不需要重新编译,缺点是必须支持dlmod命令;
3.子代理扩展,将生成的.c和.h文件编译成可执行程序,运行该程序和snmpd即可,优点是操作简单,缺点是需要运行两个程序才行。
个人觉得动态加载和子代理扩展简单,本次使用的动态加载的方法。
1.编写MIB文件
可参照如何编写MIB文件 - 百度文库编写自己的MIB。
写完之后把MIB文件放到mibs目录下,和snmp自带的MIB文件放一起, snmptranslate -Tp XXX(MIB文件名)-MIB::xxxMIB ,查看节点结构是否符合预期。注意:指令中“xxxMIB”应使用MIB文件中“MODULE-IDENTITY”前的节点名,即自己节点名称。
MIB结构没有问题之后,执行
env MIBS="/xxx/mibs/XXX-MIB.txt" mib2c -c mib2c.int_watch.conf xxxMIB
生成 xxxMIB.c 和 xxxMIB.h 两个文件。与这次项目而言,MIB到此的任务也就结束了,后期基本不会有变动了。snmp服务不完全按照MIB结构运行服务,关键还是在修改的 .c、.h 文件。
2.编写代码
可参考【snmp】net-snmp添加自定义MIB(标量和表格) - 程序员大本营编写 .c 和 .h文件。
编写程序的时候要注意MIB中设置节点的类型,在调试的时候有些节点内容长度超出MIB使用snmptranslate查看到的范围后,运行snmpd服务可能会直接崩了;
此外,调用shell指令获取设备信息有时会需要等待时间,如果等的时间长的话,运行snmpd服务可能也会挂掉(之前使用popen运行ipmitool获取设备信息的时候就失败了)。
3.编译动态库
编译指令:
gcc -I `net-snmp-config --cflags` -fPIC -shared -g -O0 -o XXXMIB.so xxMIB.c `net-snmp-config --libs` -lnetsnmp -lrt (按照自己代码需要添加库及路径)
编译出动态库之后,使用 ldd -r XXXMIB.so ,查看动态库中函数的链接
undefined symbol: netsnmp_register_scalar (./XXXMIB.so)
undefined symbol: snmp_set_var_typed_value (./XXXMIB.so)
undefined symbol: netsnmp_create_handler_registration (./XXXMIB.so)
undefined symbol: snmp_log (./XXXMIB.so)
查看到有这些函数找不到函数符号表,等运行的时候不会有问题,服务中可以找到这些函数符号表。
四、运行服务
将生成的动态库和MIB放到同一目录下之后,在snmpd.conf配置文件最后添加:
dlmod XXXMIB /usr/local/net-snmp/share/snmp/mibs/XXXMIB .so(我的动态库放在这个地址,可按实际修改路径)
每次修改动态库之后都要重启一下snmpd。运行失败的话可能是因为没安装dlmod或者打开共享内存等操作没有权限,可以看看init函数里有没有错。
五、测试
项目中使用的是snmpv3版本,查看节点方式
snmpwalk -v3 -u name -l authPriv -a MD5 -A @123 -x DES -X pass 192.168.55.55 1.3.6.1.4.1.716 (snmpv2参见 “二、2.配置snmpd.conf”)
运行结果如下
SNMPv2-SMI::enterprises.716.1.1.0 = STRING: "Power Status : Power Unit Group: 1,Status: Not Present. Power Unit Group: 2,Status: Not Present."
SNMPv2-SMI::enterprises.716.1.2.0 = STRING: "Volt : 12.294000"
SNMPv2-SMI::enterprises.716.1.4.0 = STRING: "CPU Temperature : 36"
SNMPv2-SMI::enterprises.716.1.5.0 = STRING: "Network Interface : eth0 eth1 lo "
SNMPv2-SMI::enterprises.716.1.6.0 = STRING: "Local IP : 192.168.55.55"
可能遇到的问题如下:
1..运行snmpwalk后节点内容打印的是十六进制数,可以在运行snmpwalk时添加 -Oa 参数;
2.运行后节点中有一堆“.”,可能是因为在代码调用snmp_set_var_typed_value函数的时候标注字符串大小使用的是sizeof计算的,snmp默认把剩下空间进行了填充,换成strlen就没事了;
3.运行snmpwalk之后snmpd挂了:代码运行到上次snmpwalk最后一个节点的时候有问题,服务崩了,可以考虑 “三、添加代理” 中提到的问题;
至此,snmp添加代理节点就完成了。