wtorek, 29 czerwca 2010

Automatyczne śledzenie logów

Sesja, sesja, i po sesji. Na jednych zajęciach miałem okazję opiekować się serwerem z zainstalowanym ubuntu, który - między innymi - miał informować o udanych lub nie próbach wejściach do systemu.

W Linuxie stosowne informacje i tak już są zapisywane w logach, a konkretnie w /var/log/auth.log. Tam można zobaczyć dla kogo została otwarta sesja, lub kiedy autentyfikacja się nie powiodła (został podany zły logpass). Mnie interesowało zautomatyzowanie procesu analizowanie tego pliku, więc jak prawdziwy unixowy żółtodziób zacząłem googlać gotowych rozwiązań. Znalazłem skrypt w perlu, który wedle opisu miał robić dokładnie to co chciałem: wykrywał dopisania linii z poszukiwaną frazą, jednak oczywiście praktyka a teoria to dwa różne światy.
Źródła tamtego rozwiązania niestety nie zapisałem, a teraz szybkie wyszukiwania nie pozwoliły mi go odnaleźć. Cóż, teraz wiem jakich słów kluczowych używać, wtedy wpisywałem zapewne różne dziwne rzeczy w biednego wujka Google :)

Tak czy siak, zabrałem się za modyfikację kodu do moich potrzeb. Perla (oczywiście) w ogóle nie znałem i skłamałbym mówiąc, że się to zmieniło, ale mimo to wyprodukowałem poniższy kod:


#!/usr/bin/perl
my $output = 0;
while ( 1 )
{ 
    system('logtail -f /var/log/auth.log | tee -a ./tmpFile ./tmpFile2');
    system('rm ./output');
    system('rm ./output2');
    system('cat ./tmpFile | grep [fF]ailure | wc -l > ./output');
    open(FILE, "<output");
    $output = <FILE>;
    if ($output > 0)
    {
        system('mailx -s "authentication failed" adres@odbiorcy < ./mail.mail');
        system ('/bin/cat /dev/null > ./tmpFile');    
    }
    close FILE;
    
    system('cat ./tmpFile2 | grep Accepted | wc -l > ./output2');
    open(FILE, "<output2");
    $output = <FILE>;
    if ($output > 0)
    {
        system('mailx -s "session opened" adres@odbiorcy < ./mail.mail');
        system ('/bin/cat /dev/null > ./tmpFile2');    
    }
    close FILE;
    sleep 5;
}
Program opiera się na zasadniczo na bashowej komendzie logtail. Skrypt zapisuje ostatnie nowe linie do dwóch plików, a następnie przeszukuje, czy w pierwszym z nich znajduje się słowo "failure" - którego obecność jest praktycznie jednoznaczna z czyimś nieudanym logowaniem. Wynik działania (0, lub znalezione linie) jest zapisywane do pliku. Jeśli w pliku jest coś więcej niż 0, wtedy wysyłamy maila. Dalej analogicznie postępujemy aby wykryć udane logowania. Następnie śpimy pięć sekund i proces się powtarza.

Oczywiście, tworzenie tmpFile i tmpFile2 jest redundantne, wystarczyłoby się ograniczyć do jednego pliku. Taka postać wynika niestety z zastosowanej metody prób i błędów. Tak samo można wątpić, czy konieczne jest zapisywanie wyników grep'a do pliku.

Skrypt wykorzystuje mailx'a, co oznacza, że w systemie musi być skonfigurowana skrzynka pocztowa zdolna do wysyłania maili. Plik mail.mail zawiera treść wysyłanej wiadomości. Przez wysyłanie maili na adres z włączoną usługą powiadamianiem smsem o temacie nowej wiadomości, można łatwo uzyskać powiadomienia na komórkę. (Ja użyłem skrzynki plusnet.pl - usługa kosztowała jednokrotnie 5 złotych).

Skrypt odpalałem przez jednolinijkowy skrypt basowy IDS.sh:
./getauth.pl > /dev/null 2>&1 &

A ponieważ korzystałem z serwera przez ssh i zależało mi, aby skrypt działał po moim wylogowaniu, użyłem narzędzia nohup.