Skip to content

Commit

Permalink
Fix SNMP v3 issue using USM (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rui Liu authored Jul 30, 2024
1 parent 32cd3de commit fe35fa4
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 24 deletions.
24 changes: 24 additions & 0 deletions host/config/config-snmpv3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
host.system: snmp_host

instances:
- snmp.host: udp:9.30.78.59/161
poll.interval: 25
callback.interval: 30
otel.backend.url: http://127.0.0.1:4317
#otel.backend.using.http: true
#otel.backend.url: http://9.112.252.66:4318/v1/metrics
#host.name: stantest0.fyre.ibm.com
#os.type: linux
#community: public
#retries: 3
#timeout: 1000
version: 3
securityLevel: 3
securityName: linuser
authPassword: linuserpass
privacyPassword: linprivpass
#AuthSHA: 1.3.6.1.6.3.10.1.1.3
authType: 1.3.6.1.6.3.10.1.1.3
#PrivDES: 1.3.6.1.6.3.10.1.2.2
privacyType: 1.3.6.1.6.3.10.1.2.2

Binary file modified host/libs/simp-snmp-0.1.2.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ public SnmpHostDc(Map<String, Object> properties, String hostSystem) throws IOEx
option.setTimeout((Integer) properties.getOrDefault("timeout", 450));
option.setVersion((Integer) properties.getOrDefault("version", SnmpConstants.version2c)); //1
option.setSecurityLevel((Integer) properties.getOrDefault("securityLevel", SecurityLevel.NOAUTH_NOPRIV)); //1
option.setSecurityName((String) properties.get("securityName"));
option.setAuthPassword((String) properties.get("authPassword"));
option.setPrivacyPassword((String) properties.get("privacyPassword"));
option.setAuthType((String) properties.get("authType"));
option.setPrivacyType((String) properties.get("privacyType"));
simpSnmp = new SimpSnmp(snmpHost, option);

Map<OID, SnmpValue> result = simpSnmp.queryScalarOids(Oid.HOST_NAME, Oid.OS_TYPE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
package com.instana.dc.host.impl.snmphost;

import com.instana.dc.SimpleQueryResult;
import com.instana.dc.host.HostDcUtil;
import com.instana.simpsnmp.SnmpValue;
import org.snmp4j.smi.OID;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down
65 changes: 45 additions & 20 deletions internal/simp-snmp/src/main/java/com/instana/simpsnmp/SimpSnmp.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,37 +33,57 @@ public class SimpSnmp implements Closeable {
private final SnmpOption option;

public SimpSnmp(String endpoint, SnmpOption option) throws IOException {
String securityName = "MD5DES";
String securityName = option.getSecurityName();
this.endpoint = endpoint;
this.option = option;
if (option.getVersion() == SnmpConstants.version3) {
myTarget = new UserTarget<>();
myTarget.setSecurityLevel(option.getSecurityLevel());
myTarget.setSecurityName(new OctetString(securityName));
} else {
myTarget = new CommunityTarget<>();
((CommunityTarget<?>) myTarget).setCommunity(new OctetString(option.getCommunity()));
}

Address deviceAdd = GenericAddress.parse(this.endpoint);
myTarget.setAddress(deviceAdd);
myTarget.setRetries(option.getRetries());
myTarget.setTimeout(option.getTimeout());
myTarget.setVersion(option.getVersion());

transport = new DefaultUdpTransportMapping();
protocol = new Snmp(transport);
if (option.getVersion() == SnmpConstants.version3) {
if (option.getSecurityLevel() != SecurityLevel.NOAUTH_NOPRIV) {
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityProtocols sp= new SecurityProtocols(SecurityProtocols.SecurityProtocolSet.maxCompatibility);
/*sp.addDefaultProtocols();
sp.addAuthenticationProtocol(new AuthSHA());
sp.addAuthenticationProtocol(new AuthMD5());
sp.addAuthenticationProtocol(new AuthHMAC128SHA224());
sp.addAuthenticationProtocol(new AuthHMAC192SHA256());
sp.addAuthenticationProtocol(new AuthHMAC256SHA384());
sp.addAuthenticationProtocol(new AuthHMAC384SHA512());
sp.addPrivacyProtocol(new PrivDES());
sp.addPrivacyProtocol(new Priv3DES());
sp.addPrivacyProtocol(new PrivAES128());
sp.addPrivacyProtocol(new PrivAES192());
sp.addPrivacyProtocol(new PrivAES256());*/
USM usm = new USM(sp, new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
transport.listen();
protocol.getUSM().addUser(new UsmUser(
new OctetString(securityName), AuthMD5.ID,
new OctetString(option.getAuthPassword()), PrivDES.ID,
new OctetString(securityName), new OID(option.getAuthType()),
new OctetString(option.getAuthPassword()), new OID(option.getPrivacyType()),
new OctetString(option.getPrivacyPassword())));
}
} else {
transport.listen();
}

if (option.getVersion() != SnmpConstants.version3) {
myTarget = new CommunityTarget<>();
((CommunityTarget<?>) myTarget).setCommunity(new OctetString(option.getCommunity()));

myTarget.setAddress(GenericAddress.parse(this.endpoint));
myTarget.setRetries(option.getRetries());
myTarget.setTimeout(option.getTimeout());
myTarget.setVersion(option.getVersion());
} else {
myTarget = new UserTarget<>();
myTarget.setSecurityLevel(option.getSecurityLevel());
myTarget.setSecurityName(new OctetString(securityName));

myTarget.setAddress(GenericAddress.parse(this.endpoint));
myTarget.setRetries(option.getRetries());
myTarget.setTimeout(option.getTimeout());
myTarget.setVersion(option.getVersion());
}
transport.listen();
}

public SimpSnmp(String endpoint) throws IOException {
Expand Down Expand Up @@ -91,7 +111,12 @@ public void close() throws IOException {
}

public Map<OID, SnmpValue> queryScalarOids(List<OID> oids) throws IOException {
PDU request = new PDU();
PDU request;
if (option.getVersion() < SnmpConstants.version3) {
request = new PDU();
} else {
request = new ScopedPDU();
}
request.setType(PDU.GET);
for (OID oid : oids) {
request.add(new VariableBinding(oid));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.instana.simpsnmp;

import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.fluent.SnmpBuilder;
import org.snmp4j.fluent.SnmpCompletableFuture;
import org.snmp4j.fluent.TargetBuilder;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;

public class SimpSnmpTst {
public static void main(String[] args) throws IOException, ExecutionException {
SnmpBuilder snmpBuilder = new SnmpBuilder();
Snmp snmp = snmpBuilder.udp().securityProtocols(
SecurityProtocols.SecurityProtocolSet.maxCompatibility).v3().usm().build();

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

if (targetEngineID != null) {
TargetBuilder<?> targetBuilder = snmpBuilder.target(targetAddress);

Target<?> target = targetBuilder
.user("linuser", targetEngineID)
.auth(TargetBuilder.AuthProtocol.sha1).authPassphrase("linuserpass")
.priv(TargetBuilder.PrivProtocol.des).privPassphrase("linprivpass")
.done()
.timeout(1500).retries(2)
.build();
target.setVersion(SnmpConstants.version3);
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);

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

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class SnmpOption {
private int securityLevel;
private String authPassword;
private String privacyPassword;
private String securityName;
private String authType;
private String privacyType;

public SnmpOption() {
this.community = "public";
Expand Down Expand Up @@ -53,15 +56,23 @@ public int getVersion() {
}

public void setVersion(int version) {
this.version = version;
if (version == SnmpConstants.version3) {
this.version = SnmpConstants.version3;
} else {
this.version = SnmpConstants.version2c;
}
}

public int getSecurityLevel() {
return securityLevel;
}

public void setSecurityLevel(int securityLevel) {
this.securityLevel = securityLevel;
if (securityLevel < SecurityLevel.NOAUTH_NOPRIV || securityLevel > SecurityLevel.AUTH_PRIV) {
this.securityLevel = SecurityLevel.NOAUTH_NOPRIV;
} else {
this.securityLevel = securityLevel;
}
}

public String getAuthPassword() {
Expand All @@ -79,4 +90,28 @@ public String getPrivacyPassword() {
public void setPrivacyPassword(String privacyPassword) {
this.privacyPassword = privacyPassword;
}

public String getSecurityName() {
return securityName;
}

public void setSecurityName(String securityName) {
this.securityName = securityName;
}

public String getAuthType() {
return authType;
}

public void setAuthType(String authType) {
this.authType = authType;
}

public String getPrivacyType() {
return privacyType;
}

public void setPrivacyType(String privacyType) {
this.privacyType = privacyType;
}
}

0 comments on commit fe35fa4

Please sign in to comment.