Hi!
I’m experiencing issues when attempting to execute SNMP commands over DTLS. I have successfully implemented functionality for USM and “regular” TLS, but I am unsuccessful in my attempts to replace TLS with DTLS. I’m using SNMP4J v3.6.4 (the latest and greatest).
Below is the code I’m running for TLS (which works):
System.setProperty("javax.net.ssl.keyStore", <path>);
System.setProperty("javax.net.ssl.keyStorePassword", <password>);
System.setProperty("javax.net.ssl.trustStore", <path>);
System.setProperty("javax.net.ssl.trustStorePassword", <password>);
TLSTM transport = new TLSTM();
DefaultTlsTmSecurityCallback securityCallback = new DefaultTlsTmSecurityCallback();
((TLSTM) transport).setSecurityCallback(securityCallback);
MessageDispatcher md = new MessageDispatcherImpl();
MPv3 mpv3 = new MPv3();
md.addMessageProcessingModel(mpv3);
SecurityModels.getInstance().addSecurityModel(new TSM(new OctetString(mpv3.getLocalEngineID()), false));
Snmp snmpClient = new Snmp(md, transport);
ScopedPDU pdu = new ScopedPDU();
pdu.setType(PDU.GET);
pdu.add(new VariableBinding(new OID(<oid>)));
transport.listen();
CertifiedTarget<Address> target = new CertifiedTarget<Address>(new OctetString("<sn>"));
target.setVersion(SnmpConstants.version3);
target.setSecurityModel(SecurityModel.SECURITY_MODEL_TSM);
target.setAddress(GenericAddress.parse("tls:192.168.0.123/10161")); // Not my actual IP
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
target.setRetries(2);
ResponseEvent<Address> res = snmpClient.send(pdu, target);
The request finishes and the response contains the value of the OID I’m requesting.
I figured all I had to do in order to get DTLS up and running was replace the the transport to “DTLSTM” instead of “TLSTM”, and then replace the “tls”-prefix in the address with “dtls”. Below is the code I’m attempting for DTLS. It’s essentially the same, but I left comments on the parts where it differs from the code above:
System.setProperty("javax.net.ssl.keyStore", <path>);
System.setProperty("javax.net.ssl.keyStorePassword", <password>);
System.setProperty("javax.net.ssl.trustStore", <path>);
System.setProperty("javax.net.ssl.trustStorePassword", <password>);
DTLSTM transport = new DTLSTM(); // Changed to DTLSTM
DefaultTlsTmSecurityCallback securityCallback = new DefaultTlsTmSecurityCallback();
((DTLSTM) transport).setSecurityCallback(securityCallback); // Changed to DTLSTM
MessageDispatcher md = new MessageDispatcherImpl();
MPv3 mpv3 = new MPv3();
md.addMessageProcessingModel(mpv3);
SecurityModels.getInstance().addSecurityModel(new TSM(new OctetString(mpv3.getLocalEngineID()), false));
Snmp snmpClient = new Snmp(md, transport);
ScopedPDU pdu = new ScopedPDU();
pdu.setType(PDU.GET);
pdu.add(new VariableBinding(new OID(<oid>)));
transport.listen();
CertifiedTarget<Address> target = new CertifiedTarget<Address>(new OctetString("<sn>"));
target.setVersion(SnmpConstants.version3);
target.setSecurityModel(SecurityModel.SECURITY_MODEL_TSM);
target.setAddress(GenericAddress.parse("dtls:192.168.0.123/10161")); // Changed "tls" to "dtls"
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
target.setRetries(2);
ResponseEvent<Address> res = snmpClient.send(pdu, target);
Now, when running with debug enabled, I get the following exception:
java.io.IOException: DTLSTM: SSLEngine has closed
at org.snmp4j.transport.DTLSTM.prepareOutPackets(DTLSTM.java:710)
at org.snmp4j.transport.DefaultUdpTransportMapping.sendMessage(DefaultUdpTransportMapping.java:123)
at org.snmp4j.transport.DefaultUdpTransportMapping.sendMessage(DefaultUdpTransportMapping.java:46)
at org.snmp4j.MessageDispatcherImpl.sendMessage(MessageDispatcherImpl.java:261)
at org.snmp4j.MessageDispatcherImpl.sendPdu(MessageDispatcherImpl.java:612)
at org.snmp4j.Snmp.sendMessage(Snmp.java:1059)
at org.snmp4j.Snmp$PendingRequest.run(Snmp.java:1899)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)
There is also an ERROR-line printed a few lines above the exception:
ERROR DTLS handshake failed for 192.168.0.123/192.168.0.123:10161, status is NEED_UNWRAP: Not ready for application data yet, giving up
I have verified that DTLS works outside SNMP4J by executing a “raw” snmpget from the net-snmp package with the following command, and it works fine:
snmpget -v 3 -T our_identity=<identity> -T their_identity=<identity> dtls:192.168.0.123:10161 <oid>
I’m at total loss here. I thought it was the firewall and first and ended up disabling it with no improvements. But since I am able to run the same query with “snmpget” I figured it wasn’t the firewall.
Are there any additional steps required for DTLS that I have missed, that isn’t required for TLS?
Kind regards and happy holidays,
Andreas