无法使 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 中有这样的安全漏洞。

我用于初始化接收器的代码:(我没有在这里显示重写的方法 processPduauthenticationFailure

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,则预计是第二个。