SNMP 协议

SNMP 基本概念

简单网络管理协议(Simple Network Management Protocol, SNMP)原名叫做简单网关监控协议(Simple Gateway Monitoring Protocol, SGMP)。

SNMP是专门设计用于在 IP 网络管理网络节点(服务器、工作站、路由器、交换机及Hubs等)的一种标准协议,它是一种应用层协议

SNMP中的MIB是一种树状数据库,MIB管理的对象,就是树的端节点,每个节点都有唯一位置和唯一名字。IETF规定管理信息库对象识别符(OID,Object Identifier)唯一指定,其命名规则就是父节点的名字作为子节点名字的前缀。 

Snmputil 工具

Snmputil 工具括 snmputil.exe和 snmputilg.exe 两个小程序,是测试、学习 snmp 的工具,支持 xp、win7、win10 系统。Snmputil 是一个命令行下的软件,使用语法如下:

usage: snmputil [get|getnext|walk] agent community oid [oid ...]

参数说明
agent代理进程的 IP 地址
community团体名
oid被获取的 MIB 对象 ID

实验用的设备的 IP 地址是 172.21.10.173,使用 snmputil 获取实验设备上的有关硬件和操作系统的描述,oid 是 .1.3.6.1.2.1.1.1.0。

snmputil get 172.21.10.173 public .1.3.6.1.2.1.1.1.0


使用 wireshark 抓包,过滤条件直接设为“snmp”,成功抓到包。Snmp 是应用层协议,也就是说一般情况下会源主机发一个包进行请求,目的主机发另一个包进行回复。例如 NO.59 的包就是一个请求信息,它的 data 类型是 get-request,说明它用于请求。“Object”指示了在请求的数据是 MIB 树中的哪一个条目,value 还未知。

NO.60 的包就是一个响应信息,它的 data 类型是 get-response,说明它用于响应请求。“Object”指示了在响应的数据是MIB树中的哪一个条目,value 填充了自己主机上的数据。

验证 SNMP 协议的工作过程

PDU 一共有 GetRequest-PDU、GetNextRequest-PDU、GetResponse-PDU、SetRequest-PDU、Trap-PDU 五种,这些类型在 RFC1157 的第 4 节Protocol Specification 有给出。


IP 组提供了与 IP 协议有关的信息,可以在 RFC1213 的 3.7 看到。

实验使用的设备的 IP 地址是 172.21.10.210,获取其设备的 IP 地址使用如下命令。

snmputil walk 172.21.10.210 public .1.3.6.1.2.1.4.20.1.1


成功抓到如下数据包。

可以明显地看出,SNMP 是基于请求/响应模型进行工作的,客户端发送一个请求,服务器对请求的内容进行回应。


例如 NO.39 数据包是“get-next-request”,说明是请求下一个,请求的对象是“.1.3.6.1.2.1.4.20.1.1”。

NO.40 为服务器的响应,数据包是“get-response”说明是对上一个数据包的回应。回应的对象是“.1.3.6.1.2.1.4.20.1.1”,值是“127.0.0.1”。

注意此时客户端是不知道服务器是有多少数据的,例如我舍友的设备只有 2 个
IP 地址。由于发送方不知道对方有多少 IP 地址,因此就发送了第 3 个请求。可以看到,接收方的最后一个包的 value 是“1”,这个值可以提示发送方已经获取完毕,至此一次查询结束。

SNMP PDU 分析

GetRequest PDU 分析

前文抓到的 NO.59 的包就是一个请求信息,它的 data 类型是 get-request,说明它用于请求。


首先看 version 的编码,version 字段的 REC 文档定义如下:

SNMP 第一个字段是 version(版本号),它是值为 0 的 INTEGER 类型。INTEGER 是 UNIVERSAL(通用标签),因此前两位(标签)为 00。INTEGER是简单类型,因此第三位类型值为 0。类型 INTEGER 的标签号 UNIVERSAL 2,因此后五位为 00010。
综上所述 TLV 中第一个字节 T 的值为二进制 00 0 00010,即 0000 0010,对应十六进制数为 02H。

第二部分L表示值 V 的长度,1 个字节,对应十六进制数为 01H。第三部分V表示值 0,对应十六进制数为 00H。综上,版本号 0 的 BER 编码为 02 01 00。

community 类型是 OCTET STRING 字节串为通用标签 UNIVERSAL,标签值为4。因此前两位(标签)为 00,类型为简单类型,第三位为 0,标签值为 4,后五位为 00100。T 字段为的值为 00000100,对应十六进制数为 04。variable-bindings 的值有6个字节,所以L字段的值为 00000110,十六进制为 06。V 字段的值为 public,也就是用 ASCII 码表示的值为 70 75 62 6C 69 63。

“Object”指示了在请求的数据是MIB树中的哪一个条目,value 还未知。get-request PDU 的格式如下:

定义中 [0] 表明 GetRequest 的标签为“上下文专用标签”,标签值为 0。类型为 SEQUENCE 序列类型,这是一种构造类型。IMPLICIT(隐含标签)指用新标签替换老标签,因此编码时只编码新标签(即上下文专用标签)。
根据BER编码规则,GetRequest 的标签为“上下文专用标签”,前两位(标签)为 10。类型为 SEQUENCE 是构造类型,因此第三位类型值为 1。“[0]”表示标签值为 0,因此后五位为 00000。由此可见,TLV 中第一个字节 T 的值为二进制10 1 00000,即 1010 0000,对应十六进制数为a0。
第二部分 L 表示值 V 的长度,这次抓到的包 GetRequest PDU 的长度为 25 个字节,是十六进制 19。第三部分 V 表示 GetRequest PDU 的值,即协议数据单元的内容。根据 BER 定义,此处递归地再编码为 TLV 结构。

Request-id、error-status 和 error-index都是 INTEGER 类型,因此 T 字段的前 2 位都是 00,INTEGER 类型是简单类型,第 3 位是 0,INTEGER 类型的标签号是 2,后 5 位是00000,因此 T 字段都是 02。这 3 个字段的长度都是 1 个字节,所以 L 字段的值为 1,Request-id、error-status 和error-index 的 V 字段值分别为 1、0、0。所以 Request-id 的编码为 02 01 01:

error-status 的编码和 error-index 编码一样,都是 02 01 00:


关于 variable-bindings 格式,在 RFC1157 中也可以找到其定义,在 4.1.1 中有写到。

variable-bindings 类型为 SEQUENCE 是构造类型,是通用标签
UNIVERSAL,因此前两位(标签)为 00,类型为简单类型,第三位为 0,标签值为 16,后五位为 10000。T 字段为的值为 00110000,对应十六进制数为 30。variable-bindings 的值有 12 个字节,所以 L 字段的值为 00001010,十六进制为 0C。

variable-bindings 下的第一个是 Object Name,类型是 OBJECT IDENTIFIER 为通用标签 UNIVERSAL,标签值为 6。因此前两位(标签)为
00,类型为简单类型,第三位为 0,标签值为 6,后五位为 00110。T字段为的值为 00000110,对应十六进制数为 06。variable-bindings 的值有8个字节,所以 L 字段的值为 00001000,十六进制为 08。V 字段的值为 oid,也就是1.3.6.1.2.1.1.1.0。
Value 的值是 NULL,NULL 类型只有一个值 NULL,其标签是 UNIVERSAL 5。由于这个类型是空类型,无需存储或传送它的值,第二个字节 00 表示值长度为 0。

GetResponse-PDU 分析

GetResponse-PDU 在 RFC 文档中的定义如下。


定义中 [2] 表明 GetResponse 的标签为“上下文专用标签”,标签值为2。类型为 SEQUENCE 序列类型,这是一种构造类型。IMPLICIT(隐含标签)指用新标签替换老标签,因此编码时只编码新标签(即上下文专用标签)。
根据 BER 编码规则,GetResponse 的标签为“上下文专用标签”,前两位(标签)为 10。类型为SEQUENCE是构造类型,因此第三位类型值为 1。“[2]”表示标签值为 2,因此后五位为00010。T 字段的值为二进制 10100010,对应十六进制数为 a2。这次抓到的包的长度为 287 个字节,此处超过了 127 个字节需要扩充,需要一个字节左边第一位置为1标尺扩充,其余 7 位表示需要的字节数,此处 287 个字节需要 1 个字节来表示,所以是 1000 0001,扩充后的那个字节表示 287,也就是 1001 1111,所以 L 字段的值是十六进制 81 9F。

GetResponse 中的 variable-bindings 中的 value 类型是 OCTET STRING 字节串为通用标签 UNIVERSAL,标签值为 4。因此前两位(标签)为 00,类型为简单类型,第三位为 0,标签值为 4,后五位为 00100。T 字段为的值为
00000100,对应十六进制数为 04。
variable-bindings的 value 长度为 259 个字节,此处超过了 127 个字节需要扩充,需要一个字节左边第一位置为 1 标尺扩充,其余 7 位表示需要的字节数,此处 259 个字节需要 1 个字节来表示,所以是 1000 0001,扩充后的那个字节表示 259,也就是 1001 0011,所以L字段的值是十六进制 81 83。

SNMPv3抓包

可参考wireshark专栏——解密加密报文_privkey unknown_牛牛来了的博客-CSDN博客

SNMP wireshark 过滤条件

  • SNMP Trap

过滤关键字:snmp && udp.dstport == 162

  • 根据oid来进行过滤

过滤关键字:snmp.name contains 1.3.6.1.4.1.2021.11.9.0

参考资料

https://www.cnblogs.com/linfangnan/p/14853987.html

《计算机网络管理(第三版)》雷震甲 编著,西安电子科技大学出版社

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值