无法使 SNMP 身份验证与 snmp4j 一起正常工作
Can't get SNMP authentication work correctly with snmp4j
我正在编写一个 SNMP v3 trap/informs 发送器,使用带有身份验证的 snmp4j,但令我惊讶的是,即使身份验证失败,通知也会被正确确认。我还使用snmp4j开发了陷阱接收器来帮助我调试。
我注意到几个意想不到的场景:
第一种情况:发送带有 Auth / NoPriv 的 INFORM,用户名未知或密码错误 => INFORM 未被确认,只是没有响应,发件人必须等待超时。然而,在接收方,AuthenticationFailureEvent 被触发,但我预计 snmp4j 会向发送方响应错误。未调用覆盖的方法 processPdu。我想这可能取决于接收器的实现,或者对此有标准的行为?
第二种情况:使用现有用户名发送 INFORM 但没有密码(使用 NoAuth / NoPriv),而它在接收器上配置了密码 => INFORM 被确认为响应,没有任何错误,我的陷阱接收器甚至没有像它应该的那样触发 AuthenticationFailureEvent。
我希望接收方在未经身份验证的情况下拒绝该请求。我忘记初始化什么了吗?我无法想象 snmp4j 中有这样的安全漏洞。
我用于初始化接收器的代码:(我没有在这里显示重写的方法 processPdu 和 authenticationFailure)
EmbeddedSNMPReceiver(final int port, final Optional<UsmUser> user) throws IOException {
final MessageDispatcherImpl dispatcher = new MessageDispatcherImpl();
dispatcher.addAuthenticationFailureListener(this);
final UdpAddress listenAddress = new UdpAddress("localhost/" + port);
final TransportMapping transport = new DefaultUdpTransportMapping(listenAddress);
SecurityProtocols.getInstance().addDefaultProtocols();
final USM usm = new USM(SecurityProtocols.getInstance(), new OctetString("RECEIVER"), 0);
snmp = new Snmp(dispatcher, transport);
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3(usm));
SecurityModels.getInstance().addSecurityModel(usm);
if (user.isPresent()) {
snmp.getUSM().addUser(user.get().getSecurityName(), user.get());
}
snmp.addCommandResponder(this);
snmp.listen();
}
public static void main(String[] args) {
// FOR DEBUG
try {
final OctetString octUsername = new OctetString("zaza");
final OID userAuthOID = AuthSHA.ID;
final OctetString octUserPassphrase = new OctetString("12345678");
final UsmUser user = new UsmUser(octUsername, userAuthOID, octUserPassphrase, null, null);
final EmbeddedSNMPReceiver server = new EmbeddedSNMPReceiver(1099, Optional.of(user));
Thread.sleep(500000);
server.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
PS:澄清一下,我在与发送方不同的进程中启动接收方,以避免 snmp4j 状态性质/单例问题...
您可以仔细阅读 RFC 3414 第 4 节,看看您是否确实达到了发现过程的预期行为。
第一个不应该承认,它遵循 v1 和 v2c 约定。
如果回复消息是 REPORT,则预计是第二个。
我正在编写一个 SNMP v3 trap/informs 发送器,使用带有身份验证的 snmp4j,但令我惊讶的是,即使身份验证失败,通知也会被正确确认。我还使用snmp4j开发了陷阱接收器来帮助我调试。
我注意到几个意想不到的场景:
第一种情况:发送带有 Auth / NoPriv 的 INFORM,用户名未知或密码错误 => INFORM 未被确认,只是没有响应,发件人必须等待超时。然而,在接收方,AuthenticationFailureEvent 被触发,但我预计 snmp4j 会向发送方响应错误。未调用覆盖的方法 processPdu。我想这可能取决于接收器的实现,或者对此有标准的行为?
第二种情况:使用现有用户名发送 INFORM 但没有密码(使用 NoAuth / NoPriv),而它在接收器上配置了密码 => INFORM 被确认为响应,没有任何错误,我的陷阱接收器甚至没有像它应该的那样触发 AuthenticationFailureEvent。 我希望接收方在未经身份验证的情况下拒绝该请求。我忘记初始化什么了吗?我无法想象 snmp4j 中有这样的安全漏洞。
我用于初始化接收器的代码:(我没有在这里显示重写的方法 processPdu 和 authenticationFailure)
EmbeddedSNMPReceiver(final int port, final Optional<UsmUser> user) throws IOException {
final MessageDispatcherImpl dispatcher = new MessageDispatcherImpl();
dispatcher.addAuthenticationFailureListener(this);
final UdpAddress listenAddress = new UdpAddress("localhost/" + port);
final TransportMapping transport = new DefaultUdpTransportMapping(listenAddress);
SecurityProtocols.getInstance().addDefaultProtocols();
final USM usm = new USM(SecurityProtocols.getInstance(), new OctetString("RECEIVER"), 0);
snmp = new Snmp(dispatcher, transport);
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3(usm));
SecurityModels.getInstance().addSecurityModel(usm);
if (user.isPresent()) {
snmp.getUSM().addUser(user.get().getSecurityName(), user.get());
}
snmp.addCommandResponder(this);
snmp.listen();
}
public static void main(String[] args) {
// FOR DEBUG
try {
final OctetString octUsername = new OctetString("zaza");
final OID userAuthOID = AuthSHA.ID;
final OctetString octUserPassphrase = new OctetString("12345678");
final UsmUser user = new UsmUser(octUsername, userAuthOID, octUserPassphrase, null, null);
final EmbeddedSNMPReceiver server = new EmbeddedSNMPReceiver(1099, Optional.of(user));
Thread.sleep(500000);
server.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
PS:澄清一下,我在与发送方不同的进程中启动接收方,以避免 snmp4j 状态性质/单例问题...
您可以仔细阅读 RFC 3414 第 4 节,看看您是否确实达到了发现过程的预期行为。
第一个不应该承认,它遵循 v1 和 v2c 约定。
如果回复消息是 REPORT,则预计是第二个。