Skip to content

SNMPv3 Get Request authorization problem for SNMP4J although working via 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

Answer

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.