尽管通过 net-snmp 工作,但 SNMPv3 获取 SNMP4J 的请求授权问题

SNMPv3 Get Request authorization problem for SNMP4J although working via net-snmp

问题

我在为简单的 Get-Request 配置 SNMP4J 作为 SNMPv3 管理器时遇到了一些麻烦。 SNMPv2 工作正常,同时使用 net-snmp 和 SNMP4J。

设置

在我的本地机器上,我有一个 运行ning snmp 守护进程(通过 net-snmp)。

zetts@zetts_x1_carbon~: cat /etc/snmp/snmpd.conf
rouser v3_ro_user priv .1
rocommunity start123

#       sec.name  source          community
com2sec local     localhost       public

group MyRWGroup    v1         local
group MyRWGroup    v2c        local
group MyRWGroup    usm        local

view all    included  .1                               80

access MyROGroup ""      any       noauth    exact  all    none   none
access MyRWGroup ""      any       noauth    exact  all    all    none

使用 net-snmp 的 snmpget 按预期工作:

zetts@zetts_x1_carbon~: snmpget -v 3 -l authPriv -u v3_ro_user -a sha -A myAuthPw -x aes -X myPrivPw localhost .1.3.6.1.2.1.1.1.0
SNMPv2-MIB::sysDescr.0 = STRING: Linux zettsx1carbon 5.10.105-1-MANJARO #1 SMP PREEMPT Fri Mar 11 14:12:33 UTC 2022 x86_64

我的 SNMP4J 实现如下所示:

public static void get() throws IOException {

SnmpBuilder snmpBuilder = new SnmpBuilder();
Snmp snmp = snmpBuilder.udp().v3().usm().build();

Address targetAddress = GenericAddress.parse("udp:127.0.0.1/161");
byte[] targetEngineID = snmp.discoverAuthoritativeEngineID(targetAddress, 1000);

if (targetEngineID != null) {
      System.out.println("Trying with " + authPro.toString());
      TargetBuilder<?> targetBuilder = snmpBuilder.target(targetAddress);

      Target<?> target = targetBuilder
              .user("v3_ro_user", targetEngineID)
              .auth(TargetBuilder.AuthProtocol.hmac192sha256).authPassphrase("myAuthPw")
              .priv(TargetBuilder.PrivProtocol.aes128).privPassphrase("myPrivPw")
              .done()
              .timeout(1500).retries(1)
              .build();
      target.setVersion(SnmpConstants.version3);

      PDU pdu = targetBuilder.pdu().type(PDU.GET).contextName("").build();
      pdu.add(new VariableBinding(new OID(".1.3.6.1.2.1.1.1.0")));

      SnmpCompletableFuture snmpRequestFuture = SnmpCompletableFuture.send(snmp, target, pdu);
      try {
          List<VariableBinding> vbs = snmpRequestFuture.get().getAll();
          System.out.println("Received: " + snmpRequestFuture.getResponseEvent().getResponse());
      } catch (ExecutionException | InterruptedException ex) {
          System.err.println("Request failed: " + ex.getCause().getMessage());
      }
} else {
    System.err.println("Timeout on engine ID discovery for " + targetAddress + ", GET not sent.");
}
snmp.close();
}

我有时会使用不流畅的语法(例如 target.setVersion()),因为相应的流畅方法不起作用。

分析

SNMP4J 运行 结果:Request failed: SNMP Request timed out

我使用 tcpdump 捕获了本地主机 UDP 端口 161 的流量。可以看到来自 net-snmp 的 snmpget 的前 4 个数据包(成功),然后是来自 SNMP4J 的 4 个数据包。 看起来 EngineID 发现也适用于 SNMP4J,但下一个数据包中的 msgAuthenticationParameters 比相应的 net-snmp 请求数据包中的要长得多。 然后 SNMP4J 请求得到 OID 为“1.3.6.1.6.3.15.1.1.5.0” (oidUsmStatsWrongDigests) 的报告的答复。

SNMP 守护程序日志:

zetts@zetts_x1_carbon~: cat snmpd.log
NET-SNMP version 5.9.1
Authentication failed for v3_ro_user

看来是身份验证的问题,但是用户名和密码肯定是一样的,而且是正确的。 authProtocol 有问题吗?仅指定“SHA”时 net-snmp 使用哪个版本?

有人可以进一步提示在哪里寻找根本原因吗?

谢谢你和最诚挚的问候, 塞巴斯蒂安

我不熟悉 SNMP4J,但是这段代码可能需要将安全级别定义为 authPriv 或者 SNMP4J 引用它:

      Target<?> target = targetBuilder
              .user("v3_ro_user", targetEngineID)
              .auth(TargetBuilder.AuthProtocol.hmac192sha256).authPassphrase("myAuthPw")
              .priv(TargetBuilder.PrivProtocol.aes128).privPassphrase("myPrivPw")
              .done()
              .timeout(1500).retries(1)
              .build();
      target.setVersion(SnmpConstants.version3);

我解决了,最后是SHA版本问题:

net-snmp 默认使用 SHA-1,所以我将 TargetBuilder.AuthProtocol.hmac192sha256 更改为 TargetBuilder.AuthProtocol.sha1

但是,现在执行立即失败: SNMP error Authorization error on index 0 此外,Net-SNMP 守护程序日志为空。

调试 SNMP4J 执行并阅读其 in-file 文档后,我发现 SHA-1 协议必须显式添加到 Snmp 实例,因为 SNMP4J 认为它不安全。 在 Snmp 构建链中的 .v3() 之前添加 .securityProtocols(SecurityProtocols.SecurityProtocolSet.maxCompatibility) 现在可以解决所有问题。