我能够使用示例 TLS Traffic Encryption Example 中描述的类似方法进行身份验证。
正如人们对示例所期望的那样,我可以确认 SNMP4J 使用 Java 属性 javax.net.ssl.keystore、javax.net.ssl.keyStorePassword、javax.net.ssl.trustStore 和 javax.net.ssl.trustStorePassword 中设置的密钥库。
以下是我对示例所做的更改以使其正常工作。
别名(或文档中的安全名称)需要在CertifiedTarget 构造函数中设置,以便它知道要使用哪个证书。
CertifiedTarget ct = new CertifiedTarget(new OctetString(alias));
必须设置安全级别,否则 SNMP 代理将报错并无法通过身份验证。
ct.setSecurityLevel(SecurityLevel.AUTH_PRIV);
SecurityCallback 主题 DN 必须与服务器证书主题完全匹配,否则它将拒绝所有响应。
securityCallback.addAcceptedSubjectDN("EMAILADDRESS=admin@net-snmp.org, CN=snmpagent, OU=Development, O=Net-SNMP, L=Davis, ST=CA, C=US");
最后,您必须使用该地址注册服务器公共证书别名(安全名称)。
securityCallback.addLocalCertMapping(ct.getAddress(), "snmpagent");
它看起来像这样。
// Set java keystore manually
System.setProperty("javax.net.ssl.keyStore", KEYSTORE_DIR);
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
System.setProperty("javax.net.ssl.trustStore", KEYSTORE_DIR);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
// create the TLS transport mapping:
TLSTM transport = new TLSTM();
// set the security callback (only required for command responder,
// but also recommended for command generators) -
// the callback will be configured later:
DefaultTlsTmSecurityCallback securityCallback = new DefaultTlsTmSecurityCallback();
((TLSTM) transport).setSecurityCallback(securityCallback);
MessageDispatcher md = new MessageDispatcherImpl();
// we need MPv3 for TLSTM:
MPv3 mpv3 = new MPv3();
md.addMessageProcessingModel(mpv3);
Snmp snmp = new Snmp(md, transport);
// create and initialize the TransportSecurityModel TSM:
SecurityModels.getInstance().addSecurityModel(new TSM(new OctetString(mpv3.getLocalEngineID()), false));
// do not forget to listen for responses:
snmp.listen();
CertifiedTarget ct = new CertifiedTarget(new OctetString("alias"));
ct.setVersion(SnmpConstants.version3);
ct.setSecurityModel(SecurityModel.SECURITY_MODEL_TSM);
ct.setAddress(GenericAddress.parse(myAddress));
ct.setSecurityLevel(SecurityLevel.AUTH_PRIV);
securityCallback.addAcceptedSubjectDN("EMAILADDRESS=admin@net-snmp.org, CN=snmpagent, OU=Development, O=Net-SNMP, L=Davis, ST=CA, C=US");
securityCallback.addLocalCertMapping(ct.getAddress(), "snmpagentalias");
PDU pdu = new ScopedPDU();
pdu.add(new VariableBinding(new OID(someOid)));
pdu.setType(PDU.GET);
ResponseEvent response = snmp.send(pdu, ct);
您还必须确保正确配置所有证书,以便实际使用它们。
作为旁注,在发现这一点时,我和我的团队发现了 SNMP4J 处理 TLS 的几个错误,主要是在传输层。这似乎是一个时间问题(可能是竞争条件?)它将获取 SNMP 数据但随后忽略它。我们可以通过设置CertifiedTarget 超时和重试次数来绕过它。我们将在获得更多信息后正式报告此事。