带有 AuthPriv 的 SNMP4J V3 Trap 未处理

SNMP4J V3 Trap with AuthPriv not processing

我正在尝试使用 SNMP4J 在 Java 中创建一个 SNMP TRAP/Notify 代理。 traps/notify 用于发送给远程侦听器。

我想通过身份验证添加对 V2 和 V3 陷阱的支持。

我目前的设置:

我的问题简要描述:

我已经使用以下命令尝试了我的设置,确认它有效:

虚拟机:

sudo snmptrapd -f -Lo -c /usr/share/snmpdtrapd.conf

开发:

sudo snmptrap -e 0x80001370017f000101 -v 3 -a SHA -A 02m-auth -x DES -X o2m-priv -l authPriv o2m-user 192.168.1.92:162 1 .1.3.6.1.2.1.1.8

在 VM 上生成此日志消息:

2018-10-29 14:42:21 <UNKNOWN> [UDP: [192.168.1.61]:44309-> 
[192.168.1.92]:162]:
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (1) 0:00:00.01  
SNMPv2-MIB::snmpTrapOID.0 = OID: SNMPv2-MIB::sysORLastChange

现在我已经 运行 下面的代码,并且已经确认它到达了 VM(运行 启用了 -d 的 snmptrapd 命令可以看到 snmp 数据包实际到达)

        TransportMapping transportMapping = new DefaultUdpTransportMapping();
        Snmp snmp = new Snmp(transportMapping);
        OctetString localEngineId = new OctetString(MPv3.createLocalEngineID());

        USM usm = new USM(SecurityProtocols.getInstance(), localEngineId, 0);

        SecurityModels.getInstance().addSecurityModel(usm);


        OctetString securityName = new OctetString("o2m-user");

        OID authProtocol = AuthSHA.ID;
        OID privProtocol = PrivDES.ID;

        OctetString authPassphrase = new OctetString("o2m-auth");
        OctetString privPassphrase = new OctetString("o2m-priv");

        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(new UdpAddress("192.168.1.92" + "/" + 162));
        target.setVersion(SnmpConstants.version3);

        snmp.listen();

        ScopedPDU pdu = new ScopedPDU();
        pdu.setType(PDU.TRAP);
        pdu.setContextEngineID(localEngineId);
        pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(1)));
        pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(".1.3.6.1.2.1.1.8")));


        System.out.println("Sending V3 trap");
        snmp.send(pdu, target);
        snmp.close();

上面的代码不会在 snmptrapd 服务器上生成任何日志消息。

我也试过用实际的引擎 ID 替换 MPv3.createLocalEngineId(),但这似乎也没有帮助。

我已经对这两个请求(来自 JAVA 和来自 snmp-trap)进行了 Wireshark,我注意到的唯一区别是它们都有不同的 AuthorativeEngineID。

Java 有一个生成的,因为它在每个请求上都不同,snmp-trap 有一个静态的。

我做错了什么?

能否附上到达的snmp数据包的详细日志?

我认为用户 "o2m-user" 是在 192.168.1.92 上使用 AuthorativeEngineID 0x80001370017f000101 创建的,所以我尝试用它发送陷阱消息。

所以,我更新了

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

OctetString  authorativeEngineID = createOctetString("0x80001370017f000101");  +
snmp.getUSM().addUser(securityName, authorativeEngineID, new UsmUser(securityName, authProtocol, authPassphrase, privProtocol, privPassphrase));  -+

private OctetString createOctetString(String s) {
    if (s == null) {
        return null;
    }
    OctetString octetString = null;
    if (s.startsWith("0x")) {
        octetString = createStr16(s.substring(2));
    }
    else {
        octetString = new OctetString(s);
    }
    return octetString;
}

private OctetString createStr16(String str10) {
    String[] strs  = str10.split("");
    byte[] value = new byte[strs.length];
    for (int n = 0; n < strs.length; n++) {
        value[n] = (byte)Integer.parseInt(strs[n], 16);
    }
    return new OctetString(value);
}

在那之后,当我试图发送 v3 陷阱时,我得到了一个错误 SNMPv3_USM_UNKNOWN_SECURITY_NAME。然后我阅读了SNMP4J的源代码snmp.send(pdu, target),发现本地引擎ID应该与请求的AuthorativeEngineID相同,所以我继续设置本地引擎ID,如下所示,

snmp.setLocalEngine(authorativeEngineID.getValue(), 0, 0);  +
snmp.listen();

然后trap消息可以正常发送,但是192.168.1.92在engineID上还是匹配不上,详细日志如下(使用命令snmptrapd -f -d -Dusm -Lo查看日志):
注意:我的测试authorativeEngineID是0x8000000001020305,我的测试用户名是mytrapuser2

Received 559 byte packet from UDP: [xxxxxx]:xxxxx->[xxxxxx]:162
0000: 30 82 01 B0  02 01 03 30  11 02 04 6B  E7 AD 69 02    0......0...k..i.
0016: 03 00 FF FF  04 01 00 02  01 03 04 2B  30 29 04 10    ...........+0)..
0032: 08 00 00 00  00 00 00 00  00 01 00 02  00 03 00 05    ................
0048: 02 01 00 02  01 00 04 0B  6D 79 74 72  61 70 75 73    ........mytrapus
0064: 65 72 32 04  00 04 00 30  82 01 69 04  10 08 00 00    er2....0..i.....
...

usm: USM processing begun...
usm: match on user mytrapuser2
usm: no match on engineID (08 00 00 00 00 00 00 00 00 01 00 02 00 03 00 05 )
usm: Unknown User(mytrapuser2)
...

难道“08 00 00 00 00 00 00 00 00 01 00 02 00 03 00 05”不等于“0x8000000001020305”,所以出现了引擎ID不匹配的错误?我现在不确定,我会继续研究。

我的问题:
我不确定是否应该将本地引擎ID设置为0x80001370017f000101,如果不是,如何避免问题SNMPv3_USM_UNKNOWN_SECURITY_NAME?

Vicky 的问题的帮助下,我确实找到了问题所在。

我没有设置正确的ID,忘记在两个地方设置ID。

我在服务器端的引擎ID实际上是Mpv3.createLocaleEngineId()创建的程序localEngineID的前9个字节。

所以我实际上只是将 ID 子字符串化如下:

OctetString localEngineId = new OctetString(MPv3.createLocalEngineID()).substring(0, 9);

并在 addUser 部分添加 localEngineId 如下:

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

对于 snmp 引擎 id:

snmp.setLocalEngine(localEngineId.getValue(), 0, 0);

这解决了我的问题,消息记录在 snmptrapd 守护进程中。