【问题标题】:Why is snmp agent not accepting resquest on an snmp4j get, when net-snmp get returns a response event当 net-snmp get 返回响应事件时,为什么 snmp 代理不接受 snmp4j get 上的请求
【发布时间】:2019-03-26 17:02:49
【问题描述】:

我正在尝试编写我的第一个 snmp4j 客户端。我有一个在 192.168.60.105 上运行的代理。使用 net-snmp 我可以查询 OID 并获得结果。使用 smnp4j,snmp get 的响应事件返回空响应和空错误。我认为消息正在超时,但我不知道为什么。

我使用 net-snmp 得到结果

jgaer@ljgaer2_~: snmpget 192.168.60.105 .1.3.6.1.4.1.27675.20.5.2.0
CW-NET-STG-SVR-MIB::cwNetStgSvrProvisioningEnable.0 = Hex-STRING: 00 00 00 00 

我尝试过使用更长的超时时间和更多的重试次数,但返回所需的时间更长。这就是为什么我认为我正在超时。我只是不明白为什么。我也曾预料到,如果在超时时返回 responseEvent,则错误会表明这一点。我试过使用 verions1。使用版本 3 需要一个作用域 PDU。

public static void main(String[] args) throws IOException {
        String address = ("udp:192.168.60.105/161");
        TransportMapping transport = new DefaultUdpTransportMapping();
        Snmp snmp = new Snmp(transport);
        transport.listen();
        PDU pdu = new PDU();
        pdu.setType(PDU.GET);
        pdu.add(new VariableBinding(new OID(".1.3.6.1.4.1.27675.20.5.2.0")));
        Address targetAddress = GenericAddress.parse(address);
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString("public"));
        target.setAddress(targetAddress);
        target.setRetries(2);
        target.setTimeout(1500);
        target.setVersion(SnmpConstants.version2c);
        ResponseEvent response = snmp.send(pdu,target);
        System.out.println(response);
        System.out.println(response.getResponse());
        System.out.println(response.getError());

    }

上面代码运行的结果

org.snmp4j.event.ResponseEvent[source=org.snmp4j.Snmp@3f91beef]
null
null

我希望错误或响应不为空。我正在使用 java 版本 java 版本“1.8.0_191”和 snmp4j 版本 2.5.0。 代理正在运行 2.5.3

我使用 wireshark 跟踪了数据包,并且可以确认我从未使用 snmp4j 得到代理的响应。我对协议的了解不够,无法进行逐字节比较,但是网络的信息列-snmp 调用看起来与 snmp4j 调用非常不同。

网络-snmp

 length       info           
 106          get-request                      : sent from client to agent
 159          report 1.3.6.1.6.3.15.1.1.4.0    : sent from agent to client
 192          encryptedPDI : privKey unknown   : sent from client to agent
 196          encryptedPDI : privKey unknown   : sent from agent to client

snmp4j - 响应从未收到从客户端到代理的三条消息

 89          get-request 1.3.6.1.4.1.27675.20.5.2.0 sent from client to agent

查看字节的文本编码版本,我看到字符串“public”

【问题讨论】:

  • 考虑在您的代码运行时(并且在 netsnmp get 运行时,以确保 1)您实际上正在发送 PDU 2)响应来嗅探到/来自该设备的有线流量返回 3) PDU 和响应在这两种情况下是相似的

标签: java snmp net-snmp snmp4j


【解决方案1】:

问题是代理是 SNMPv3,要求我使用带有一些授权信息的 ScopedPDU。用户和密码短语是从 ~/.snmp/snmp.conf 文件中获得的。我现在正在连接并得到代理的响应。代码如下所示。我没有得到正确的值,而是我发出了多少得到的计数器。但这是另一个问题。

第二个问题是 authProtocol 和 privProtocol 使用了错误的值。 经验教训除了检查 errorResponse 之外,还要检查响应的 pdu 类型。响应类型的报告指示失败,报告的 OID 是导致失败的关键。

public static void main(String[] args) throws Exception {
        TransportMapping transport = new DefaultUdpTransportMapping();
        Snmp snmp = new Snmp(transport);

        OctetString localEngineId = new OctetString(MPv3.createLocalEngineID());
        USM usm = new USM(SecurityProtocols.getInstance(), localEngineId, 0);
        SecurityModels.getInstance().addSecurityModel(usm);

        OctetString securityName = new OctetString("masked");
        OID authProtocol = AuthMD5.ID;
        OID privProtocol = PrivDES.ID;
        OctetString authPassphrase = new OctetString("masked");
        OctetString privPassphrase = new OctetString("masked");

        snmp.getUSM().addUser(securityName, new UsmUser(securityName, authProtocol, authPassphrase, privProtocol, privPassphrase));


        UserTarget target = new UserTarget();
        target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
        target.setSecurityName(securityName);

        target.setAddress(GenericAddress.parse(String.format("udp:%s/%s", "192.168.60.105", "161")));
        target.setVersion(SnmpConstants.version3);
        target.setRetries(2);
        target.setTimeout(60000);
        transport.listen();

        PDU pdu = new ScopedPDU();
        pdu.add(new VariableBinding(new OID(".1.3.6.1.4.1.27675.20.10.1.2.0")));
        pdu.setType(PDU.GET);
        ResponseEvent event = snmp.send(pdu, target);
        if (event != null) {
            PDU pdu2 = event.getResponse();
            System.out.println(pdu2.get(0).getVariable().toString());
            if (pdu2.getErrorStatus() == PDU.noError) {
                System.out.println("SNMPv3 GET Successful!");
            } else {
                System.out.println("SNMPv3 GET Unsuccessful.");
            }
        } else {
            System.out.println("SNMP get unsuccessful.");
        }

}

【讨论】:

  • 这是标准的 SNMP v3 发现过程。您应该查看 snmp4j 文档/示例以了解如何正确执行此操作。
  • 用wireshark查看包。看起来发现正在发生。我看到一个未加密的数据包在没有用户的情况下发出,并看到一个 oid 为 1.3.6.1.6.3.15.1.1.4.0 的报告返回并带有 authorativeEngineId 集。然后我看到第二个数据包与上一个报告集中的 authoritaveEngineeId 一起使用并加密有效负载。这也是我在 net-smtp 生成的请求中看到的。然而,对第二个请求的响应是对 SNMP4J 请求的 pdu 为 1.3.6.1.6.3.15.1.1.5.0 的报告,而它是对 net-snmp 请求的带有加密 PDU 的响应。
  • “1.3.6.1.6.3.15.1.1.4.0”(usmStatsUnknownEngineIDs)和“1.3.6.1.6.3.15.1.1.5.0”(usmStatsWrongDigests)各有含义,tools.ietf.org/html/rfc3414跨度>
  • 如果您找到了解决方案,请发布您自己的答案并接受它。
  • 这个解决方案对我有用,改变 oid ".1.3.6.1.4.1.27675.20.10.1.2.0" 并替换你自己的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多