Wednesday, November 5, 2014

ELK: Анализ почтовых журналов. Подготовка

Продолжим тематику визуального анализа журналов. С журналов доступа в сеть Интернет переключимся на почтовые.
Начнем с получения журналов с почтового сервера и их подготовку к передаче ELK.
Так получилось, что в моей сети в качестве внутреннего почтового сервера используется Microsoft Exchange 2003. Каким-то неведомым мне образом, раз в сутки в почту падает файл с архивом почтового журнала сервера за предыдущий день. Мы пытались настоять на том, чтобы журналы отправлялись по протоколу syslog c помощью snare, но в этом было отказано под "уважительным" предлогом "высокой чувствительности пользователей к минимальным задержкам в работе сервиса".
Сначала письмо, как и множество других, проходит через procmail. Оно попадает под действие правила:
 :0:  
 * ^Subject(.*Exchange log file*)  
 {  
   :0 Bcw  
   | /home/sa/bin/logs/ExtractAttachment.pl  
   :0 a  
   | /home/sa/bin/logs/ImportMaillog.pl  
   :0  
   inbox/mailstat/.  
 }  

Скрипт "/home/sa/bin/logs/ExtractAttachment.pl" является вариантом этого скрипта.
За скрипт "home/sa/bin/logs/ImportMaillog.pl" не судите строго. Он писался в режиме "быстрее хоть что-нибудь" и сейчас исправлять его не хочется, потому-что "работает!".
 use strict;  
 use Encode qw(decode);  
 use Time::Local;  
 use Sys::Syslog;  
 use open qw(:std :utf8);  
 my $configfile = "/home/sa/bin/logs/rcfile";  
 my $conf = new Config::General("$configfile");  
 my %config = $conf->getall;  
 open (FILE, "<:encoding(utf8)", "/tmp/maillog.tmp") or die "Can't open file /tmp/maillog.tmp!\n";  
 open (OFILE, ">/tmp/maillog") or die "unable to open /tmp/maillog !";  
 openlog("Secure_Maillog", "ndelay", "local0");  
 while (<FILE>) {  
   s/\<\>/postmaster\@udmurtneft.ru/g;  
   my @str = split(/\t/);  
   my $str18 = "";  
   if ( $str[8] =~ /102[80]/ ) {  
      if ( $str[18] =~ /=?/ ) {  
        $str[18] =~ s/UNICODE-1-1-UTF-8/UTF-8/g;  
        $str[18] =~ s/unicode-1-1-utf-7/UTF-8/g;  
        $str[18] =~ s/x-user-defined/UTF-8/g;  
        $str[18] =~ s/gb18030/windows-1251/g;  
        $str[18] =~ s/window-1251/windows-1251/g;  
        $str[18] =~ s/UNKNOWN/windows-1251/g;  
        $str[18] =~ s/134/windows-1251/g;  
        my $flag = utf8::is_utf8($str[18]);  
           $str[18] = Encode::decode('MIME-Header',$str[18]);  
           $str18 = $str[18];  
      }  
      $str[1] =~ s/ GMT//g;  
      my $time = $str[0]." ".$str[1];  
      my @t = ($time =~ /^(\d{4})-(\d{1,2})-(\d{1,2})\s(\d{1,2}):(\d{1,2}):(\d{1,2})/);  
      $t[1]--; $t[3] = $t[3]+4;  
      if ( $t[3] > 23 ) { $t[3] = $t[3] - 24 };  
      my $timestamp = timelocal 0,@t[4,3,2,1,0];  
      print OFILE "\t$timestamp\t$str[19]\t$str[7]\t$str[12]\t$str[18] \n";  
      syslog('mail|info', $timestamp."\t".$str[19]."\t".$str[7]."\t".$str[12]."\t".$str[18]);  
   }  
 }  
 closelog();  
 close(OFILE);  
 system("mysqlimport --local logs /tmp/maillog --user=$config{db}->{user} --password=$config{db}->{password}");  
 unlink("/tmp/maillog.tmp");  
 unlink("/tmp/maillog");  
 unlink("/tmp/report.zip");  
Важные строки выделены жирным. Первая из них передает строку журнала в syslog, а оттуда в logstash. Вторая записывает в олдскульный sql для тяжелого анализа.
В следующий раз, чтобы разбавить тему анализа глазами. рассмотрим что можно достать из SQL.
PS. Если вы захотите отметить, что хранить временные файлы в общей директории /tmp не безопасно, то ответа будет два:
1. На сервере, куда падают журналы, все пользователи имеют доступ к ним.
2.
 $ cat /etc/profile | grep umask  
 umask 077  

No comments: