#!/usr/bin/perl ######################################################################### # # CGI скрипт для поиска и визуализации данных собранных rdrcollector-ом # по логину абонента # # Автор: Сергей Калинин e-mail: banzaj28@yandex.ru # распространяется под лицензией GPL # (c) 2015 ######################################################################### use CGI ':standard'; use DBI; use Time::Local; # Вывод заголовка print header(-type=>'text/html', -charset=>'utf-8'); print start_html("Поиск сессий абонента по имени пользователя"); print "

Поиск сессий абонента по имени пользователя

\n"; print "
\n"; print_prompt(); do_work(); print_tail(); read_protocol(); print end_html; ######################################################################### # описание процедур ######################################################################### # вывод формы с полями sub print_prompt { print start_form; print "

"; print ""; print ""; print ""; print "
Дата (ДД.ММ.ГГГГ)".textfield('date')."
Имя пользователя".textfield('login')."
"; #print "sss"; # print "

",reset; print submit('Action','Выполнить'); print end_form; print "


\n"; } # проверка корректности даты sub match_date { my $input = shift; if ($input =~ m!^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$!) { # At this point, $1 holds the year, $2 the month and $3 the day of the date entered if ($3 == 31 and ($2 == 4 or $2 == 6 or $2 == 9 or $2 == 11)) { return 0; # 31st of a month with 30 days } elsif ($3 >= 30 and $2 == 2) { return 0; # February 30th or 31st } elsif ($2 == 2 and $3 == 29 and not ($1 % 4 == 0 and ($1 % 100 != 0 or $1 % 400 == 0))) { return 0; # February 29th outside a leap year } else { return $input; # Valid date } } else { return 0; # Not a date } } sub do_work { my $key; my $cmd; # получаем данные введённые в форме # и проверяем формат my $date = match_date(param(date)); my $login = param(login); my $contract = param(contr); # если данные введены не верно выводим сообщение chomp $login; if ($login eq "") { print "Введите имя пользователя"; exit; } if ($date eq "" || $date == 0) { print "Необходимо корректно ввести дату"; exit; } login_search($date, $login, $contract) } sub ip_search { my $key; my $cmd; # получаем данные введённые в форме # и проверяем формат my $date = $_[0]; my ($date_start, $t_start) = split (" ", $_[1]); my ($date_stop, $t_stop) = split (" ", $_[2]); my $src = $_[3]; my $dst; # Преобразуем дату и время в unixtime # начало сессии my ($hour, $min, $sec) = split(':',$t_start); my ($year, $month, $day) = split('-',$date_start); my $time_start = timelocal($sec,$min,$hour,$day,$month,$year)."\n"; # конец сессии ($hour, $min, $sec) = split(':',$t_stop); ($year, $month, $day) = split('-',$date_stop); my $time_stop = timelocal($sec,$min,$hour,$day,$month,$year)."\n"; # если данные введены не верно выводим сообщение if ($dst eq 0 || $src eq 0) { print "Введите корректный IP адрес"; exit; } # формируем каталог для поиска в соответствии с датой my ($dday,$dmonth,$dyear) = split(/\./,$date); my $dir = "/var/srv/rdrcollector/$dyear/$dmonth/$dday"; # формируем команду поиска данных в зависимости от даты и IP адресов (1 или 2 адреса) # определяем каталог в архиве и если он есть ищем данные в файлах этого каталога # если такого каталога нет - поиск производится в кэше. if (-d $dir) { if ($dst eq "") { $cmd = "/usr/bin/gzip -c -d ".$dir."/*.gz | /usr/bin/grep -h ".$src."@"; } else { $cmd = "/usr/bin/gzip -c -d ".$dir."/*.gz | /usr/bin/grep -h ".$src."@ | /bin/grep ".$dst; } } else { print "Данные за $date в архиве не найдены производится поиск за последние сутки
"; if ($dst eq "") { $cmd = "/usr/bin/grep -h ".$src."@ /var/cache/rdrcollector/*"; } else { $cmd = "/usr/bin/grep -h ".$src."@ /var/cache/rdrcollector/* | /usr/bin/grep ".$dst; } } # выполняем команду поиска и выводим данные ввиде html-таблицы #print "

Список TCP/IP сессий c адреса ".$src." за ".$date."

"; # заголовок таблицы print ""; my $i = 0; my $bgcolor; my $session_up; my $session_down; # команда выполняется и результат обрабатывается циклом foreach my $lines (`$cmd`) { my $expr = $i % 2; # чередование цвета фона строк для чётных и не чётных if ($expr eq 0) { $bgcolor = "#fffff"; } else { $bgcolor = "#c5eaff"; } # разбиваем строку на поля для удобства вывода. my ($date_time, $client, $client_ip, $server_ip, $up_down, $protocol_sign) = split(/\t/, $lines); # определяем IP абонента my ($user_ip, $group) = split("@", $client); # проверка на пустое поле даты или идетнификатора абонента # бывают покоцанные файлы if ($date_time eq "" || $client eq "") { next; } # преобразуем дату время найденного соединения в unixtime my ($t, $date) = split(" ", $date_time); ($day, $month, $year) = split(/\./,$date); ($hour, $min, $sec) = split(':',$t); #print "$date_time - $hour $min $sec $day $month $year
"; my $time = timelocal($sec, $min, $hour, $day, $month, $year); # сравниваем дату и время TCP/IP сессии с датой и временем сессии абонента в биллинге # и если она входит в диапазон, выводим на экран if ($time > $time_start && $time < $time_stop) { # отбрасываем записи о "пустых" соединениях # if ($client_ip ne ":" || $server_ip ne ":") { # считаем трафик my ($up, $down) = split("/", $up_down); $session_up += $up; $session_down += $down; # определяем название протокола по его подписи $protocol = read_protocol("$protocol_sign"); # вводим данные print ""; print ""; print "\n"; $i++; # } } # exit; } print "\n"; print "
ДатаАбонентIP клиентаIP сервераТрафик вх/исхПротоколИнформация
$date_time$client$client_ip$server_ip$up_down$protocol$info_string
Всего трафика$session_up / $session_down
"; } sub print_tail { print "
© 2015, OOO \"Терион\"
"; } # читаем файл с описанием протокола sub read_protocol { #print $_[0]; $cmd = "/usr/bin/grep -h \'".$_[0]."\' /usr/local/etc/protocol.csv"; my $lines = `$cmd`; #print "$lines"; if ($lines) { my ($prot, $signature) = split(";", $lines); return $prot; } else { return $_[0]; } } # поиск данных в БД биллинга sub login_search { my $login = param(login); my $date = param(date); my $contract = param(contr); if ($contract ne "") { print "

Договор - $contract

\n"; } my ($day,$month,$year) = split(/\./, $date); # определяем имя таблицы с сессиями my $table = "inet_session_log_1_".$year."".$month; # конектимся к GLPI базе. my $dsn = 'DBI:mysql:bgbilling:192.168.1.250'; my $db_user_name = 'netflow'; my $db_password = 'Cbcntvfnbpfwbz112318'; my ($id, $password); my $dbh = DBI->connect($dsn, $db_user_name, $db_password); # форматируем дату для запроса my $date_begin = $year."-".$month."-".$day." 00:00:00"; my $date_end = $year."-".$month."-".$day." 23:59:59"; # формируем SQL запрс my $sth = $dbh->prepare(qq{select c.title, serv.login, INET_NTOA(CONV(HEX( session.ipAddress ), 16, 10)) as ip, session.sessionStart, session.sessionStop from inet_serv_1 serv left join $table session on serv.id = session.servid left join contract c on c.id = serv.contractid LEFT outer JOIN inet_serv_1 as parentServ ON serv.parentId>0 AND serv.parentId=parentServ.id where serv.contractid <> '2' and serv.login = '$login' AND session.parentId=0 and session.sessionStart >= '$date_begin' AND session.sessionStart <= '$date_end'}); # Выполняем запрос к БД $sth->execute(); # если в предыдущем запорсе ничего не найден обращаемся к таблице с активными сессиями if ($sth->rows == 0) { $sth = $dbh->prepare(qq{select c.title, i_c_1.username, INET_NTOA(CONV(HEX( i_c_1.ipAddress ), 16, 10)) as ip , session.sessionstart, session.sessionstop from inet_connection_1 i_c_1 join inet_session_1 session on session.connectionid = i_c_1.id join inet_serv_1 i_s_1 on i_s_1.id = i_c_1.servid join contract c on c.id = i_s_1.contractid where i_c_1.parentid = 0 and i_c_1.username = '$login' and session.sessionStart >= '$date_begin'}); $sth->execute(); } print "

Найдено записей - ".$sth->rows."

"; # получаем данные запроса форматируем и выводим на экран while (($title, $login, $ip, $start, $stop) = $sth->fetchrow_array()) { if ($stop eq "") { $stop = $date_end; } #print "Договор - $title
Имя пользователя - $login
IP - $ip
Cессиия - $start - $stop
"; print "

IP - $ip
Cессиия - $start - $stop

"; # запускаем процедуру поиска сессий в файла RDR коллектора ip_search($date, $start, $stop, $ip); } $sth->finish(); # Отцепляемся от БД $dbh->disconnect(); }