Первый шаг довольно очевиден. Необходимо получить дамп сетевой активности во время максимальной нагрузки на RADIUS-сервер. Данных 10-15 минутного интервала вполне достаточно для анализа. Для Unix-like систем получить эти данные можно при помощи tcpdump, но поскольку, в нашем случае, RADIUS-сервер работал на Windows-системе, пришлось прибегнуть к помощи Wireshark. Выполнив захват пакетов, Wireshark показал эту замечательную картинку:
Хотя этот интерфейс очень удобен для интерактивной работы, для получения статистики, требуется перевести данные в форму более удобную для автоматизированной обработки. К счастью, Wireshark умеет сохранять данные в текстовый формат:
Результирующий файл выглядит следующим образом:
+---------+---------------+----------+ 10:03:59,092,544 ETHER |0 |ff|ff|ff|ff|ff|ff|00|0c|29|6b|5a|a3|08|00|45|00|00|e5|b6|15|00|00|80|11|04|d4|c0|a8|7d|ce|c0|a8|7f|ff|00|8a|00|8a|00|d1|ee|a9|11|0e|d1|fb|c0|a8|7d|ce|00|8a|00|bb|00|00|20|46|44|46|41|44|44|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|00|20|45|4a|45|4f|46|45|45|46|46|43|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|43|41|42|4e|00|ff|53|4d|42|25|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|11|00|00|21|00|00|00|00|00|00|00|00|00|e8|03|00|00|00|00|00|00|00|00|21|00|56|00|03|00|01|00|00|00|02|00|32|00|5c|4d|41|49|4c|53|4c|4f|54|5c|42|52|4f|57|53|45|00|01|00|80|fc|0a|00|53|50|33|00|25|03|00|00|00|00|fc|5e|20|03|02|00|05|01|03|12|01|00|0f|01|55|aa|00| +---------+---------------+----------+ 10:03:59,184,049 ETHER |0 |ff|ff|ff|ff|ff|ff|00|1d|7d|3a|f9|3a|08|06|00|01|08|00|06|04|00|01|00|1d|7d|3a|f9|3a|0a|15|52|44|00|00|00|00|00|00|0a|15|52|41|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00| ...
С этим уже можно работать. Из спецификаций RFC 768, 2865, 2866 нам известны смещения интересующих нас полей (смещения представлены в десятеричной системе счисления, значения — в шестнадцатеричной):
+23 = 11 (UDP) +36 = 07 14 (RADIUS Destination Port = 1812) +42 - (01 = Access Request) +43 - ID +34 = 07 14 (RADIUS Source Port = 1812) +42 - (02 = Access Accept; 03 = Access Reject) +43 - ID +36 = 07 15 (RADIUS Destination Port = 1813) +42 - (04 = Accounting Request) +43 - ID +34 = 07 14 (RADIUS Source Port = 1812) +42 - (05 = Accounting Response) +43 - ID
Обработать данные нам поможет Perl:
use Time::Local; my $tm; my $ln; my %auth; my %acco; my %discarded; my %accepted; # Обрабатываем все поступающие строки while (<>) { # Убираем перевод строки chomp; s/\|0\s+\|//; # Регулярным выражением извлекаем время if (/^(\d\d):(\d\d):(\d\d),(\d\d\d),\d\d\d/) { # Приводим значение времени к количеству миллисекунд с начала эпохи # Поскольку дата нас не интересует, берем 01/01/1970 $tm = timelocal($3, $2, $1, 01, 01, 1970) * 1000 + $4; } if (/\|/) { $ln .= $_; } else { if ($ln) { # Разбиваем строку на байты my @packet = split /\|/, $ln; # Нас интересуют только UDP-пакеты if ($packet[23] eq '11') { my $code = $packet[42]; my $id = $packet[43]; # RADIUS Request if ($packet[36] eq '07' and ($packet[37] eq '14' or $packet[37] eq '15')) { # Аккаутинг if ($code eq '04') { # Повтор ID запроса означает потерю соответствующего ответа if (exists($acco{%id})) { $discarded{$code}++; } # Сохраняем время получения запроса $acco{%id} = $tm; # Авторизация } else { if (exists($auth{%id})) { $discarded{$code}++; } $auth{%id} = $tm; } } # RADIUS Response if ($packet[34] eq '07' and ($packet[35] eq '14' or $packet[35] eq '15')) { # Аккаутинг if ($code eq '05') { if (exists($acco{%id})) { if ($tm - $acco{%id} > 1000) { # Если прошло более 1 секунды, считаем пакет отброшенным $discarded{$code}++; } else { # Иначе увеличиваем количество успешно обработанных пакетов $accepted{$code}++; } delete($acco{%id}); } # Авторизация } else { if (exists($auth{%id})) { if ($tm - $auth{%id} > 1000) { $discarded{$code}++; } else { $accepted{$code}++; } delete($auth{%id}); } } } } $ln = ''; } } } # На всякий случай, учитываем ID, для которых не сформирован ответ while (($id, $tm) = each(%auth)) { $discarded{'01'}++; } while (($id, $tm) = each(%acco)) { $discarded{'04'}++; } #Выводим результаты обработки print "Auth Accepted: $accepted{'02'}\n"; print "Auth Rejected: $accepted{'03'}\n"; print "Acco Responsed: $accepted{'05'}\n\n"; print "Auth Request Discarded: $discarded{'01'}\n"; print "Auth Accept Discarded: $discarded{'02'}\n"; print "Auth Reject Discarded: $discarded{'03'}\n"; print "Acco Request Discarded: $discarded{'04'}\n"; print "Acco Response Discarded: $discarded{'05'}\n";
Поскольку мы все еще работаем в Windows, bang-комментарий в исходном коде не обязателен (кстати, Perl для Windows можно взять здесь). Для работы со временем, не забываем подключить Time::Local. Скрипт запускаем на выполнение следующей командой:
perl stat.pl dump.txt > dump
Скрипт работает довольно долго (в основном из-за split-а большого объема данных), но один раз можно и потерпеть. В конечном итоге, формируется следующий результат:
Auth Accepted: 195 Auth Rejected: 907 Acco Responsed: 6058 Auth Request Discarded: 13 Auth Accept Discarded: Auth Reject Discarded: Acco Request Discarded: 1476 Acco Response Discarded:
Здесь мы видим, что за 10 минут было успешно обработано 6058 пакетов аккаунтинга и 1102 пакетов авторизации (из них на 907 запросов был сформирован Reject). Все запросы были обработаны сервером не более чем за 1 секунду. По непонятной причине, NAS отослал 13 повторных запросов авторизации и 1476 запросов аккаунтинга. Возможно это связано с потерями UDP-пакетов при передаче их по сети.
Приведенный выше скрипт можно улучшить, для получения более детальной статистики по времени отклика, но в целом задачу можно считать выполненной. RADIUS-сервер работает нормально.
ссылка на оригинал статьи http://habrahabr.ru/post/191720/
Добавить комментарий