![](https://i-blog.csdnimg.cn/blog_migrate/96eef40eab58648c196bea35282d1dca.png)
SNMP 演变#
TCP/IP 网络管理最初使用的是 1987 年 11 月提出的简单网关监控协议(SGMP),在此基础上改进成简单网络管理协议第一版(SNMPvl)。当初提出 SNMP 的目的是作为弥补网络管理协议发展阶段之间空缺的一种临时性措施,由于其简单性和易于实现性,SNMPv1 得到了许多制造商的支持和广泛的应用。
SNMP 虽然被广泛应用,但是 SNMP 没有实质性的安全设施,用户面临的只能是在很不完善的管理工具和遥遥无期的管理标准之间作出选择的两难处境。为了修补 SNMP 的安全缺陷,1992 年 7 月出现了一个新标准——安全 SNMP(S-SNMP),这个协议增强了安全方面的功能。但是 S-SNMP 没有改进 SNMP 在功能和效率方面的其他缺点,有人又提出了另外一个协议 SMP 对 SNMP 进行扩充。在对 S-SNMP 和 SMP 讨论的过程中,Internet 研究人员之间确定必须扩展 SNMP 的功能,并增强其安全性,于是决定以 SMP 为基础开发 SNMPv2。
由于 SNMPv2 没有达到“商业级别”的安全要求(提供数据源标识、报文完整性认证、防止重放、报文机密性、授权和访问控制、远程配置和高层管理能力等),所以 SNMPv3 工作组一直在从事新标准的研制工作,终于在 1999 年 4 月发布了 SNMPv3 新标准。
SNMPv1 协议数据单元#
SNMPv1 支持的操作#
SNMP 仅支持对管理对象值的检索和修改等简单操作,SNMP 实体可以对 MIB-2 中的对象执行下列操作:
操作 | 功能 |
---|---|
Get | 用于检索管理信息库中标量对象的值 |
Set | 用于设置管理信息库中标量对象的值 |
Trap | 代理用陷入报文向管理站报告管理对象的状态变化 |
SNMP 不支持管理站改变管理信息库的结构,即不能增加和删除管理信息库中的管理对象实例,例如不能增加、删除管理信息库中的对象实例。管理站只能逐个访问管理信息库中的叶子节点,不能一次性访问一个子树,例如不能访问整个表的内容。 |
SNMP PDU 格式#
RFC1157 用 ASN.1 给出了 SNMPv1 协议的定义,在 SNMP 管理中管理站和代理之间交换的管理信息构成了 SNMP 报文。报文由 3 部分组成:版本号、团体名、协议数据单元(PDU),报文头中的版本号是指 SNMP 的版本,团体名用于身份认证。
管理站发出的 3 种请求报文GetRequest、GetNextRequest和 SetRequest 采用的格式是一样的。
代理的应答报文格式只有一种 GetResponsePDU。
报文应答序列#
SNMP 报文在管理站和代理之间传送,包含 GetRequest、GetNextRequest 和 SetRequest 的报文由管理站发出,代理以 GetResponse 响应。
Trap 操作相当于代理系统发送事件报告,因此 Trap 报文由代理发给管理站,不需要应答。
SNMP 操作访问对象实例,而且只能访问对象标识树的叶子节点。然而为了减少通信负载,一般希望一次检索多个管理对象,把多个变量的值装入一个 PDU。这时要用到变量绑定表。
报文发送和接收#
当 SNMP 协议实体发送报文时,首先按照 ASN.1 的格式构造 PDU 交给认证进程。接着认证进程检查源和目标之间是否可以通信,如果检查通过则把有关信息(版本号、团体名、PDU)组装成报文。最后经过 BER 编码,交传输实体发送出去。
当一个 SNMP 协议实体接收到报文时,需要执行封装报文的逆过程。首先按照 BER 编码恢复 ASN.1 报文,然后对报文进行语法分析、验证版本号和认证信息等。如果通过分析和验证,则离出协议数据单元,并进行语法分析。在认证检验失败时可以生成一个陷入报文,向发送站报告通信异常情况并丢弃报文。
SNMPv1 操作#
检索简单对象#
检索简单的标量对象可以用 Get 操作,如果变量绑定表中包含多个变量,一次还可以检索多个标量对象的值。接收 GetRequest 的 SNMP 实体以请求标识相同的 GetResponse 响应。特别要注意的是 GetResponse 操作的原子性:如果所有请求的对象值都可以得到则给予应答,反之只要有一个对象的值得不到则返回错误。
例如代理系统的 UDP 组的部分对象实例如下:
使用 GetRequest 请求对象实例的标识符及其相应如下,注意此时请求的是实例,后面要加上 “.0”。
GetRequest(udpInDatagrams.0, udpNoPorts.0, udpInErrors.0, udpOutDatagrams.0)
GetResponse(udpInDatagrams.0 = 100, udpNoPorts.0 = 1, udpInErrors.0 = 2, udpOutDatagrams.0 = 200)
使用 GetNextRequest 请求对象实例的标识符及其相应如下,由于 GetNextRequest 按照词典顺序请求下一个实例,因此这里不需要加上 “.0”。
GetNextRequest(udpInDatagrams, udpNoPorts, udpInErrors, udpOutDatagrams)
GetResponse(udpInDatagrams.0 = 100, udpNoPorts.0 = 1, udpInErrors.0 = 2, udpOutDatagrams.0 = 200)
若代理不支持管理站对 udpNoPorts 的访问,则使用 GetNextRequest 得到的相应如下。由于 udpNoPorts 不允许访问,因此 GetNextRequest 会按照词典顺序检索下一个实例。
GetNextRequest(udpInDatagrams, udpNoPorts, udpInErrors, udpOutDatagrams)
GetResponse(udpInDatagrams.0 = 100, udpInErrors.0 = 2, udpInErrors.0 = 2, udpOutDatagrams.0 = 200)
检索未知对象#
GetNext 命令检索变量名指示的下一个对象实例,并不要求变量名是对象标识符或者是实例标识符,该命令会按照词典顺序访问下一个实例。
例如例如管理站不知道 UDP 组有哪些变量,先试着发出 GetNextRequest 命令。该命令会根据词典顺序访问下一个实例,重复访问就可以获取其他实例。
GetNextRequest(udp)
GetResponse(udpindatagrams.0 = 100)
检索表对象#
由于 GetNext 可以按照词典顺序访问下一个实例,因此可以有效地检索表对象。
例如代理系统的 UDP 组的部分对象实例如下:
如果用 getRques 检索 ifNumber 的值得到响应,就可以知道代理系统有两个接口。
GetRquest(1.3.6.1.2.1.1.0)
GetResponse(2)
如果想知道每个接口的数据速率,则可以用下面的命令检索接口表的第五个元素。最后的 1 是索引项ifIndex的值,得到的响应说明第一个接口的数据速率是 10Mb/s。
GetRquest(1.3.6.1.2.1.2.1.5.1)
GetResponse(100000000)
如果发出的命令是 getNextRequest,则得到的是第二个接口的数据速率。
GetNextRequest(1.3.6.1.2.1.2.2.1.5.1)
GetResponse(56000)
假定管理站不知道该表的行数而想检索整个表,则可以连使用 GetNext 命令。检索到第一行对象后,对该对象使用 GetNextRequest 就可以获取下一行。
GetNextRequest(ipRouteDest, ipRouteMetricl, ipRouteNextHop)
GetResponse(ipRouteDest.9.1.2.3 = 9.1.2.3, ipRouteMetric.1.9.1.2.3 = 3, ipRouteNextHop.9.1.2.3 = 99.0.0.3)