1.3 简单网络管理协议
根据前面两节的内容,我们对网络管理已经有了一个较清晰的了解。网络管理的本质,是从网络设备上获取信息,根据管理者所关心的信息(管理信息)进行辨识、分析、判断,从而适时地做出适当的决策或操作。
比如当通过获取的数据得知,被管理设备的内存占用较多时,可进一步查看其相关的进程数量,分析各进程的具体占用情况。根据这些具体的情况辨识系统是否处于预期状态,如果在预期内,即可视作正常现象;如果不是正常现象,则应采取相关的措施,以保障系统正常、有效地运行。同样,在诸如使用频率高的设备(如UPS)中,如发现设备电压或电流出现异常,应该及时采取处理措施,包括(远程)调节系统的相关参数以保障系统的正常运行,否则可能会带来灾难性的后果。如果被管理设备能在出现异常前提前主动告知(主动告警)管理者(软件),同时管理者能够通过诸如邮件、短信等方式通知运维人员,这将会使工程运营及维护的成本大大降低。不论哪种情况,信息的获取与设置是网络管理中必要的两个通信过程,智能化的主动告警也在常规的理解范围之列。
网络管理协议应该能够处理以上描述的基本情况,以保证有效的通信方式,并有对应的通用标准来处理以下两个问题:
·管理信息的定义和表示方法是什么?
·如何传递被管理者和管理者在通信过程中的管理信息?
SNMP(Simple Network Management Protocol,简单网络管理协议),是恰如其分地满足管理要求的“简单的”网络管理协议。所谓“简单”,可以从SNMP使用的通信协议栈和少数几个协议命令(GET和SET系列,可参考1.3.3节和6.3节)中来理解。在SNMP的术语里,上面所述的管理者和被管理者被解释为NMS(Network Management Station,管理工作站)和代理,下文开始使用这两个名称来描述。
1.3.1 SNMP的发展历史
SNMP发展至今,可谓是历经曲折。从最初的一种临时替代协议发展到如今应用最广的网络管理协议,这与其保持着简单的设计原则是分不开的,也正是因为简单才使其生机勃勃。
和其他协议都会有很多发行版本一样,SNMP也发布了多个版本,使得该协议得到不断地改进和完善。最终广泛应用的版本是SNMP v1、SNMP v2c、SNMP v3。首先,各版本之间主要的差异表现在信息的定义、通信协议的操作和安全机制上。其次,随着各个版本的发行,同时也出现了SNMP应用的两个扩展远程网络监控——RMON(Remote Network Monitoring)和RMON2。
从1.1节中了解到,SNMP v1是SGMP的增强版本,是一个临时的网络管理的解决方案。SNMP v1发布之后很快就成为Internet上网络管理协议的标准,并在此基础上定义了RMON以增强SNMP在数据处理方面的功能,它也引入了概念表、概念行等新概念。RMON实际是SNMP的特殊应用,由特定的MIB和特殊的代理组成。该代理主要提供对子网的监控,具备收集网络数据流量和设备的有关信息,分担了原NMS中的部分管理功能。由于SNMP v1具有限制或关闭轮询的功能,在一定程度上减少了网络负荷。从管理结构的角度讲,RMON代理是NMS的下级代理,按照1.2.2节中的理解,RMON可以看作分布式管理模型的雏形。
在SNMP发展史中,安全性一直是不断被争论和改进的焦点。在SNMP v1中,提供了一种NMS到Agent的简单的认证模式——共同体(Community),NMS向Agent请求时需携带以明文表示的ASCII的字串,代理收到该字符串后需检测是否和本地一致。由于使用明文作为“密码”,明显具有安全隐患。为解决这个问题,从SNMP v1版本升级到SNMP v2的过程中,出现了多个中间版本。
首先出现了“安全的”SNMP版本SNMPsec(sec即security),这个版本中首次提供了与数据相关的安全性——完整性、保密性和数据来源认证等加强安全的特性。不过由于其兼容性方面的原因并没有被广泛应用。为了继续改进该协议的性能和功能,在SNMPsec的基础上进一步出现了SNMP v2p(Party-Based SNMP)。不过由于增加了较多的新内容,简单网络管理协议逐渐变得复杂了,包括计算负担和配置的复杂性,导致SNMP v2p也没能流行。
在1996年IETF公布了SNMP v2c(Community-Based SNMP v2),该版本充分利用了之前版本的成果:SNMP v1的基于共同体的框架和SNMP v2p的其余内容。SNMP v2还定义了管理站之间的通信,所以支持了分布式网络管理。可惜的是,SNMP v2c在安全机制方面又回到了SNMP v1初级认证机制,算是一个折中的v2版本。在SNMP v2c之后,该协议的使用者们在协议的安全性上面做了进一步的改进,出现了SNMP v2u(User-Based SNMP v2),再后来又基于SNMP v2u和SMNP v2p出现了SNMP v2*,亦可称为SNMP v2star。
随着网络安全问题的日益突出,IETF于1998年公布了SNMP v3,其在SNMP v2的基础上扩展了安全性(基于用户的安全模型及视图的访问控制模型)和管理机制。在安全性上,SNMP v3在协议报文中加入了安全性参数,这就允许对报文进行加密和强制性验证,它是一种安全的协议。SNMP v3中使用模块化的思想定义了协议中的各个组成模块,完善了协议的体系结构,最重要的是与SNMP v1和SNMP v2保持兼容。当然随着功能的增强,其实现也越来越复杂,SNMP简单特性的原则被适当地削弱了。
上述的这个SNMP版本的特性在Net-SNMP中并非都支持,也没有必要都支持。Net-SNMP主要支持的有SNMP v1、SNMP v2c、SNMP v3等的特性,这三个版本是当前广泛应用的SNMP版本。更多的详情,读者可以参考其源码目录中的\include\net-snmp\library\snmp.h头文件。该文件定义了SNMP的一些标准内容。
总之,SNMP是目前应用最为广泛的网络管理协议,其仍然在继续完善和发展中。后续大部分对特性的描述都是针对SNMP v3版本来进行的。图1-6简单地描示了SNMP的发展过程(图中SNMP的多个版本2没有体现出先后顺序)。
图1-6 SNMP发展过程图
1.3.2 SNMP的框架组成
本小节按照自上向下的方式讲述SNMP的框架组成,我们可以从物理层和协议层将其结构分解。SNMP的框架图,如图1-7所示。
图1-7 SNMP的框架图
1.物理层
首先从物理层的角度看,使用SNMP对网络进行管理应该包含:至少一台管理工作站或主机(NMS),一个或多个代理设备(Agent),或者还包括代理服务器,代理服务器也可称为委托代理(Proxy Agent)。这些名称或概念,在SNMP v3中都被称为SNMP应用程序实体,文章后续使用“实体”的称呼即源于此。
·Agent:该实体能够响应管理节点的请求也能够主动产生通告消息;它位于管理系统的底层。在实际的网络管理中可以存在一个或者多个这样的实体。
·NMS:该实体能够产生协议命令,能够接受通告消息;它位于管理系统的顶层。在实际的网络管理中至少包含一个这样的SNMP实体。
·Proxy Agent:某些情况下,如不同(子)网络间,不同版本间的通信,还存在一种特殊的代理——委托代理。它用于实现SNMP请求和告警信息的转发,不同协议版本间的转换、翻译等功能。在这些情况下,Agent对NMS是透明的,它位于管理系统的中间层。
从C/S客户端和服务器模式上来看,代理可理解为服务端,管理站可理解为客户端。而当代理发出事件报告时,其相互关系暂时又对调了。
2.协议层
类似的也可以从协议层的角度看,SNMP包含以下几个部分:
·SMI:(Structure of Management Information,管理信息结构)是ASN.1(Abstract Syntax Notation One,抽象语法标记)的一个子集,SMI规定了SNMP中可使用ASN.1中的元素、自定义的数据类型和宏等,由这些元素、数据类型、宏及其相关的语法可定义SNMP中的MIB。ASN.1更多的内容请参考第2章,SMI进一步的讲述内容请参考第3章。
·MIB:管理信息库是Agent中可被管理对象的抽象描述。在1.2.1小节中有所提及,因为它不是SNMP里面特有的协议内容。在SNMP中,MIB是以树形结构组织进行查看的。树中的每个节点称为OID(Object identifier,对象标识),以类似于网址域名的方式组织,以整数表示各个节点,如1.3.6.4。
MIB中的对象直观地解释如下:
·标量:只有单个值的管理对象/OID。假设节点1.3.6.1定义为标量,含义为本书的读者数量。那么每次下发1.3.6.1.0获取该节点信息时,就是单个值,可理解为一维数组。
·表格:具有多个值的管理对象/OID。假设节点1.3.6.2定义为表格型类型,含义为本书在湖南、黑龙江、广东读者的数量。那么每次下发(1.3.6.2.1.0、1.3.6.2.2.0、1.3.6.2.3.0)获取时,就不止一个数据了,可理解为多维数组。
·协议:协议规定了各个实体间通信必须遵循的规定,是客户端和服务端通信的约定。包括协议栈、报文格式、协议细节。每个SNMP协议报文称为PDU(Protocol Data Unit,协议数据单元),更多的内容可参考第5章。
更多有关MIB中的信息以及如何编写SNMP中的MIB请参考第4章。
我们知道SNMP最初是为基于TCP/IP的网络管理而发展起来的。SNMP是属于TCP/IP协议栈的应用层协议,它类似于HTTP、FTP协议。不过,SNMP下层的传输层使用的是不可靠协议UDP(User Datagram Protocol,用户数据包协议),相比TCP来说UDP更便捷、开销更低,这也是SNMP设计的简单原则之一,因为不需要其事先建立可靠的通信链接。这使得当对方网络出现部分故障时SNMP依然能够发出Trap(术语“陷进”,或理解为告警),很明显,TCP通信方式是不支持这种机制的。当然像往常一样,发出去的Trap不能确保对方能够收到。也正是因为如此,通信双方需要自己维护超时时间,并做出判断。
1.3.3 SNMP的功能
SNMP的功能,也就是网络管理的功能,读者应该已基本了解。我们需要掌握Agent设备当前的状态、参数信息及配置情况;当定义的重要事件发生变化时,Agent设备能主动“认错”。对于这些需求的实现,也就是SNMP中具体的操作了,其包括以下内容。
·读取类命令:Get系列命令,即NMS发出请求,获取Agent的管理信息。
·设置类命令:Set命令,即NMS将报文中携带的数据写入Agent中。
·告警功能:Trap系列,Agent主动向NMS发出告警/事件报文的信息。
这些命令及功能是网络管理中最常见的操作命令及功能,在下面更进一步的解释中,在这个层面,MIB中的管理对象一般以OID这一具体的形式称呼和表示。
1.Get操作
顾名思义,Get操作是NMS主动发起的操作。在发出的报文中除了携带Get请求标志外,还包括了待请求OID名称和值对,并以这种名称和值对的绑定形式实现管理对象信息的传递。当然,Get操作中OID对应的值为NULL。否则,就不对应了。Get请求并不能一次获取所有待查询对象的信息,一般一次Get操作只获取一个管理对象。虽然这样设计简单,但是当查询的信息量大时其效率是不高的。实际上,一条报文中可以包括多个MIB对象的变量绑定,以这种方式可以实现一次查询多个管理对象,不过会受限于报文的长度,报文的长度建议不要超过484个字节。
2.Get-Next操作
Get-Next操作与Get操作功能类似,不过有不同之处。从字面意思上去理解是获取下一对象的信息,也就是说查询的信息并不是报文中绑定的OID信息而是该对象的下一个OID的信息(如果下一个OID信息是可读的)。SNMP中Get-Next是按照字典序的深度优先搜索算法实现的,如图1-8右侧图所示。
图1-8 OID树形结构示例
什么是字典序?首先,OID实际上是以点分十进制表示,其类似于IP地址,如,1.3.6.1.2.3.100。OID在MIB浏览器中以直观的树形结构表示,点越多表示树形越深,如图1-8左侧图所示。
字典序即是按照树形生长和数字的升序排序的,其涉及以下两个问题:
1)请求的OID是叶子节点(没有枝,位于末端,其代表具体的管理对象,如节点A~G)。
2)请求的OID不是叶子节点(为该级的父节点,如节点5~8)。
对于问题(1),按照深度优先搜索,需要从该节点向上回溯到上级父节点,在确定的回溯深度下,直到该父节点具有子节点(或没有节点了则结束),然后从该节点获取实例值。按照图中MIB节点的信息,假设节点8为(单索引MIB)表格,且有两行实例(每个节点有两个值,分别为.1、.2),当Get-Next作用于5.8.1.1.2,即F节点的第2个实例时,则实际返回的是5.8.1.2.1节点的实例,即G节点实例第一个实例。
对于问题(2),则简单些,直接返回该父节点下面的子节点,即按字典序排在第一个的子节点的值。按照图中MIB的节点信息,当报文携带的OID为5.6.1.0则返回的是下一个节点的信息5.6.2.0,也就是B。其实际效果同Get报文中携带5.6.2.0的返回结果。实际应用中叶子节点的实例表示方式是(即Get具体的值)该节点OID加上后缀.0。表格对象与其类似,不过稍微有点儿特殊,表示方式是该OID加上“.行实例.0”(行示例数值表示第几行的意思),多维表格则是多个行实例,按点分方式生长,最后补0表示具体实例。如对于二维表格,“.行实例1.行实例2.0”。
在实际应用中,它可能是最常用的功能或命令。对其原理的掌握非常有利于调试,笔者曾经在调试过程中对所打印的信息摸不着头脑!现在,把图1-8中的OID实例按照字典序排序后的结果,如表1-1所示,应该可以看出眉目了。
表1-1 OID字典序的排列
读者是否发现在读取表格中有什么规律?按照Get-Next的操作,如图1-9所示。
图1-9 具有两行实例的MIB表格对象示例
我们发现,获取信息是按照列的方式进行的,即先读取完F列,再读取G列。如果需要按行读取,可以参考Get一次获取多个OID的方法,即在Get-Next中绑定多个OID,这些OID需要按照某行和列的顺序排好。如,获取F、G列的第2行,需要绑定F第一列第一行的OID,和第二列第一行的OID,才能一次获取第二行。
最后,请思考有了Get请求后,为什么还要设计Get-Next请求呢?一般情况下,具有完全责任的NMS,应该清楚Agent中所有的MIB信息。如果NMS只掌握部分MIB,这样根据Get-Next请求的特性,可以发现未知的节点信息。这种假设或许概率上不值得说书布道。但还有一种情况,那就是Get-Next请求的特性也可以轻松地实现对表内容的遍历。初始OID为表头OID,通过Get-Next不断地获取实例,当发现下一OID已越过表头OID,则表明表的遍历已经结束,开始进到其他的节点中。这种实现机制可作为NMS端SNMP程序设计时的参考。
SNMP v2版本中新加入了Get-Bulk操作,实际效果是多个Get-Next操作的集合,以提高网络效率。其具体的实现是,除提供一组OID变量的绑定外,还提供一个最大重复数的参数——max-repeaters,表示可以返回的最大节点数信息,以及一个不重复数non-repeaters,表示OID中不进行后续OID信息的获取,即对前non-repeaters个OID执行Get-Next操作。比如共有N个OID,则前non-repeaters个OID执行Get-Next操作,剩下(N个max-repeaters)的OID最多返回后续max-repeaters的节点信息。
在上述表格中,假设Get-Bulk绑定了F、G两列,且最大重复数为2,则可以实现请求一次返回整个表格的内容,实际上就是把max-repeaters设置为表对象中的行数。所以,Get-Bulk常用来获取表对象中的实例信息。如果只绑定一个OID,最大重复数为1,实际上就是Get-Next的操作了。
3.Set操作
Set操作是对具有可写权限的OID进行参数的设置操作。以实现对设备的参数管理、配置、控制等。同样在Set操作中也可以绑定多个OID信息,与Get操作绑定变量的不同是,Set中需要绑定对应OID的待设置的值。Set操作成功改变对象的值后,会引起什么变化,完全由应用程序自己决定。既可以是改变了代理设备运行的物理参数,又可以是触发代理设备进行日志的备份或清理,还可以是业务需求下的任一动作,等等。
4.Get-Response
Get-Response顾名思义是潜意识中理解它时就停止吧!Get-Response不仅仅是Get请求的响应,而是对NMS的Get和Set两类命令的响应。根据命令的不同和命令中的参数不同,相应的返回变量绑定的信息以及错误状态信息(表明命令执行成功或失败)等。
5.Trap系列
Trap是Agent向NMS主动报告重要事件的机制。对于这种报告,NMS无须对Agent进行响应。Trap字面含义为陷进,也可以理解为事件、告警或通告。Trap可分为两大类:通用类和(企业)自定义类。通用类为协议中的标准Trap,包括coldStart(0)、warmStart(1)、linkDown(2)、linkUp(3)、authenticationFailure(4)、egpNeighborLoss(5)、enterpriseSpecific(6)。括号中的数字为该Trap的标号。SNMP v2引入SNMP v2Trap、notification(SNMP v3支持)、Inform(SNMP v3支持),后者用于管理站之间的相互通告。
Trap信息中的内容表明了“何时、何地、何事”,主要包括以下4个部分:
·什么地点——发送陷进的Agent端标识信息,主要是IP地址和系统类型。
·什么时间——此处应理解为Agent上一次初始化网络到该Trap发送时的累积时间,实际上就是系统启动时间。
·什么事件——以一个标识符标识事件,由NMS和Agent约定,一种事件对应一个标识符。
·其他信息——这里指的是其他节点信息的绑定,用于传送更多的附加信息。如当发送流量过高的Trap时,附带占用流量前3位的IP地址信息。
Trap的应用场景:一般情况下,NMS负责其名下各个站点信息的轮询,不过当管辖的Agent过多而且每个Agent信息量又很大时,NMS一遍轮询下来负担过重,且不能保证其对各Agent的实时查询,甚至是不现实的。不过当引入Trap机制后,管理站能够在降低网络和系统开销的情况下实现设备的管理。它是如何实现的呢?比如设计好一个事件,该事件是向NMS传达信息的“使者”,一旦该“使者”到达NMS,NMS则对产生事件的站点进行相应的查询动作,以这种回调和低开销的方式实现对设备的主动查询、信息入库等,这使得网络管理具有某种自动化。
当然,NMS还能产生其他的动作。如对于“注册”好的某个事件,NMS收到Trap后,可以通过邮件、短信等方式通知设备管理或维护人员实现主动报警。这种实现对重要的设备,如UPS、网关等核心设备具有重要的意义。
到此,读者应该对“简单”的网络管理协议有了较直观的认识了,SNMP的功能,如图1-10所示。
回顾一下Agent和NMS各自的功能:Agent主要负责信息的上传,而NMS除了具有SNMP协议基本的功能外,一般还具有对已发送和接收的信息进行日志记录、通告消息的记录和管理、完善配置的功能,并能提供图形化的配置和管理界面。日志记录一般记录了诸如用户获取和设置的操作历史记录、系统状态变化及更新等内容;通告消息一般记录了网络实体(如网关)主动上报的通告类信息,同时解析事先约定好的通告消息,按通告类型,告警级别分门别类的加以呈现。管理站还具有一定的主动性,根据管理站的配置情况,当某类事件发生时,主动采取相应的措施,如发邮件或短信。
图1-10 SNMP的功能
更为完善一些的管理站还能提供整个网络拓扑结构的图形化呈现、动态监控和告警管理、日志分析及报表功能。这为网络管理员监控网络运行和诊断网络故障提供了更有力更便捷的支持。
正是因为SNMP具有简单管理的特点,使得SNMP广泛应用于IP网络上的网络设备,常见的有路由器、交换机、集线器、服务器等,同时随着嵌入式移动开发的兴起,SNMP也将逐渐应用于移动智能设备。
1.3.4 实现版本
由于SNMP已成为网络管理的标准和主流,与之相关的SNMP开发包或实现版本也出现了百花齐放的局面,它们主要由当今流行的开发语言实现,包括C语言版本、C++版本、Java版本以及基于这些版本的衍生版或库。
1.C语言版本的Net-SNMP
这是本书的主题,是SNMP的开源实现之一,全部支持SNMP版本(v1、v2c、v3)。其前身是卡内基梅隆大学开发的UCD-SNMP,它具有悠久的历史和成熟的社区网站,其完善的开发工具和调试方法有助于用户快速实现需求和原型。由于现实世界中较大一部分网络管理设备都为嵌入式设备,诸如路由器、交换机、监控设备等,C语言版本的Net-SNMP在这些设备上具有天然的优势,无论是从功能、性能、资源利用、可靠性、可移植性等方面都是最优的选择。Net-SNMP功能强大,接口众多,也能方便与(嵌入式)Linux系统集成或其他上层管理软件集成以完成更强大的网络管理功能。同时Net-SNMP也提供了多样的开发模式和接口供开发者选择,支持Perl、Python和Java编程语言(Java的netsnmpj开源项目http://netsnmpj.sourceforge.net/),还有基于Net-SNMP库的Lua脚本语言的luaSNMP实现。
与很多支持SNMP的开发包不同,Net-SNMP除了为用户提供代理开发库之外,其本身就是一款软件,用户只需下载源码、配置、安装后就能实现最基本的SNMP功能。目前,Net-SNMP依然在发展和完善中,包括丰富其内容和部分开发接口的完善,如Perl接口。让我们拭目以待吧,同时也感谢那些为此做出贡献并具有极客精神的前辈们。总之,Net-SNMP是应用最为广泛的SNMP实现,也是Linux发行版中标准的SNMP的实现方案。
2.C++版本SNMP++
SNMP++是一套C++实现的开源库,源于HP公司,用于SNMP网络管理应用程序的开发。它为用户提供了简单易用的开发接口;在系统资源管理上,SNMP++提供了安全机制,可防止内存泄漏。开发者可以使用库中所提供的基础API开发自己的代理,它是一款具有高效、可移植、灵活、可扩展的面向对象的开发库。
3.Java版本
·jSNMP Enterprises,简称jSNMP,是非开源软件(http://www.jsnmp.com/home.html)。它主要由Java SNMP SDK、Java SNMP API、SNMP Java库组成,支持SNMP v1、SNMP v2c、SNMP v3、trap/inform和协议安全机制,并对软件中网络流量消耗、效率进行了优化,官方称其速度与C/C++版本实现相当。其支持灵活的扩展、支持多个网络连接、拥有3层架构。其次,它还具有时间窗的缓存功能可以减少网络流量、易于管理和有效的Trap处理机制,并针对MIB提供了jMIBC的MIB编译器。
·iReasoning公司提供了iReasoning Java SNMP API,它是一款工业界领先的SNMP库,具有高性能、跨平台、线程安全和多线程环境优化等特性,也是首款同时支持DES和128位AES加密算法的SNMP库,并提供了MIB解析器。
·SNMP4J(http://www.snmp4j.org/)是一款基于Java管理者和代理实现的企业级的开源库,是Java 2SE 1.4及后续版本中最先进的开源库。其先进的面向对象的设计思想被SNMP++所采用,Java开发者可考虑使用该开源库。
·AdventNet SNMP API也是一款工业级别的Java开发软件,可开发独立的、基于Web和分布式的跨平台的SNMP管理应用程序及工具。其可用于系统管理、应用程序管理、网络管理。其可视化的IDE和自动代码生成功能能有效地提高开发质量和效率,值得称赞的是它还为开发者提供了良好的参考文档。AdventNet销售多种管理软件,也提供C/C++版本的开发工具套件——AdventNet Agent Toolkit C Edition。该套件不仅支持SNMP还支持CLI、HTTP等其他协议(http://www.manageengine.com/)。
4.Python版
PySNMP是一款跨平台的,用python编写的SNMP实现引擎,开源免费。支持ipv4/ipv6协议及SNMP v1、SNMP v2c、SNMP v3三个版本,可应用于管理站端、代理端、委托代理端。PySNMP提供了非常简单的开发接口,直接使用这些接口就能实现很多应用场景的需求。它也有类似于Net-SNMP中的功能,如MIB转python代码的工具、snmpget、snmpset、snmpwalk等实用工具。不过Python需要依赖第三方Python库。
以上是对各种SNMP实现方案的介绍,希望能为读者提供更好的选择。