SNMP4J V3 Trap с AuthPriv не обрабатывается

Я пытаюсь создать агент SNMP TRAP/Notify в Java, используя SNMP4J. Ловушки / уведомления предназначены для отправки удаленному слушателю.

Я хотел бы добавить поддержку ловушек V2 и V3 с аутентификацией.

Моя настройка в настоящее время:

  • Dev машина работает с уведомителем. (192.168.1.61)

  • ВМ на Debian 9(Stretch) (192.168.1.92) работает с snmptrapd

Моя проблема описана вкратце:

  • Сообщения V2 работают.
  • Сообщения V3 принимаются, но не обрабатываются при отправке с Java.

Я попробовал свои настройки с помощью следующей команды, подтвердив, что она работает:

VM:

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

Dev:

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

На виртуальной машине он генерирует это сообщение журнала:

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

Теперь я запустил следующий код и подтвердил его поступление на виртуальную машину (запустил команду snmptrapd с включенной опцией -d, чтобы увидеть, что пакет 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.

Я также пытался заменить MPv3.createLocalEngineId() с фактическим идентификатором двигателя, но это, похоже, тоже не помогло.

Я Wiresharked оба запроса (из JAVA и из snmp-trap) и единственное отличие, которое я заметил, заключается в том, что они оба имеют разные AuthorativeEngineID.

У Java был сгенерированный, поскольку он отличается в каждом запросе, у snmp-trap есть статический.

Что я делаю неправильно?

2 ответа

Решение

С помощью вопроса Vicky я фактически идентифицировал проблему.

Я не устанавливал правильный идентификатор и забыл установить идентификатор в двух местах.

Мой идентификатор движка на стороне сервера - это первые 9 байт программ localEngineID, созданных Mpv3.createLocaleEngineId(),

Так что я на самом деле просто подставил идентификатор следующим образом:

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

И добавил localEngineId в части addUser следующим образом:

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

И для идентификатора двигателя snmp:

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

Это исправило мою проблему и сообщение вошло в snmptrapd демон.

Можете ли вы приложить подробные журналы о поступившем пакете snmp?

Я думаю, что пользователь "o2m-user" был создан с AuthorativeEngineID 0x80001370017f000101 192.168.1.92, поэтому я попытался отправить сообщение с ним.

Итак, я обновил

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) и обнаружил, что идентификатор локального механизма должен совпадать с запрошенным AuthorativeEngineID, поэтому я могу установить идентификатор локального механизма, как показано ниже:

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

Тогда сообщение прерывания может быть отправлено без какой-либо ошибки, но 192.168.1.92 все еще не может соответствовать по engineID, подробные журналы приведены ниже (для просмотра журнала используйте команду snmptrapd -f -d -Dusm -Lo):
ПРИМЕЧАНИЕ. Мой тестовый authorativeEngineID - 0x8000000001020305, мой тестовый пользователь - my trapuser2.

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", поэтому не произошло совпадения по идентификатору EngineID? Я не уверен сейчас, я буду продолжать изучать это.

Мои вопросы:
Я не уверен, стоит ли устанавливать идентификатор локального движка как 0x80001370017f000101, если нет, как избежать проблемы SNMPv3_USM_UNKNOWN_SECURITY_NAME?

Другие вопросы по тегам