我编写了一个SNMP代理并注册了一个托管对象(创建/设置了一个MIB OID的值)。 当我使用SNMPv2c检索此值时,正确返回值 - 来自ResponseEvent.getResponse的PDU具有type = GET,并且变量绑定具有预期数据 - 正确的OID等。 当我使用SNMPv3和用户身份验证检索此值时,未正确返回值 - 来自ResponseEvent.getResponse的PDU具有type = REPORT并且变量绑定具有 与请求中的OID不同 - 从我到目前为止所看到的,这表示配置/身份验证错误。 以下是用于客户端的示例代码(片段)。代理商 - 请你告诉我如何创建代理商&客户 - 我出错的地方?
// TestSNMPAgent:
public class TestSNMPAgent {
private OID sysDescr = new OID("1.3.6.1.2.1.1.1.0");
...
public static void main(String[] args) throws IOException {
TestSNMPAgent agent = new TestSNMPAgent();
agent.init("0.0.0.0/4071");
private void init(String agentIp) throws IOException {
agent = new SNMPAgent(agentIp);
agent.start();
agent.unregisterManagedObject(agent.getSnmpv2MIB());
agent.registerManagedObject(new MOScalar(oid,
MOAccessImpl.ACCESS_READ_WRITE,
getVariable(value),sysDescr,
"1")));
...
}
}
// SNMPAgent:
public class SNMPAgent extends BaseAgent {
...
@Override
protected void addUsmUser(USM arg0) {
UsmUser user = new UsmUser(new OctetString("SHADES"),
AuthSHA.ID,
new OctetString("SHADESAuthPassword"),
PrivDES.ID,
new OctetString("SHADESPrivPassword"));
}
@Override
protected void addViews(VacmMIB vacm) {
vacm.addGroup(SecurityModel.SECURITY_MODEL_USM,
new OctetString("SHADES"),
new OctetString("v3group"),
StorageType.nonVolatile);
vacm.addAccess(new OctetString("v3group"), new OctetString(),
SecurityModel.SECURITY_MODEL_USM,
SecurityLevel.NOAUTH_NOPRIV, VacmMIB.vacmExactMatch,
new OctetString("fullReadView"),
new OctetString("fullWriteView"),
new OctetString("fullNotifyView"),
StorageType.nonVolatile);
}
public void registerManagedObject(ManagedObject mo) {
try {
server.register(mo, null);
} catch (DuplicateRegistrationException ex) {
throw new RuntimeException(ex);
}
}
// TestSNMPMgr
public class TestSNMPMgr {
public static void main(String[] args) throws IOException {
TestSNMPMgr client = new TestSNMPMgr();
client.init();
}
public void init() {
SNMPMgr client = new SNMPMgr();
client.start();
// Get back Value which is set
String value = client.getAsString(new OID("1.3.6.1.2.1.1.1.0"));
}
}
// SNMPMgr
public class SNMPMgr {
Snmp snmp = null;
Address address = null;
public SNMPMgr()
{
address = "1.3.6.1.2.1.1.1.0";
}
/**
* Start the Snmp session. If you forget the listen() method you will not
* get any answers because the communication is asynchronous
* and the listen() method listens for answers.
* @throws IOException
*/
public void start() throws IOException {
address = GenericAddress.parse("udp:127.0.0.1/4701");
TransportMapping transport = new DefaultUdpTransportMapping();
snmp = new Snmp(transport);
USM usm = new USM(SecurityProtocols.getInstance(),
new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
transport.listen();
}
public void end() {
try {
snmp.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Method which takes a single OID and returns the response from the agent as a String.
* @param oid
* @return
* @throws IOException
*/
public String getAsString(OID oid) throws IOException {
ResponseEvent event = get(new OID[] { oid });
return event.getResponse().get(0).getVariable().toString();
}
public ResponseEvent get(OID oids[]) throws IOException {
PDU pdu = new ScopedPDU();
for (OID oid : oids) {
pdu.add(new VariableBinding(oid));
}
pdu.setType(PDU.GET);
// add user to the USM
snmp.getUSM().addUser(new OctetString("SHADES"),
new UsmUser(new OctetString("SHADES"),
AuthSHA.ID,
new OctetString("SHADESAuthPassword"),
PrivDES.ID,
new OctetString("SHADESPrivPassword")));
// send the PDU
ResponseEvent event = snmp.send(pdu, getTarget(), null);
if(event != null) {
return event;
}
throw new RuntimeException("GET timed out");
}
/**
* This method returns a Target, which contains information about
* where the data should be fetched and how.
* @return
*/
private UserTarget getTarget() {
UserTarget target = new UserTarget();
target.setAddress(address);
target.setRetries(1);
target.setTimeout(5000);
target.setVersion(SnmpConstants.version3);
target.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
target.setSecurityName(new OctetString("SHADES"));
return target;
}
}
答案 0 :(得分:0)
报告PDU中的OID应该告诉您发生了什么。在典型情况下,将有一个或两个(或两个)请求/报告交换,以在管理器和代理(或者更确切地说,分别是非权威和权威引擎)之间建立初始SNMPv3通信。
第一个通常是usmStatUnknownEngineIDs
报告,允许管理员发现代理的引擎ID(密钥本地化等所需),如果您没有指定正确的,则会发生初始请求中的引擎ID。如果使用auth/noPriv
或auth/priv
级别安全性,那么第二个/另一个会发生,这是usmStatsNotInTimeWindows
,如果请求未在适当的时间内指定引擎启动/引擎时间值,则会发送user
代理商的价值范围。这些值可以通过使请求不再有效来防止消息重放攻击,如果它们超出时间窗口,并且管理器通常不知道它们是什么,直到它通过报告PDU从代理接收它们为止。
管理员拥有正确的引擎ID,引导和时间,并在必要时具有引擎ID的本地化密钥,然后正常的请求/响应交换可以按预期进行。一些SNMP API将为您处理此交换,因此您只需发送您的请求并在交换后获得最终结果。似乎SNMP4j没有,如果它是其中一个报告,你可能必须自己处理它。
如果它不是这些报告之一,那么您的配置可能不匹配。