SNMP 协议简介。
这里先对 SNMP v2c 及之前版本的协议概念做简单介绍。
概念
SNMP(Simple Network Management Protocol,简单网络管理协议)是在 SGMP(Simple Gateway Monitoring Protocol,简单网关监控协议)的基础上实现的。在 SGMP 的基础上,SNMP 添加了新的管理信息结构和管理信息库。
SNMP 协议用于收集和整理 IP 网络上被管理设备的信息,它可以修改这些信息,从而改变设备的行为。
SNMP 是基于 UDP 协议的。
基本组件
SNMP 由一组网络管理标准组成,包括应用层协议、数据库模式和一组数据对象。
- Manager 负责监视网络上的主机或设备;
- 每个被管理的系统会运行 Agent,通过 SNMP 协议向 Manager 报告信息。
三个关键组件:
- 被管理的设备
- Agent,代理进程,是运行在被管理设备上的软件
- 网络管理系统 Network management station (NMS) 是运行在 Manager 上的软件。
在 NMS 使用 SNMP 协议向 Agent 查询被管理设备上的信息时,Agent 根据 SNMP 的请求将所需的数据公开为变量。
SNMP 协议本身并不定义系统应该提供哪些变量,而是使用可扩展的设计,让应用程序定义自己的层次结构,这些层次结构被表述为管理信息库(Management information base, MIB)。
MIB 描述了设备子系统的管理数据结构,它们使用包含对象标识符(object identifiers, OID)的分层命名空间。每个 OID 标识一个可以通过 SNMP 读取或设置的变量。
MIB 使用管理信息结构 2.0 版(SMIv2、RFC 2578)(ASN.1 的子集)定义的符号。
工作方式
SNMP 端口是 SNMP 通信端点,SNMP 消息传输通过 UDP 进行,通常使用 UDP 端口号161/162。有时也使用传输层安全性(TLS)或数据报传输层安全性(DTLS)协议,端口使用情况如下表所示。
过程 | 协议 | 端口号 |
---|---|---|
代理进程接收请求信息 | UDP | 161 |
NMS 与代理进程之间的通信 | UDP | 161 |
NMS 接收通知信息 | UDP | 162 |
代理进程生成通知信息 | - | 任何可用的端口 |
接收请求信息 | TLS/DTLS | 10161 |
接收通知信息 | TLS/DTLS | 10162 |
版本
SNMP 有三种版本:SNMPv1,SNMPv2c 和 SNMPv3。
- SNMPv1:SNMP 的第一个版本,它提供了一种监控和管理计算机网络的系统方法,它基于团体名认证,安全性较差,且返回报文的错误码也较少。它在 RFC 1155 和 RFC 1157 中定义。
- SNMPv2c:第二个版本 SNMPv2c 引入了 GetBulk 和 Inform 操作,支持更多的标准错误码信息,支持更多的数据类型。它在 RFC 1901,RFC 1905和 RFC 1906中定义。
- SNMPv3:鉴于 SNMPv2c 在安全性方面没有得到改善,IETF 颁布了 SNMPv3 版本,提供了基于 USM(User Security Module)的认证加密和基于 VACM(View-based Access Control Model)的访问控制,是迄今为止最安全的版本。SNMPv3 在 RFC 1905,RFC 1906,RFC 2571,RFC 2572,RFC 2574 和 RFC 2575中定义。
用法
使用 net-snmp 工具管理 Agent。
Get 请求:
GetNext 请求:
Set 请求
GetBulk 请求
可以看到,我们可以进行一些请求(get、getnext、set、bulkget、etc.);设置 snmp 版本、设置 community、设置 OID 等操作,那么这些操作和设置都代表什么含义呢?
MIB 与 OID
MIB 是用来翻译 OID 的工具。在上文中,OID 是一串又一串的由数字、字母和点组成的字符,这对人类并不是很友好,不过我们可以通过 MIB 去阅读 OID 串。
例如,经过完全验证的 OID 一般都由 .iso.org.dod.internet.private
开始,表示成数字串为 .1.3.6.1.4
。我们可以去 https://oidref.com/ 查询通用的 OID 及其含义。
在 private
的后面是 enterprise
,我们可以到 https://www.iana.org/assignments/enterprise-numbers/ 查询所有已经注册的分配。
我对 OID 具体的实现并不感兴趣,而是对怎样使用它更感兴趣。如果有机会的话以后再整理吧。
我们可以使用 snmpwalk
获取指定 Agent 的所有 OID。
snmpwalk 也是 Net-SNMP 工具集合的一部分,它扫描 OID 的方法很简单:
想要通过 SNMP 2c 协议扫描 IP 为 192.168.x.y
,community 为 public 的所有 OID,我们可以输入:
它的格式形如 iso.<num1>.<num2>.<num n>
,其中的 num 可以是任意数字。
PDU
SNMPv1 指定了五种核心协议数据单元(protocol data units, PDUs),SNMPv2 中添加了 GetBulkRequest
和 InformRequest
PDU,SNMPv3 添加了 Report
PDU。
操作类型 | 发送端 | 描述 | 备注 |
---|---|---|---|
Get | NMS | Get 操作可以从 Agent 中提取一个或多个参数值。 | - |
GetNext | NMS | GetNext 操作可以从 Agent 中按照字典序提取下一个参数值。 | - |
Set | NMS | Set 操作可以设置 Agent 的一个或多个参数值。 | - |
Response | Agent | Response 操作可以返回一个或多个参数值。这个操作是由 Agent 发出的,它是 GetRequest、GetNextRequest、SetRequest 和 GetBulkRequest 四种操作的响应操作。Agent 接收到来自 NMS 的 Get/Set 指令后,通过 MIB 完成相应的查询/修改操作,然后利用 Response 操作将信息回应给 NMS。 | - |
Trap | Agent | Trap 信息是 Agent 主动向 NMS 发出的信息,告知管理进程设备端出现的情况。 | - |
GetBulk | NMS | GetBulk 操作实现了 NMS 对被管理设备的信息群查询。 | SNMPv1版本不支持 GetBulk 操作 |
Inform | Agent | InformRequest 是 Agent 向 NMS 主动发送告警。与 Trap 告警不同的是,被管理设备发送 Inform 告警后,需要 NMS 回复 InformResponse 来进行确认。 | SNMPv1版本不支持 Inform 操作 |
Report |
协议格式
一般来说,整个 SNMP 消息三个字段组成:
- SNMP Version:SNMP 的版本;
- SNMP Community:团体字;
- SNMP PDU:上文介绍的 PDU。
PDU 是复杂的,它由多个数据构建而成:
其中:
- Request ID 用来标注特定 SNMP 的请求,它会在 Agent 返回的消息中被设置;
- Error 在发送时的默认值是 0,只有 Agent 处理出错时才会被设置。具体的错误类型见 附录 1;
- Error Index 保存了发生错误时导致出错的对象的指针,默认为 0。
- Varbind 由两个字段组成,第一个字段是 OID,用于指定特定参数,第二个字段是包含特定参数的值。
- 这里的问题是,怎样使用 net-snmp 一次发送多个 Varbind?
协议解析
SNMP 报文格式是经典的 TLV(Type-Length-Value)字段,对于一些简单的数据,它的格式是这样的:
而对于复杂的嵌套数据(比如 Sequence 和 PDUs),则是嵌套保存的:
对 OID 编码需要遵循两个原则:
- OID 的前两个数字
x.y
需要使用公式(40*x)+y
编码为一个值。例如,一般的 OID 前两个数字总是1.3
,那么按照公式就可以编码为 43(0x2B); - OID 剩余的数字编码为一个字节;
- 但是对于大数字有特殊的规则,因为一个字节只能表示不超过 255 的数字,因此规定任何超过 127 的数字都必须用一个字节以上进行编码,并用字节的最高位作为标志,让接收者知道这个数字会用多个数字编码。
- 例如,想要编码数字 2680,就需要分成两个字节 0x94 0x78,在计算的时候用
(0x94-0x80)*0x80+0x78=2680
来计算。
参考协议格式和协议解析这两段,我们可以对任意 SNMP 报文进行解析,下面给出一个书意图:
SNMP v3
(以 Cisco 的设备为例)
新的元素
- SNMP 视图(SNMP View):定义可以在 Agent 上看到的内容,避免未授权访问;
- SNMP 用户(SNMP User):SNMP User 和 SNMP Group 相关联,在关联时定义了用户名、密码、加密和身份验证级别;
- SNMP 群组(SNMP Group):SNMP View 和 SNMP Group 关联,定义了访问类型(如只读/读写)。与设备交互期间启动的安全方法由 SNMP Group 决定。
认证模型
- 身份验证:用于确保只有预期的收件人才能读取 trap。创建消息时,会根据实体的 EngineID 为其赋予一个特殊密钥。该密钥与预期接收者共享并用于接收消息。
- 加密 - 隐私对 SNMP 消息的有效负载进行加密,确保未经授权的用户无法读取。任何被截获的 trap 信息都将充满乱码,无法读取。在 SNMP 信息必须通过互联网传输的应用中,隐私功能尤其有用。
安全级别
SNMP Group 中有三种安全级别:
noAuthnoPriv
- 无需验证和隐私的通信;authNoPriv
- 有身份验证但无隐私的通信。用于身份验证的协议是 MD5 和 SHA;authPriv
- 带有身份验证和隐私保护功能的通信。用于身份验证的协议有 MD5 和 SHA,用于隐私保护的协议有 DES 和 AES。
SNMPv3 的报文解析见附录 5. SNMPv3 报文解析。
参考资料
- SNMP协议 - 西伯尔(cnblog)
- Simple Network Management Protocol - wikipedia
- SNMP: Simple? Network Management Protocol - ranecommercial
- SNMPv3 (Simple Network Management Protocol v3) - study-ccna
- Configuration Template for SNMPv3 - cisco
- SNMP Version 3 - cisco
附录 1. PDU 错误类型
- 0x00 — No error occurred
- 0x01 — Response message too large to transport
- 0x02 — The name of the requested object was not found
- 0x03 — A data type in the request did not match the data type in the SNMP agent
- 0x04 — The SNMP manager attempted to set a read-only parameter
- 0x05 — General Error (some error other than the ones listed above)
附录 2. 原始数据类型
Primitive Data Types | Identifier | Complex Data Types | Identifier |
---|---|---|---|
Integer | 0x02 | Sequence | 0x30 |
Octet String | 0x04 | GetRequest PDU | 0xA0 |
Null | 0x05 | GetResponse PDU | 0xA2 |
Object Identifier | 0x06 | SetRequest PDU | 0xA3 |
附录 3. scapy 实现不完整问题
scapy 提供了一个 snmpwalk
函数,位于 scapy.layers.snmp
:
我们可以轻松调用这个函数:
行为差异
理论上,Net-SNMP 和 scapy 提供的 snmpwalk 应当行为相同,但在用 scapy 的时候会出现这样的问题:
1.0.8802.1.1.2.1.3.3.0 : <ASN1_STRING[b'ohmytest']>
1.0.8802.1.1.2.1.3.4.0 : <ASN1_STRING[b'MikroTik RouterOS 7.1.1 (stable) x86']>
1.0.8802.1.1.2.1.3.5.0 : <ASN1_STRING[b'(']>
... ...
1.3.6.1.2.1.31.1.1.1.3.1 : 0x0 <ASN1_COUNTER32[0]>
1.3.6.1.2.1.31.1.1.1.4.1 : 0x0 <ASN1_COUNTER32[0]>
1.3.6.1.2.1.31.1.1.1.5.1 : 0x0 <ASN1_COUNTER32[0]>
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[2], line 1
----> 1 snmpwalk(dst="192.168.202.152", oid=".1", community="public")
File ~/anaconda3/envs/fuzz/lib/python3.9/site-packages/scapy/layers/snmp.py:293, in snmpwalk(dst, oid, community)
291 print(repr(r))
292 break
--> 293 print("%-40s: %r" % (r[SNMPvarbind].oid.val, r[SNMPvarbind].value))
294 oid = r[SNMPvarbind].oid
296 except KeyboardInterrupt:
File ~/anaconda3/envs/fuzz/lib/python3.9/site-packages/scapy/packet.py:1327, in Packet.__getitem__(self, cls)
1325 else:
1326 name = cast(str, lname)
-> 1327 raise IndexError("Layer [%s] not found" % name)
1328 return ret
IndexError: Layer [SNMPvarbind] not found
在对 OID 1.3.6.1.2.1.31.1.1.1.5.1
进行 next 时报错了,这是 Net-SNMP 中 snmpwalk 不会出现的问题。
复现包
我们可以通过 scapy 构造一个简单的报文复现:
得到的 p
是:
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
p
<IP version=4 ihl=5 tos=0x0 len=75 id=7276 flags=DF frag=0 ttl=63 proto=udp chksum=0x195f src=192.168.202.152 dst=172.31.206.118 |<UDP sport=snmp dport=snmp len=55 chksum=0xdb74 |<Raw load='0-\x02\x01\x01\x04\x06public\\xa2 \x02\x01\x00\x02\x01\x00\x02\x01\x000\x150\x13\x06\x0b+\x06\x01\x02\x01\x1f\x01\x01\x01\x06\x01F\x04\x01\x0c3\\xd3' |>>>
hexdump(p)
0000 45 00 00 4B 4D 05 40 00 3F 11 E8 C5 C0 A8 CA 98 E..KM.@.?.......
0010 AC 1F CE 76 00 A1 00 A1 00 37 88 66 30 2D 02 01 ...v.....7.f0-..
0020 01 04 06 70 75 62 6C 69 63 A2 20 02 01 00 02 01 ...public. .....
0030 00 02 01 00 30 15 30 13 06 0B 2B 06 01 02 01 1F ....0.0...+.....
0040 01 01 01 06 01 46 04 01 0C 42 26 .....F...B&
可以看到,收到的包被解析成了 Raw 格式,无法解析成 SNMP 报文,也难怪上面会报错。我们对比 snmpgetnext:
可以看到它正常返回了下一个 OID 和对应的值:iso.3.6.1.2.1.31.1.1.1.6.1
。
那 scapy 中正常的报文长什么样呢?我们对 .1
NEXT 试试:
得到的结果为:
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
p
<IP version=4 ihl=5 tos=0x0 len=78 id=29917 flags=DF frag=0 ttl=63 proto=udp chksum=0xc0ea src=192.168.202.152 dst=172.31.206.118 |<UDP sport=snmp dport=snmp len=58 chksum=0x9381 |<SNMP version='v2c' 0x1 <ASN1_INTEGER[1]> community=<ASN1_STRING[b'public']> PDU=<SNMPresponse id=0x0 <ASN1_INTEGER[0]> error='no_error' 0x0 <ASN1_INTEGER[0]> error_index=0x0 <ASN1_INTEGER[0]> varbindlist=[<SNMPvarbind oid=<ASN1_OID['.1.0.8802.1.1.2.1.3.3.0']> value=<ASN1_STRING[b'ohmytest']> |>] |> |>>>
hexdump(p)
0000 45 00 00 4E 74 DD 40 00 3F 11 C0 EA C0 A8 CA 98 E..Nt.@.?.......
0010 AC 1F CE 76 00 A1 00 A1 00 3A 93 81 30 30 02 01 ...v.....:..00..
0020 01 04 06 70 75 62 6C 69 63 A2 23 02 01 00 02 01 ...public.#.....
0030 00 02 01 00 30 18 30 16 06 0A 28 C4 62 01 01 02 ....0.0...(.b...
0040 01 03 03 00 04 08 6F 68 6D 79 74 65 73 74 ......ohmytest
这是一个正常的 SNMP 报文,但是奇怪的事情发生了:我们注意到,在这次请求中,我们实际上收到了两个包;而在上一次错误的请求中,我们只收到了一个包!
抓包
这里我们抓包看一下 Net-SNMP 和 scapy 构造包的区别。在这里我发了四个包,分别用 上文实现的 create_getnext_request 和 Net-SNMP 的 snmpgetnext 对 oid=".1"
和 oid=1.3.6.1.2.1.31.1.1.1.5.1
进行发送。最终收到了 10 个包,如下图所示,前六个包是上文实现的函数发送接收的。
可以看到,实际上不论是 Net-SNMP 和 scapy 都正常收到了 SNMP 报文,那为什么在 oid=1.3.6.1.2.1.31.1.1.1.5.1
的时候显示为没有接收呢?又为什么 scapy 发送的报文会多一条 Port unreachable
的回复呢?
戳啦,再回头看一下,它们的行为是一致的,只是 scapy 没有解析出来而已。收到的 Raw 包为:
p[Raw].fields['load']
b'0-\x02\x01\x01\x04\x06public\xa2 \x02\x01\x00\x02\x01\x00\x02\x01\x000\x150\x13\x06\x0b+\x06\x01\x02\x01\x1f\x01\x01\x01\x06\x01F\x04\x01\r\x94\xc9'
0000 00 15 5d 98 cb 68 00 15 5d 1c 3d 19 08 00 45 00
0010 00 4b 6a 55 40 00 3f 11 cb 75 c0 a8 ca 98 ac 1f
0020 ce 76 00 a1 00 a1 00 37 3b f1 30 2d 02 01 01 04
0030 06 70 75 62 6c 69 63 a2 20 02 01 00 02 01 00 02
0040 01 00 30 15 30 13 06 0b 2b 06 01 02 01 1f 01 01
0050 01 06 01 46 04 01 0c b7 72
和正常的报文对比没有什么区别
结论
我们可以用 scapy 发包,但是解析包可能有问题。可能是 scapy SNMP 的实现有问题。它的实现为:
附录 4. Cisco SNMP v3 配置方法
配置访问列表
在下文的命令中,我们创建了一个名称为 snmp-service
的控制列表,它只允许 192.168.100.101 和 192.168.100.102 这两个 IP 访问 snmp 服务。
!
configure terminal
ip access-list standard snmp-service
remark SNMP Poller Server #1
permit 192.168.100.101
remark SNMP Poller Server #2
permit 192.168.100.102
end
!
创建 SNMP 视图
SNMP 视图(Views)包括只读视图和读写视图,这两种视图都可以访问设备上的所有 OIDs。
在下文的命令中,我们创建了一个名称为 snmp-v3-ReadOnly-View
的只读视图和一个名称为 snmp-v3-ReadWrite-View
的读写视图。
!
configure terminal
snmp-server view snmp-v3-ReadOnly-View iso included
snmp-server view snmp-v3-ReadWrite-View iso included
end
!
查询 SNMP 视图
!
show snmp view
!
创建 SNMP 组
在 SNMP v3 中,SNMP 组(Groups)和 SNMP 视图相关联。
下面的命令创建了两个 SNMP 组,分别是只读的 snmp-v3-ReadOnly
,它和上文的 snmp-v3-ReadOnly-View
相关联,并且按照 snmp-service
的权限列表控制权限;同理创建了可读写的 snmp-v3-ReadWrite
组。
其中,access snmp-service
可以省略。
!
configure terminal
snmp-server group snmp-v3-ReadOnly v3 priv read snmp-v3-ReadOnly-View access snmp-service
snmp-server group snmp-v3-ReadWrite v3 priv write snmp-v3-ReadWrite-View access snmp-service
end
!
查询 SNMP 组
!
show snmp community
!
创建只读用户
下文创建了两个只读用户,分别称作 cacti-user
和 read-only-user
。
!
configure terminal
snmp-server user cacti-user snmp-v3-ReadOnly v3 auth sha AaBbCcDdEe1234 priv aes 128 123456789AaBbCc access snmp-service
snmp-server user read-only-user snmp-v3-ReadOnly v3 auth sha 5678MmNnOoPp priv aes 128 MnNnOo7890 access snmp-service
end
!
创建读写用户
!
configure terminal
snmp-server user net-config-user snmp-v3-ReadWrite v3 auth sha 9876QqRrSsTt priv aes 128 TtUuVv3456 access snmp-service
end
!
查询用户
!
show snmp user
!
向 Agent 查询
snmpwalk \
-v3 \
-a SHA `# 验证算法` \
-A 5678MmNnOoPp `# 验证密钥` \
-x AES `# 加密算法` \
-X MnNnOo7890 `# 加密密钥` \
-u read-only-user `# SNMP v3用户名` \
-l authPriv `# 安全级别`\
172.22.148.2 `# target ip` \
1.3.6.1.2.1.1.1 `# OIDS`
附录 5. SNMPv3 报文解析
在 附录 4 的基础上对 SNMPv3 的报文进行解析。先简单发送两个报文:
在进行实际的报文发送时,会先进行一次设置交换再发送报文:
例如,第一段报文中设置了 Reportable
,要求反馈;设置了 msgSecurityModel
为 USM;发送了一个空的 variable-bindings
:
Simple Network Management Protocol
msgVersion: snmpv3 (3)
msgGlobalData
msgID: 589393291
msgMaxSize: 65507
msgFlags: 04
.... .1.. = Reportable: Set
.... ..0. = Encrypted: Not set
.... ...0 = Authenticated: Not set
msgSecurityModel: USM (3)
msgAuthoritativeEngineID: <MISSING>
msgAuthoritativeEngineBoots: 0
msgAuthoritativeEngineTime: 0
msgUserName:
msgAuthenticationParameters: <MISSING>
msgPrivacyParameters: <MISSING>
msgData: plaintext (0)
plaintext
contextEngineID: <MISSING>
contextName:
data: get-request (0)
get-request
request-id: 1798557581
error-status: noError (0)
error-index: 0
variable-bindings: 0 items
然后 Agent 向 Manager 返回一个值:
Simple Network Management Protocol
msgVersion: snmpv3 (3)
msgGlobalData
msgID: 589393291
msgMaxSize: 1500
msgFlags: 00
.... .0.. = Reportable: Not set
.... ..0. = Encrypted: Not set
.... ...0 = Authenticated: Not set
msgSecurityModel: USM (3)
msgAuthoritativeEngineID: 800000090300c4641390eea0
1... .... = Engine ID Conformance: RFC3411 (SNMPv3)
Engine Enterprise ID: ciscoSystems (9)
Engine ID Format: MAC address (3)
Engine ID Data: Cisco type: Agent (0x00)
Engine ID Data: MAC address: Cisco_90:ee:a0 (c4:64:13:90:ee:a0)
msgAuthoritativeEngineBoots: 4
msgAuthoritativeEngineTime: 622717
msgUserName:
msgAuthenticationParameters: <MISSING>
msgPrivacyParameters: <MISSING>
msgData: plaintext (0)
plaintext
contextEngineID: 800000090300c4641390eea0
1... .... = Engine ID Conformance: RFC3411 (SNMPv3)
Engine Enterprise ID: ciscoSystems (9)
Engine ID Format: MAC address (3)
Engine ID Data: Cisco type: Agent (0x00)
Engine ID Data: MAC address: Cisco_90:ee:a0 (c4:64:13:90:ee:a0)
contextName:
data: report (8)
report
request-id: 1798557581
error-status: noError (0)
error-index: 0
variable-bindings: 1 item
1.3.6.1.6.3.15.1.1.4.0: 18
这里返回的 variable-bindings
是一项 OID,似乎是发送过的 SNMPv3 命令的数量?
去翻一下 https://oidref.com/1.3.6.1.6.3.15.1.1.4,介绍是:
The total number of packets received by the SNMP engine which were dropped because they referenced an snmpEngineID that was not known to the SNMP engine.
行吧,再回顾一下第一个包:
msgAuthoritativeEngineID: <MISSING>
所以 net-snmp 发送的第二个包才是有效的,那第一个包的发送目的是啥?难道是判断目标是否支持 snmp v3 版本?倒是可以阅读一下源码。
那就直接看 net-snmp 发送的第二个报文吧:
Simple Network Management Protocol
msgVersion: snmpv3 (3)
msgGlobalData
msgID: 589393290
msgMaxSize: 65507
msgFlags: 07
.... .1.. = Reportable: Set
.... ..1. = Encrypted: Set
.... ...1 = Authenticated: Set
msgSecurityModel: USM (3)
msgAuthoritativeEngineID: 800000090300c4641390eea0
1... .... = Engine ID Conformance: RFC3411 (SNMPv3)
Engine Enterprise ID: ciscoSystems (9)
Engine ID Format: MAC address (3)
Engine ID Data: Cisco type: Agent (0x00)
Engine ID Data: MAC address: Cisco_90:ee:a0 (c4:64:13:90:ee:a0)
msgAuthoritativeEngineBoots: 4
msgAuthoritativeEngineTime: 622717
msgUserName: read-only-user
msgAuthenticationParameters: 2d9f084f27aa8d0640c214e8
msgPrivacyParameters: 58f003461dc6095f
msgData: encryptedPDU (1)
encryptedPDU: a5f60016a940b7cc5ddab8a65033d336f4c9a44e26550de73b0a1676215dc96e743b1270c7161c3885ffd0f05c9600c0374b
这个报文指定了 msgAuthoritativeEngineID
,这里面包含了 Engine 的一些信息,所以上一个报文其实是用来获取 contextEngineID
用于本次的数据发送的。这一次设置了 msgFlags
中的 Reportable
、Encrypted
、Authenticated
。
对于 encryptedPDU
,我们可以在 Wireshark 中设置其解码方式。参考 How to decrypt SNMPv3 packets using Wireshark,在设置→首选项中设置协议→SNMP 中的各项设置即可。其中的 Engine-ID
就是报文中的 msgAuthoritativeEngineID
。
在设置完成后就可以解析 encryptedPDU
了:
msgData: encryptedPDU (1)
encryptedPDU: a5f60016a940b7cc5ddab8a65033d336f4c9a44e26550de73b0a1676215dc96e743b1270c7161c3885ffd0f05c9600c0374b
Decrypted ScopedPDU: 3030040c800000090300c4641390eea00400a11e02046b33cf8c0201000201003010300e060a28c462010101010101000500
contextEngineID: 800000090300c4641390eea0
1... .... = Engine ID Conformance: RFC3411 (SNMPv3)
Engine Enterprise ID: ciscoSystems (9)
Engine ID Format: MAC address (3)
Engine ID Data: Cisco type: Agent (0x00)
Engine ID Data: MAC address: Cisco_90:ee:a0 (c4:64:13:90:ee:a0)
contextName:
data: get-next-request (1)
get-next-request
request-id: 1798557580
error-status: noError (0)
error-index: 0
variable-bindings: 1 item
1.0.8802.1.1.1.1.1.1.0: Value (Null)
[Response In: 4]