写点什么

SNMP 协议在设备监控中的使用

  • 2025-06-27
    北京
  • 本文字数:4535 字

    阅读完需:约 15 分钟

随着网络技术的飞速发展,网络管理变得日益重要。网络管理员需要一种高效、可靠的方式来监控网络设备、收集状态信息并对其进行配置。简单网络管理协议(SNMP)正是为此目的而设计的。本文将对 SNMP 进行详细介绍,并提供使用 SNMP 进行网络管理的基本指南。

1.简介

SNMP(Simple Network Management Protocol)是一个基于互联网协议族(IP)的网络管理标准,用于在 IP 网络中的管理节点与被管理节点之间进行通信,以实现对网络设备的远程监控和管理。SNMP 具有简单、高效、易于实现和扩展性强等优点,因此在网络管理领域得到了广泛应用。

2.SNMP 的组成和版本

2.1.SNMP 协议的组成

SNMP 协议架构主要包括以下几个部分:



1.管理信息库(MIB) :MIB 是一个信息数据库,用于存储被管理设备的信息,如设备类型、接口状态、路由表等。MIB 是 SNMP 的核心,管理站通过 SNMP 协议获取 MIB 中的信息,以实现对网络设备的监控和管理。


2.管理站(NMS) :NMS 是网络管理系统中的核心组件,负责收集、处理和存储来自被管理设备的信息。NMS 通常运行在网络管理中心的服务器上,通过网络管理软件实现对网络设备的远程监控和管理。


3.代理(Agent) :Agent 是被管理设备上的软件模块,负责接收 NMS 的查询请求,并返回 MIB 中的相关信息。同时,Agent 还可以将设备的状态变化通知给 NMS。

2.2.SNMP 协议版本

目前 SNMP 协议有三个版本,分别是:V1、V2 和 V3


•V1:SNMP 协议的最初版本


•V2:在 V1 的基础上增加 community(团体名),这里的团体名可以理解为密码


•V3:增加认证和对密文的传输的支持,这种方式安全等级最高

3.SNMP 报文


SNMP 报文包含三个部分


•版本号:表明当前使用的版本,管理站和代理之间的版本号必须相同才能通信


•团体名:团体(community)是基本的安全机制,用于实现 SNMP 网络管理员访问 SNMP 管理代理时的身份验证,类似于密码,默认值为 public。团体名(Community name)是管理代理的口令,管理员被允许访问数据对象的前提就是网络管理员知道网络代理的口令。


•PDU:snmp 的数据结构

3.1.PDU 详细报文

3.2.PDU 类型

•get-request:从代理(本质上是设备)获取一个或多个参数值


•get-next-request:从代理紧接着取出下一个参数值


•set-request:设置代理一个或多个参数值


•get-response:对上述三种请求的响应


•trap:设备主动上报的数据

3.3.差错状态

•noError:无错误


•tooBig:代理无法将回答装入到一个 SNMP 报文中


•noSuchName:操作指明了一个不存在的变量


•badValue:一个 set 操作指明了一个无效值或无效语法


•readOnly:管理进程试图修改一个只读变量


•genErr:某些其他差错

3.4.trap 类型

•coldStart:代理进行了初始化


•warmStart:代理进行了重新初始化


•linkDown:一个接口从工作状态变为故障状态


•linkUp:一个接口从故障状态变为工作状态


•authenticationFailure:从 SNMP 管理进程接收到具有一个无效共同体的报文


•egpNeighborLoss:一个 EGP 相邻路由器变为故障状态


•enterpriseSpecific:代理自定义事件,需要用后面的“特定代码”来指明

4.MIB 详解

4.1.MIB 树结构

MIB 以树状结构进行存储,树的叶子节点表示管理对象,它可以通过从根节点开始的一条惟一路径来识别,这也就是 OID(Object Identifier)。



OID 是由一些系列非负整数组成,用于唯一标识管理对象在 MIB 树中的位置。由 SMI 来保证 OID 不会冲突。


MIB 文件一旦发布,OID 就和被定义的对象绑定,不能修改。MIB 节点不能被删除,只能将它的状态置为“obsolete”,表明该节点已经被废除。


在上图的树形结构中,mgmt 对象可以标识为:{ iso(1) org(3) dod(6) internet(1) mgmt(2) },简单标记为:1.3.6.1.2,这种标识就叫做 OID。


NMS 通过 OID 引用 Agent 中的对象。

4.2.MIB 分类

MIB 可以分为公有 MIB 和私有 MIB 两种。


•公有 MIB:一般由 RFC 定义,主要用来对各种公有协议进行结构化设计和接口标准化处理。大多数的设备制造商都需要按照 RFC 的定义来提供 SNMP 接口。


•私有 MIB:是公有 MIB 的必要补充,当公司自行开发私有协议或者特有功能时,可以利用私有 MIB 来完善 SNMP 接口的管理功能,同时对第三方网管软件管理存在私有协议或特有功能的设备提供支持。


网络设备的很多数据都以 MIB 的树结构存储,根据数据对应的 OID,我们便可以获取到网络设备的各种统计数据和配置数据,实现网络设备的监控。

5.SNMP 实践

5.1.snmp 命令

5.1.1.snmpwalk

用于获取 SNMP 设备上的数据,它遍历设备的 SNMP 树,并返回特定对象标识符(OID)的值,通常用于查询设备的信息和状态。使用 snmpwalk 可以获取有关设备的详细信息,例如接口、系统信息、传感器状态等。以下是 snmpwalk 的一般用法:


snmpwalk -v SNMP_VERSION -c COMMUNITY_STRING TARGET_HOST OIDSNMP_VERSION:SNMP 版本,通常是 "1"(SNMPv1)或 "2c"(SNMPv2c)。COMMUNITY_STRING:SNMP 社区字符串,用于身份验证。TARGET_HOST:目标设备的主机名或 IP 地址。OID:要查询的对象标识符。
复制代码

5.1.2.snmptrap

snmptrap 用于生成和发送 SNMP 陷阱(trap)到 SNMP 管理器,这些陷阱通常表示设备上发生的重要事件或告警。snmptrap 常用于监控设备状态变化和异常事件。以下是 snmptrap 的一般用法:


snmptrap -v SNMP_VERSION -c COMMUNITY_STRING TARGET_HOST TRAP_OID [OID_VALUE] [OPTIONS]SNMP_VERSION:SNMP 版本,通常是 "1"(SNMPv1)或 "2c"(SNMPv2c)。COMMUNITY_STRING:SNMP 社区字符串,用于身份验证。TARGET_HOST:目标 SNMP 管理器的主机名或 IP 地址。TRAP_OID:陷阱的对象标识符,表示事件类型。OID_VALUE:可选,与陷阱相关的 OID 值。OPTIONS:可选,包括发送陷阱的其他选项,如 -p(指定陷阱端口)等。
复制代码

5.1.3.snmpget

用于获取单个 SNMP 对象的值。你可以指定要查询的 OID,它将返回相应的值。


snmpget -v SNMP_VERSION -c COMMUNITY_STRING TARGET_HOST OID
复制代码


snmpget -v SNMP_VERSION -c COMMUNITY_STRING TARGET_HOST OID

5.1.4.snmpset

用于设置 SNMP 对象的值。它允许你修改设备上的特定 OID 的值。


snmpset -v SNMP_VERSION -c COMMUNITY_STRING TARGET_HOST OID TYPE VALUE
复制代码

5.1.5.snmpbulkwalk

类似于 snmpwalk,但它使用了 SNMP Bulk Protocol(SNMPv2c)来提高效率,特别对于大型数据集。


snmpbulkwalk -v SNMP_VERSION -c COMMUNITY_STRING TARGET_HOST OID
复制代码

5.1.6.snmpinform

用于向 SNMP 管理器发送 SNMP INFORM 消息,这是一种更可靠的通知机制,它需要管理器进行确认。


snmpinform -v SNMP_VERSION -c COMMUNITY_STRING TARGET_HOST OID
复制代码


在网络设备信息采集中,我们通常会通过 snmpget 和 snmpwalk 命令获取网络设备的各种运行和配置数据。

5.2.代码实现

基于以上知识,我们考虑通过代码的方式执行 snmp 命令,获取设备的基本信息,实现设备的自动化监控。本文所有案例都基于 Java 语言,其余语言类似。


5.2.1.引入依赖


如下所示,我们引入 snmp 的依赖:


<dependency>   <groupId>org.snmp4j</groupId>   <artifactId>snmp4j</artifactId>   <version>2.7.0</version></dependency>
复制代码


5.2.1.代码实现


public class SnmpUtils {        /**     * 根据oid获取数据     * @param ip     * @param community     * @param oid     * @return     */    @SneakyThrows    public static void snmpGet(String ip, String community, String oid) {
Snmp snmp = null; try {
snmp = new Snmp(new DefaultUdpTransportMapping()); // 构造一个UDP snmp.listen(); // 开始监听snmp消息
CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(community));// snmpv2的团体名 target.setVersion(SnmpConstants.version2c); // snmp版本 target.setAddress(new UdpAddress(ip)); target.setTimeout(1000); // 时延 target.setRetries(2); // 重传
PDU pdu = new PDU(); pdu.setType(PDU.GET); pdu.addOID(new VariableBinding(new OID(oid)));
ResponseEvent responseEvent = snmp.get(pdu, target); PDU response = responseEvent.getResponse(); Vector<? extends VariableBinding> bindings = response.getVariableBindings(); bindings.forEach(item ->{ System.out.println(String.format("OID为:%s的值为:%s", item.getOid().toDottedString(), item.getVariable().getSyntaxString())); });
}finally { if (snmp != null) { snmp.close(); } } }
/** * 根据oids获取数据 * @param ip * @param community * @return */ @SneakyThrows public static void getTable(String ip, String community, List<String> oidList) { Snmp snmp = null; LinkedHashMap<String, List<String>> resMap = new LinkedHashMap<>(); try {
snmp = new Snmp(new DefaultUdpTransportMapping()); // 构造一个UDP snmp.listen(); // 开始监听snmp消息
CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(community));// snmpv2的团体名
target.setVersion(SnmpConstants.version2c); // snmp版本
target.setAddress(new UdpAddress(ip)); target.setTimeout(1000); // 时延 target.setRetries(2); // 重传
TableUtils utils = new TableUtils(snmp, new DefaultPDUFactory( PDU.GETNEXT));// GETNEXT or GETBULK utils.setMaxNumRowsPerPDU(109); // only for GETBULK, set max-repetitions, default is 10
utils.setCheckLexicographicOrdering(false);
OID[] oids = oidList.stream().filter(StringUtils::isNotBlank).map(OID::new).toArray(OID[]::new);
List<TableEvent> table = utils.getTable(target, oids, null, null); table.forEach(item ->{ for (VariableBinding column : item.getColumns()) { System.out.println(String.format("当前的oid为:%s,结果为:%s", column.getOid().toDottedString(), column.getVariable().getSyntaxString())); } }); }finally { if (snmp != null) { snmp.close(); } } }}
复制代码


其中 snmpGet 方法对应 snmpget 命令,snmpWalk 方法对应 snmpwalk 命令。

6.总结

本文开篇即对 SNMP(简单网络管理协议)的基本概念与核心构成进行了全面阐述,紧接着深入剖析了 SNMP 命令在实际网络管理场景中的具体应用。在文章的最后部分,通过 Java 编程语言的实践应用,本文成功展示了 SNMP 命令的实现过程。对 SNMP 协议的深入理解与掌握,无疑将为网络设备的数据监控及多元化自动化管理提供有力支持,进而显著提升网络运维的工作效率。

发布于: 刚刚阅读数: 2
用户头像

拥抱技术,与开发者携手创造未来! 2018-11-20 加入

我们将持续为人工智能、大数据、云计算、物联网等相关领域的开发者,提供技术干货、行业技术内容、技术落地实践等文章内容。京东云开发者社区官方网站【https://developer.jdcloud.com/】,欢迎大家来玩

评论

发布
暂无评论
SNMP协议在设备监控中的使用_京东科技开发者_InfoQ写作社区