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?