简介
简单网络管理协议 (SNMP) 是一种互联网标准协议,用于收集和组织有关 IP 网络上托管设备的信息,并修改该信息以更改设备行为。通常支持 SNMP 的设备包括电缆调制解调器、路由器、交换机、服务器、工作站、打印机等
引入
通常使用snmp4j进行操作,JDK8最高支持2.8.18
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.8.18</version>
</dependency>
Get/Walk
- v1/v2c
UdpAddress udpAddress = new UdpAddress(InetAddress.getByName(host), 161);
CommunityTarget target = new CommunityTarget();
//SnmpConstants.version1或SnmpConstants.version2c
target.setVersion(SnmpConstants.version1);
target.setAddress(udpAddress);
target.setCommunity(new OctetString(community));
target.setTimeout(5000);
target.setRetries(3);
PDU pdu = new PDU();
pdu.setType(PDU.GET);
//要查询的oid
pdu.add(new VariableBinding(new OID(oid)));
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
try {
snmp.listen();
ResponseEvent respEvent = snmp.send(pdu, target);
PDU response = respEvent.getResponse();
//get或是walk
response.getVariableBindings().forEach(variableBinding -> {
...variableBinding
});
} finally {
snmp.close();
}
- v3
UdpAddress udpAddress = new UdpAddress(InetAddress.getByName(host), 161);
UserTarget target = new UserTarget();
target.setVersion(SnmpConstants.version3);
target.setAddress(udpAddress);
//SecurityLevel.NOAUTH_NOPRIV无认证与加密 SecurityLevel.AUTH_NOPRIV 有认证无加密 SecurityLevel.AUTH_PRIV有认证有加密
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
target.setSecurityName(new OctetString(username));
target.setTimeout(5000);
target.setRetries(3);
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
try {
//如果存在多次调用的情况需要提取为静态代码
SecurityModels.getInstance().addSecurityModel(new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0));
snmp.listen();
snmp.getUSM().addUser(new OctetString(username), new UsmUser(new OctetString(username),
AuthMD5.ID, new OctetString(password), PrivDES.ID, new OctetString(privPassword)));
PDU pdu = new ScopedPDU();
//要查询的oid
pdu.add(new VariableBinding(new OID(oid)));
pdu.setType(PDU.GET);
ResponseEvent respEvent = snmp.send(pdu, target);
PDU response = respEvent.getResponse();
//get或是walk
response.getVariableBindings().forEach(variableBinding -> {
...variableBinding
});
} finally {
snmp.close();
}
请注意,v3版本需要添加安全模型,但如果存在多次或多线程调用的情况,每次创建snmp对象都添加安全模型有概率出现异常:
Message processing model 3 returned error: Unknown security name
原因是多次创建绑定了安全模型,因此,可以通过静态代码块中绑定来避免此问题(问题方案)
private static final USM USM;
static {
USM = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(USM);
}
Trap
- 发送
trap发送基本与get/walk代码相同,只是发送的类型转变为了PDU.TRAP
pdu.setType(PDU.TRAP)
- 接收
ThreadPool threadPool = ThreadPool.create("Trap", 2);
MultiThreadedMessageDispatcher dispatcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());
Snmp snmp = new Snmp(dispatcher);
try {
UdpAddress address = new UdpAddress(InetAddress.getByName(host), 162);;
TransportMapping<?> transport = new DefaultUdpTransportMapping(address);
snmp.addTransportMapping(transport);
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityProtocols.getInstance().addDefaultProtocols();
//v3版本需要配置
snmp.getUSM().addUser(new OctetString(username), new UsmUser(new OctetString(username),
AuthMD5.ID, new OctetString(password), PrivDES.ID, new OctetString(privPassword)));
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3(usm));
snmp.listen();
snmp.addCommandResponder((event) -> {
//解析event获取trap
event.getPDU()...
});
} finally {
snmp.close();
}
目前常用的加密协议有DES,AES128,AES192,AES256,如果需要使用超过128位的AES加密,需将local_policy.jar和US_export_policy.jar(下载地址)放置到jre的目录内(/usr/java/jdk1.8.x_xx/jre/lib/security/)问题方案