SNMP 学习上篇——获取路由器的 ARP 表

背景

SNMP 协议可以跟远程主机进行通信,实现对目标主机的监控。

路由器的 ARP

路由器的 APR 信息表是通过两个 oid 结果关联形成的,先获取 oid 为 1.3.6.1.2.1.4.22.1.2 标识的主机的 MAC 物理地址信息,再获取 oid 为 1.3.6.1.2.1.4.22.1.3 的 IP 地址信息,二者通过 OID 关联,形成一张 ARP 信息表。snmp4j 的 TableUtil 类可以自动将两个 OID 的结果根据 OID 自动完成关联,形成一张表,这就是解决本文问题的核心要素。

snmpwalk 工具

使用 yum -y install net-snmp* 命令可以在 Linux 操作系统中安装 snmpwalk 工具,用于测试。

常用 OID :
1.3.6.1.2.1.4.22.1.3 主机的IP地址
1.3.6.1.2.1.4.22.1.2 主机的MAC地址
1.3.6.1.2.1.3.1.1.2 直接得到 ARP 地址信息表

snmp4j PDU 发送请求

PUD 是 snmp4j 封装的通信包类,用它可以完成一次 SNMP 请求,但是它有一个缺陷,只能获取到某个 oid 列表数据中的第一个,基本用法为:

 try{  
            //设定CommunityTarget   
            CommunityTarget myTarget = new CommunityTarget();
            //定义远程主机的地址  
            //Address deviceAdd = GenericAddress.parse("udp:192.168.1.233/161"); 
            //定义本机的地址   
            Address localAdd = GenericAddress.parse("udp:localhost/161");
            //设定远程主机的地址 
            //myTarget.setAddress(deviceAdd); 
            //设定本地主机的地址
            myTarget.setAddress(localAdd);
            //设置snmp共同体   
            myTarget.setCommunity(new OctetString("public")); 
            //设置超时重试次数   
            myTarget.setRetries(2); 
            //设置超时的时间  
            myTarget.setTimeout(5*60);
            //设置使用的snmp版本 
            myTarget.setVersion(SnmpConstants.version2c);  
             
            //设定采取的协议   
            TransportMapping transport = new DefaultUdpTransportMapping();//设定传输协议为UDP
            //调用TransportMapping中的listen()方法,启动监听进程,接收消息,由于该监听进程是守护进程,最后应调用close()方法来释放该进程
            transport.listen();  
            //创建SNMP对象,用于发送请求PDU
            Snmp protocol = new Snmp(transport);  
            //创建请求pdu,获取mib   
            PDU request = new PDU(); 
            //调用的add方法绑定要查询的OID
            request.add(new VariableBinding(new OID("1.3.6.1.2.1.1.1")));  
            request.add(new VariableBinding(new OID(new int[] {1,3,6,1,2,1,1,2})));
            //调用setType()方法来确定该pdu的类型
            request.setType(PDU.GETNEXT);
            //调用 send(PDU pdu,Target target)发送pdu,返回一个ResponseEvent对象
            ResponseEvent responseEvent = protocol.send(request, myTarget);  
            //通过ResponseEvent对象来获得SNMP请求的应答pdu,方法:public PDU getResponse()
            PDU response=responseEvent.getResponse();  
            //输出   
            if(response != null){  
                System.out.println("request.size()="+request.size());  
                System.out.println("response.size()="+response.size());
                //通过应答pdu获得mib信息(之前绑定的OID的值),方法:VaribleBinding get(int index)
                VariableBinding vb1 = response.get(0);  
                VariableBinding vb2 = response.get(1);  
                System.out.println(vb1);  
                System.out.println(vb2);
                //调用close()方法释放该进程
                transport.close();  
            }    
          }catch(IOException e){  
              e.printStackTrace();  
          }  
        }  

snmp4j 的 TableUtil 工具类

某个主机的 IP OID 对应的数据不止一条,但是通过 PDU 的 GETNEXT 方法却只能获取到一个,怎么能获取到全部的数据呢?

在这里插入图片描述

找到这个包的一个 TableUtil 的工具类,基本用法如下:

public static void main(String[] args) {
		try {
			// 设定CommunityTarget
			CommunityTarget myTarget = new CommunityTarget();
			// 定义远程主机的地址
			Address localAdd = GenericAddress.parse("udp:127.0.0.1/161");
			// 设定本地主机的地址
			myTarget.setAddress(localAdd);
			// 设置snmp共同体
			myTarget.setCommunity(new OctetString("public"));
			// 设置超时重试次数
			myTarget.setRetries(2);
			// 设置超时的时间
			myTarget.setTimeout(5 * 60);
			// 设置使用的snmp版本
			myTarget.setVersion(SnmpConstants.version2c);

			// 设定采取的协议
			TransportMapping<?> transport = new DefaultUdpTransportMapping();// 设定传输协议为UDP

			// 调用TransportMapping中的listen()方法,启动监听进程,接收消息,由于该监听进程是守护进程,最后应调用close()方法来释放该进程
			transport.listen();
			// 创建SNMP对象,用于发送请求PDU
			Snmp protocol = new Snmp(transport);

			TableUtils utils = new TableUtils(protocol, new DefaultPDUFactory(PDU.GETBULK));// GETNEXT
			utils.setMaxNumRowsPerPDU(5); // only for GETBULK, set

			// ARP 信息表 macOid-ipOid 得到的就是 ORP 信息表
			String macOid = "1.3.6.1.2.1.4.22.1.2";
			String ipOid = "1.3.6.1.2.1.4.22.1.3";
			OID[] columnOids = new OID[] { new OID(macOid), new OID(ipOid) };
			List<TableEvent> l = utils.getTable(myTarget, columnOids, null, null);
			for (TableEvent e : l) {
				VariableBinding[] columns = e.getColumns();
				System.out.println(columns[0].toValueString() + "," + columns[1].toValueString());
			}
			transport.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

代码参考资源

参考资源一
参考资源二
SNMP4j 的 snmp 使用
其他参考资源:
1)https://www.cnblogs.com/yuanfy008/p/8046189.html
2)https://blog.csdn.net/SignX/article/details/1774023
3)http://www.rfyy.net/archives/638.html
4)https://bbs.csdn.net/topics/392032180

发布了234 篇原创文章 · 获赞 494 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/wojiushiwo945you/article/details/103051415