rdrcollector/cgi/loginsearch

289 lines
12 KiB
Plaintext
Raw Permalink Normal View History

2021-01-15 18:43:34 +03:00
#!/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 "<table width=100%><tr><td width=10%><img src=/logo.gif></td><td width=90% align=center><h2>Поиск сессий абонента по имени пользователя</h2></td></tr></table>\n";
print "<hr>\n";
print_prompt();
do_work();
print_tail();
read_protocol();
print end_html;
#########################################################################
# описание процедур
#########################################################################
# вывод формы с полями
sub print_prompt {
print start_form;
print "<p><table><tr><td><em>Дата (ДД.ММ.ГГГГ)</em></td>";
print "<td>".textfield('date')."</td></tr>";
print "<tr><td><em>Имя пользователя</em></td>";
print "<td>".textfield('login')."</td>";
print "</tr></table>";
#print "<td><ifarme name=userdata width=468 height=60 align=left>sss</iframe></td></tr></table>";
# print "<p>",reset;
print submit('Action','Выполнить');
print end_form;
print "</p><hr>\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 "<font color=red size=5>Введите имя пользователя</font>";
exit;
}
if ($date eq "" || $date == 0)
{
print "<font color=red size=5>Необходимо корректно ввести дату</font>";
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 "<font color=red size=5>Введите корректный IP адрес</font>";
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 в архиве не найдены производится поиск за последние сутки<br>";
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 "<h4>Список TCP/IP сессий c адреса ".$src." за ".$date."</h4>";
# заголовок таблицы
print "<table width=100%><tr bgcolor=#78ceff><td align=center>Дата</td><td align=center>Абонент</td><td align=center>IP клиента</td><td align=center>IP сервера</td><td align=center>Трафик вх/исх</td><td>Протокол</td><td align=center>Информация</td></tr>";
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 <br>";
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 "<tr bgcolor=$bgcolor><td width=10%><font size=2>$date_time</td>";
print "<td width=20%><font size=2><a href=/cgi-bin/usersearch?ip=".$user_ip."&day=".$day."&month=".$month."&year=".$year."&t=".$t." target=userdata>$client</td>";
print "<td width=10%><font size=2>$client_ip</td><td width=10%><font size=2>$server_ip</td><td width=10%><font size=2>$up_down</td><td width=20%><font size=2>$protocol</td><td><font size=2>$info_string</td></tr>\n";
$i++;
# }
}
# exit;
}
print "<tr bgcolor=#78ceff><td><font size=2><b>Всего трафика</b></font></td><td></td><td></td><td></td><td width=10%><font size=2><b>$session_up / $session_down</b></td><td width=20%><font size=2></td><td><font size=2></td></tr>\n";
print "</table>";
}
sub print_tail {
print "<hr><div align=center> &copy 2015, OOO \"Терион\"</div>";
}
# читаем файл с описанием протокола
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 "<p>Договор - <b>$contract</b></p>\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 "<p>Найдено записей - ".$sth->rows."</p>";
# получаем данные запроса форматируем и выводим на экран
while (($title, $login, $ip, $start, $stop) = $sth->fetchrow_array())
{
if ($stop eq "")
{
$stop = $date_end;
}
#print "Договор - <b><i>$title</i></b><br>Имя пользователя - <b><i>$login</i></b><br>IP - <b><i>$ip</i></b><br>Cессиия - <b><i>$start - $stop</i></b><br>";
print "<p>IP - <b><i>$ip</i></b><br>Cессиия - <b><i>$start - $stop</i></b></p>";
# запускаем процедуру поиска сессий в файла RDR коллектора
ip_search($date, $start, $stop, $ip);
}
$sth->finish();
# Отцепляемся от БД
$dbh->disconnect();
}