У нас в сети, на доступе, используется большое количество коммутаторов D-Link.
Назрела необходимость принимать SNMP-трапы. Но оказалось не всё так просто, потому что огромное количество коммутаторов были из серий DES-1228/1210-28/1210-52. Эти коммутаторы вроде и умеют отправлять трапы, но вот сервер никак не хотел их ловить. Оказалось что трапы умеет ловить исключительно приложение под Windows, и название ему — Smart Console Utility.
Т.е. автоматизировать процесс сбора трапов, по задумке вендора, никак не получится.
Однако, пакеты с SNMP-трапами, все-таки на трап-сервер идут и с этим надо что-то делать.
Недолго думая, подняли на трап-сервере xinetd и начали принимать пакеты с сообщениями. Приходили они на UDP-порт 64514. И что было удивительно и интересно — сообщения шли в конце пакета, прямым текстом, нужно лишь было обрезать бинарные не читаемые заголовки.
Кстати, inetd/xinetd еще называют «супер-сервером Интернет», это такой сетевой сервис, который слушает сокеты и приходящие сетевые пакеты отправляет твоему приложению для анализа/сохранения/ и вообще для чего угодно. Т.е. в *nix системе можно «голыми руками» написать свой сетевой сервис. Это поистине круто!
Конфигурация xinetd (/etc/xinetd.d/trap-handler-scu):
service smart-console-utility
{
disable = no
id = trap-handler-scu
type = UNLISTED
flags = IPv4
protocol = udp
socket_type = dgram
user = root
wait = yes
server = /services/snmp/trap-handler-scu.php
port = 64514
# log_type = FILE /var/log/xinetd-trap-handler-scu.log
# log_on_success = PID HOST
# log_on_failure = HOST
}
Код, которому будет передаваться каждый пришедший UDP-пакет (/services/snmp/trap-handler-scu.php):
Написан на PHP, т.к. выполняется быстро, и после ему можно придать возможность складывать трап-сообщения в БД.
#!/usr/bin/php5
<?php
set_time_limit(5);
error_reporting(0);
$logging = true; // Global logging
$debug_logging = false; // Logging debug messages
$dump_requests = false; // Save requests
$request_buffer_size = 1024; // 1024 Bytes - Maximum request size
$log_file = '/var/log/smart-console-utility/smart-console-utility.log';
$req_id = preg_replace(array('/./', '/(-)([0-9]{1}$)/', '/(-)([0-9]{2}$)/', '/(-)([0-9]{3}$)/'), array('-', '$1---$2', '$1--$2', '$1-$2'), array_sum(explode(' ', microtime())));
$dump_dir = '/tmp/smart-console-utility';
$dump_request_file = $dump_dir.'/'.$req_id.'.request';
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function write_log($message)
{
global $log_file, $logging, $req_id;
if ($logging)
{$logging = (file_put_contents($log_file, date('Y-m-d H:i:s ').'['.$req_id.' '.sprintf('%-14s', $_SERVER['REMOTE_HOST']).'] '.$message."n", FILE_APPEND) !== false);}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if ($debug_logging) {write_log('Start');}
if ($read_handle = fopen('php://stdin', 'r'))
{
if (($dump_requests) && (!is_dir($dump_dir)))
{
mkdir($dump_dir, 644, true);
$dump_requests = is_dir($dump_dir);
}
// Read client request
if ($request = fread($read_handle, $request_buffer_size))
{
// Get trap message
preg_match('/[wds-().]+$/', $request, $matches);
if ($matches)
{
$trap_message =
preg_replace(array('/([d]+)/', '/[.]+$/'), '',
preg_replace('/[ ]{2,}/', ' ',
preg_replace('/^.DES/', 'DES',
trim(end($matches))
)
)
);
} else {$trap_message = '';}
if ($logging) {write_log($trap_message);}
if ($debug_logging) {write_log('Handle request, size('.strlen($request).")t-> ".$trap_message);}
if ($dump_requests) {file_put_contents($dump_request_file, $request, FILE_APPEND);}
// Parse trap message
}
else
{write_log('Null request');}
fclose($read_handle);
}
else
{write_log('Unable to open STDIN!');}
if ($debug_logging) {write_log('End');}
?>
В результате получатся приблизительно такие записи в журнале:
2014-09-12 06:25:50 SCU--1410485150-0287 10.X.0.26 DES-1210-28 Port 2 copper link up
2014-09-12 06:25:50 SCU--1410485150-3536 10.X.0.18 DES-1210-52 Port 9 copper link up
2014-09-12 06:25:50 SCU--1410485150-7605 10.X.0.31 DES-1210-52 Port 48 copper link up
2014-09-12 06:25:52 SCU--1410485152-9745 10.X.0.104 DES-1210-28 Port 10 copper link up
2014-09-12 06:25:55 SCU--1410485155-5064 10.X.0.11 DES-1210-52 Port 28 copper link up
2014-09-12 06:25:55 SCU--1410485155-7615 10.X.0.31 DES-1210-52 Port 48 copper link up
2014-09-12 06:25:58 SCU--1410485158-7782 10.X.0.31 DES-1210-52 Port 48 copper link up
2014-09-12 06:26:01 SCU--1410485161-4395 10.X.0.31 DES-1210-52 Port 48 copper link up
2014-09-12 06:26:04 SCU--1410485164-0377 10.X.0.31 DES-1210-52 Port 48 copper link up
2014-09-12 06:26:04 SCU--1410485164-3473 10.X.0.18 DES-1210-52 Port 9 copper link up
2014-09-12 06:26:06 SCU--1410485166-0395 10.X.0.31 DES-1210-52 Port 48 copper link up
2014-09-12 06:26:07 SCU--1410485167-1539 10.X.0.31 DES-1210-52 Port 47 copper link up
2014-09-12 06:26:07 SCU--1410485167-2226 10.X.0.128 DES-1210-28 Port 2 copper link up
Кстати, в данном выводе видно «схлопывание» порта (port-flapping), строчка «DES-1210-52 Port 48 copper link up» повторяется много раз. Она показывает что с портом или кабелем что-то не так.
Дефект на порту найден — задача выполнена.
Автор: ThreeDHead