I have some troubles configuring SNMP4J as SNMPv3 manager for a simple Get-Request. SNMPv2 is working properly, both using net-snmp and SNMP4J.
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.
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
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.