SNMP的工作原理
网络管理包括对硬件、软件和人力的使用、综合与协调。SNMP中的管理程序和代理程序是按照客户服务器的方式安排工作。在网络管理领域, 管理对象和被管理对象需要分别执行两套程序来完成该任务—管理程序和代理程序。在管理者主机上运行管理程序,一般作为客户端,在被管对象上运行代理程序,一般是服务器。在被管对象上运行的服务器进程不断监听来自管理站的SNMP客户程序的请求(术语一般是get或者set命令),如果请求合法有效,那么管理进程则立即返回管理站所需的信息,或者执行某个动作(设置参数等),就这样完成双方的通信。
SNMP的组织结构
SNMP由三部分组成:SNMP内核,管理信息结构SMI和管理信息库MIB。
SNMP内核负责协议结构分析,根据分析结果完成网管动作;SMI是一种通用规则,用来命名对象和定义对象类型,以及把对象和对象的值进行编码的规则;MIB在被管理的实体中创建命名对象,也就是一个实例。SMI规定游戏规则,在规则基础上由MIB实现实例化,而SNMP则是实例化的终极执行BOSS。
管理信息结构SMI
SMI有三个功能:
A 被管对象的命名
B 存储被管对象的数据类型
C 网络上传送的管理数据的编码
1、 被管对象的命名
在SNMP中,SMI规定所有被管对象都要在对象命名树上,处在该树的某个分支或者节点。如下图所示:
根节点不被命名,根下面的子节点是标准制定的三大单位。如果我们需要访问该树internet下的相关对象,那么我们首先可以找对象标识符1.3.6.1,再在下面的管理节点查找mib库,mib库中就定义了所有被SNMP管理的对象,即对象标识符(清单1)1.3.6.1.2.1(iso.org.dod.internet.mgnt.mib-2)。SNMP有一个原则,就是在添加管理对象的时候要尽量减小对原树结构的影响。由此可见,当我们需要增加一个管理对象时,只需要为该对象分配对应的在全树中唯一的标识符即可。
2、 被管对象的数据类型
SNMP使用ASN.1定义数据类型,所谓ASN.1就是抽象语法记法1。比如常规定义一个整型变量,那么不能简单说具有整数值的变量,而必须说明该变量的准确格式和整数的取值范围。
SMI将数据类型分为两大类:简单类型和结构化类型。
简单类型统一由ASN.1定义
类型 |
大小 |
说明 |
INTEGER |
4 bytes |
-2(31) 到 2(31) -1之间 |
Integer32 |
4 bytes |
同上 |
Unsigned32 |
4 bytes |
0 ~ 2(32) – 1之间 |
OCTET STRING |
可变 |
1 ~ 65535 的字符串 |
OBJECT IDENTIFIER |
可变 |
对象标识符,清单1所示 |
IPAddress |
4 bytes |
4个整数组成的IP地址 |
Counter32 |
4 bytes |
0~2(32),最大时返回到0 |
TimeTicks |
4 bytes |
记录时间的计数值,以1/100秒为单位 |
BITS |
— |
比特串 |
Opaque |
可变 |
不解释的串 |
SMI同时又有自己扩展定义的数据类型,结构化类型:sequence 和 sequence of。
数据类型sequence类似于c中的struct 或者记录,是简单数据类型的组合,而sequence of类似于数组,是同样类型的简单数据类型的组合,或同样类型的由sequence类型定义的的组合。
3、 被管对象的编码
SMI使用ASN.1指定的基本编码规则BER进行数据编码。在发送端使用BER将报文转换成对应的比特序列,在接收端,使用BER解码,将比特序还原成原报文。
BER编码的核心是按照 TLV 形式实现。T,即类型type,用以表示描述该对象所使用的数据类型;L,即长度length,表示描述对象的值所需要的字节数;V,即所表述对象的具体取值。ASN.1将所有数据元素表示成由TLV格式组成的序列。如清单2所示:
T字段
1个字节,分为类别(2),格式(1)和编号(5)
T字段的各部分的含义
名称 |
长度(bit) |
说明 |
类别 |
2 |
00:通用类,UNIVERSAL,由ASN.1定义的类型; 01:应用类, APPLICATION,由SMI定义; 10:上下文类,CONTEXT,上下文定义; 11:专用类,PRIVATE,保留为特定厂商定义的类型。 |
格式 |
1 |
0:简单类型 1:结构化类型 |
编号 |
5 |
表示不同的数据类型,取值0~30,支持31种数据类型 |
所以不同的数据类型,会如下定义(部分)
数据类型 |
类别 |
格式 |
编号 |
T字段 |
INTEGER |
00 |
0 |
00010 |
0x02 |
OCTET STRING |
00 |
0 |
00100 |
0x04 |
OBJECT IDENTIFIER |
00 |
0 |
00110 |
0x06 |
NULL |
00 |
0 |
00101 |
0x05 |
Sequence and sequence of |
00 |
1 |
10000 |
0x30 |
IPAddress |
01 |
0 |
00000 |
0x40 |
Counter |
01 |
0 |
00001 |
0x41 |
Gauge |
01 |
0 |
00010 |
0x42 |
TimeTicks |
01 |
0 |
00011 |
0x43 |
Opaque |
01 |
0 |
00100 |
0x44 |
L字段
L字段叫做长度字段(表示单字节或多字节),表示方法如下
单字节:L最高bit为0,高bit后面的7个bits表示V的长度;
多字节:L最高bit为1,高bit后面的7个bits表示V的长度取值所占的字节数,即取出7bits表示的字节后,整合得出V字段的长度。
V字段
值字段,具体取值。举例说明
例1, INTEGER 15 : T字段 0x02, INTEGER的长度为4bytes,则INTEGER 15 的TLV编码为 02 04 00 00 00 0F。
例2, IPAddres 192.1.2.3: IPAddress 的T字段为 0x40,IP地址需要四字节表示,则L字段为0x04,那么该对象的TLV编码是 40 04 C0 01 02 03。
管理信息库MIB
在网络中,管理信息即被管对象的信息的集合,这些信息可供管理程序读写和控制,同时集中在某个虚拟的容器内,这就构成了MIB库。管理程序就是根据这些信息的值对网络内外部进行管理。因此只有在MIB中的对象才能被SNMP管理。例如上面的树状信息结构中,我们若要查询IP节点下收到的IP报文,那么我们的MIB库中的实例就是:1.3.6.1.2.1.4.3。
在将设备或其他管理对象添加到SNMP时,需要先将该对象添加到MIB库中,在没有MIB库的情况下,就要创建MIB库。创建MIB库的方法不在本文介绍之中。
SNMP的报文结构
SNMP只有两种管理功能,即读和写
读操作,用Get报文来检测各被管对象的状况
写操作,用Set报文来改变各被管对象的状况。
SNMP可以实现定期探寻,但是对于Trap来说,只要满足触发条件,即使不在探寻期内,被管对象也可不在管理者发送探寻请求的情况下发送这些信息。例如,在EPON系统中,ONU的注册和销册的时机是不确定的, OLT在得知有ONU注册或者销册时候,通过代理软件,向SNMP管理软件发送注销册Trap信息,用以上位机管理客户端更新在线拓扑。
总之,使用探寻维持对网络资源的实时监控,采用Trap机制,报告特殊事件的发生,这两点促成SNMP成为有效的网络管理软件。
SNMP使用161端口来接收Get、set请求或者发送相应的响应报文,使用162端口接收来自各代理的Trap
SNMP的协议数据单元分类
SNMP定义的协议数据单元类型如下:
PDU编号(T字段) |
PDU名称 |
用途 |
0(A0) |
GetRequest |
管理者从代理处读取一个或者一组变量的值 |
1(A1) |
GetNextRequest |
管理者从代理的MIB树上读取下一个变量的值 |
2(A2) |
Response |
代理向管理者或者管理向管理者发送五种(红)Request报文的响应 |
3(A3) |
SetRequest |
管理者对代理的一个或多个MIB变量的值进行设置 |
4(A4) |
废弃 |
废弃 |
5(A5) |
GetBulkRequest |
管理者从代理处读取大块数据 |
6(A6) |
InformRequest |
管理者从另一远程管理者读取该管理者控制的代理的变量的值 |
7(A7) |
SNMPv2Trap |
代理向管理者报告发生在代理上的异常 |
8(A8) |
Report |
在管理者之间报告某些类型的差错 |
SNMP的协议报文格式
SNMP的协议数据单元被封装在UDP报文内,即采用面向无连接的数据包封装。SNMP的报文格式由四个部分组成,版本、首部、安全参数和SNMP报文的数据部分。
SNMP版本现在是v3,SNMP的首部分为三部分:报文标识(message identification)、最大报文长度和报文标志(message flag)。SNMP数据部分有两个字段用来加密报文,加密方法是通过安全参数来产生报文摘要。SNMP的PDU部分由PDU类型、请求ID、差错控制、差错索引以及变量绑定几个字段组成。PDU类型上面的表格已经列出。
请求ID(request id):由管理进程设置的一个4字节整数。代理返回响应时,也要返回该ID,用以管理进程区分响应报文。
差错状态(error status):请求报文时,置0,响应报文时填入0~18中的一个数字,类似于Linux编程的errono。具体错误编号的取值,自己查文档。
差错索引(error index):请求报文中,置0,响应报文时,如果出现错误,那么代理设置一个整数,该值表示差错的变量在变量列表中的偏移。
变量绑定(variable-binding):一个或多个变量的名和对应的值,请求报文中,变量的值忽略(置NULL)。
1 举例说明 2 3 假设管理者向代理发送GetRequest-PDU,目的是从路由器的代理进程获取通过该路由器的UDP的packets个数。 4 5 根据BER的编码规则,每个元素信息都需要使用TLV编码实现。 6 7 那么,描述GetRequest-PDU的TLV格式是: 8 9 A0 1D --GetRequest-PDU 上下文类型,后面的 值字段长度是29字节; 10 11 02 04 05 AE 56 02 --INTEGER类型,长度为4,request id = 05 ae 56 02; 12 13 02 01 00 --INTEGER类型,长度为1,error status = 00; 14 15 02 01 00 --INTEGER类型,长度为1,error index = 00; 16 17 30 0F --SEQUENCE OF类型,长度15,value是后续所有字节 18 19 30 0D --SEQUENCE类型,长度13,value是后续所有字节 20 21 06 09 01 03 01 01 02 01 07 01 00 -–OBJECT IDENTIFIER类型,长度9,udpInDataprams 22 23 05 00 --NULL类型,长度为0,请求时为空值 24 注意的是,红色字体是变量绑定域,可理解为一个由sequence of定义的内含sequence类型的数组,而sequence定义的一个结构类型,里面包含了OBJECT IDENTIFIER类型和NULL类型变量。 当代理收到该PDU后,通过本地查找获取参数重新填写相关值域,然后通过网络发送出去。
移植情况,如果感兴趣,请看本博客:http://www.cnblogs.com/iTsihang/archive/2012/10/04/2763747.html