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

发布于 2025-01-16 20:58:47 字数 3333 浏览 1 评论 0原文

问题

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

设置

在我的本地计算机上,我有一个正在运行的 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 运行结果:请求失败:SNMP 请求超时

我使用 tcpdump 捕获了本地主机 UDP 端口 161 流量。可以从 net-snmp 看到 snmpget 的前 4 个数据包(成功),然后从 SNMP4J 看到 4 个数据包。 看起来 EngineID 发现对于 SNMP4J 也同样有效,但下一个数据包中的 msgAuthenticationParameters 比相应的 net-snmp 请求数据包中的 msgAuthenticationParameters 长得多。 然后,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 使用哪个版本?

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

谢谢你并致以最诚挚的问候, 塞巴斯蒂安

Problem

I have some troubles configuring SNMP4J as SNMPv3 manager for a simple Get-Request.
SNMPv2 is working properly, both using net-snmp and SNMP4J.

Setup

On my local machine I have a running snmp daemon (via 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

A snmpget using net-snmp works as expected:

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

My SNMP4J implementation looks as follows:

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();
}

I sometimes used non-fluent syntax (e.g. target.setVersion()) since the corresponding fluent method was not working.

Analysis

SNMP4J run result: Request failed: SNMP Request timed out

I captured the localhost UDP port 161 traffic using tcpdump. First 4 packets can be seen for snmpget from net-snmp (successful), then 4 packets for from SNMP4J.
It looks as if the EngineID discovery works as well for SNMP4J, but the msgAuthenticationParameters in the next packet are way longer than in the corresponding net-snmp request packet.
The SNMP4J request is then answered with a report with OID “1.3.6.1.6.3.15.1.1.5.0” (oidUsmStatsWrongDigests).

SNMP daemon log:

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

So it seems to be an authentication issue, but the username and password are definitely the same and correct. Is there something wrong with the authProtocol? Which version is net-snmp using when specifying only “SHA”?

Can someone provide further hints where to look for the root cause?

Thank you and best regards,
Sebastian

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

依 靠 2025-01-23 20:58:47

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

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

然而,执行现在立即失败:
SNMP 错误索引 0 上的授权错误
此外,Net-SNMP 守护程序日志为空。

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

I solved it, in the end it was a SHA version issue:

net-snmp by default employs SHA-1, so I changed TargetBuilder.AuthProtocol.hmac192sha256 to TargetBuilder.AuthProtocol.sha1.

However, execution now failed instantly with:
SNMP error Authorization error on index 0
Also, the Net-SNMP daemon log was empty.

After debugging the SNMP4J execution and reading its in-file documentation I discovered that the SHA-1 protocol must be explicitly added to the Snmp instance since SNMP4J considers it to be unsafe.
Adding .securityProtocols(SecurityProtocols.SecurityProtocolSet.maxCompatibility) before .v3() in the Snmp building chain now resolves everything.

我喜欢麦丽素 2025-01-23 20:58:47

我不熟悉 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);

I'm unfamiliar with SNMP4J, but this block of code may need to have the security level defined as authPriv or however SNMP4J refers to it:

      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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文