Skip to content
Snippets Groups Projects
Commit 8166912c authored by Jakub Cegan's avatar Jakub Cegan
Browse files

(task #613) Warden Watchdog - 1. funkcni verze

Prvni funkcni verze kontroly klientu a udalosti v databazi. Staci nastavit v cronu a provadi predchystane kontroly a reportuje na zadane emaily.
parent 82dcf9ef
No related branches found
No related tags found
No related merge requests found
...@@ -7,20 +7,18 @@ ...@@ -7,20 +7,18 @@
# Use of this source is governed by a BSD-style license, see LICENSE file. # Use of this source is governed by a BSD-style license, see LICENSE file.
use WardenConf; #use WardenConf;
use strict; use strict;
use warnings; use warnings;
use DBI; use DBI;
use DBD::mysql; use DBD::mysql;
use DateTime; use DateTime;
#use Email::Simple; use Email::Simple;
use Sys::Hostname; use Sys::Hostname;
use Text::Wrap;
use Data::Dumper; use Data::Dumper;
sub sendmailWrapper{ sub sendmail_wrapper{
my $message = shift; my $message = shift;
if(open(my $sendmail, '|/usr/sbin/sendmail -oi -t')){ if(open(my $sendmail, '|/usr/sbin/sendmail -oi -t')){
print $sendmail $message; print $sendmail $message;
close $sendmail; close $sendmail;
...@@ -33,8 +31,7 @@ sub sendmailWrapper{ ...@@ -33,8 +31,7 @@ sub sendmailWrapper{
# Array of hashes # Array of hashes
#{query => ; text => ; contact => } #{query => ; text => ; contact => }
# Get clients admins sub send_report{
sub sendReport{
my $input_data = shift; my $input_data = shift;
my $contact = $$input_data{'contact'}; my $contact = $$input_data{'contact'};
...@@ -49,31 +46,28 @@ sub sendReport{ ...@@ -49,31 +46,28 @@ sub sendReport{
} }
$domain =~ s/\./\./; $domain =~ s/\./\./;
eval{ eval{
$from_hostname = hostname(); $from_hostname = hostname();
if(!($from_hostname =~ m/$domain/gi)){ if(!($from_hostname =~ m/^$domain$/gi)){
$from_hostname .= $domain; $from_hostname = $domain;
} }
}; 1;
if($@){ } or do {
return (0, "Can't retrive hostname for 'From' header!\n"); return (0, "Can't retrive hostname for 'From' header!\n");
} };
eval{ eval{
#$message = Email::Simple->create( $message = Email::Simple->create(
#header => [ header => [
#To => $contact, To => $contact,
#From => 'warden_watchdog@'.$from_hostname, From => 'warden_watchdog@'.$from_hostname,
#Subject => 'Kotrola stavu udalosti na Wardenu'], Subject => "Kotrola stavu udalosti warden serveru na stroji $domain"],
#body => fill('','',$text)); body => $text);
}; } or do {
if($@){
return (0, "Can't create email message\n"); return (0, "Can't create email message\n");
} };
print "== $contact ==\n$text\n"; my ($rc, $err) = sendmail_wrapper($message->as_string);
my ($rc, $err) = 1;#sendmailWrapper($message->as_string);
if(!$rc){ if(!$rc){
return (0, $err); return (0, $err);
} }
...@@ -100,7 +94,32 @@ sub connect_to_DB { ...@@ -100,7 +94,32 @@ sub connect_to_DB {
} }
} }
sub sendQuery{
sub update_procedures{
my $procRef = shift;
my @procedures = @{$procRef};
my $dbh;
# connect to DB
my ($rc,$err) = connect_to_DB(\$dbh);
if (!$rc){
return (0,'update_procedures can\'t connect do DB: '.$err);
}
foreach my $proc (@procedures) {
$dbh->do($proc);
}
# disconnect to DB
$dbh->disconnect;
return 1;
}
sub send_query{
my $configRef = shift; my $configRef = shift;
my $eventsRef = shift; my $eventsRef = shift;
...@@ -114,12 +133,10 @@ sub sendQuery{ ...@@ -114,12 +133,10 @@ sub sendQuery{
# connect to DB # connect to DB
($rc,$err) = connect_to_DB(\$dbh); ($rc,$err) = connect_to_DB(\$dbh);
if (!$rc){ if (!$rc){
return (0, $err); return (0,'send_query can\'t connect do DB: '.$err);
} }
while ($i < scalar(@config)) { while ($i < scalar(@config)) {
my $contact;
# run DB query -> requestor, client name # run DB query -> requestor, client name
my $sth; my $sth;
if (defined($config[$i]{query})){ if (defined($config[$i]{query})){
...@@ -134,15 +151,27 @@ sub sendQuery{ ...@@ -134,15 +151,27 @@ sub sendQuery{
}; };
my @result; my @result;
my $contact;
my $msg_text = 1;
while(@result = $sth->fetchrow()){ while(@result = $sth->fetchrow()){
if (defined($config[$i]{contact})){ if (defined($config[$i]{contact})){
$contact = $config[$i]{contact}; $contact = $config[$i]{contact};
if($msg_text){
$bad_events{$contact} .= $config[$i]{text} . "\n\n";
$msg_text = 0;
}
$bad_events{$contact} .= join(", ",@result) . "\n";
} }
else{ else{
$contact = "from_db\@$result[0]"; $contact = "from_db\@$result[0]";
$bad_events{$contact} .= $config[$i]{text} . "\n\n";
$bad_events{$contact} .= join(", ",@result) . "\n";
} }
$bad_events{$contact} .= $config[$i]{text} . "DB INFO: ". join(', ',@result) ."\n";
} }
foreach my $key (keys %bad_events){
$bad_events{$key} .= "\n\n";
}
$sth->finish; $sth->finish;
$i++; $i++;
} }
...@@ -166,40 +195,75 @@ sub run{ ...@@ -166,40 +195,75 @@ sub run{
my $dt = DateTime->now(); my $dt = DateTime->now();
$dt = DateTime->now()->subtract(days => $period); $dt = DateTime->now()->subtract(days => $period);
$date = $dt->date(); $date = $dt->date();
} or do {
#print "Warden watchdog - can't work with date\n";
syslog("err|Warden watchdog - can't work with date\n");
}; };
if($@){
print "Warden watchdog - can't work with date\n";
#syslog("err|Warden watchdog - can't work with date\n");
}
# stored procedures
# iptest - is ip from private network
my @procedures = ('DROP FUNCTION IF EXISTS iptest;', 'CREATE FUNCTION iptest(ip VARCHAR(15)) RETURNS TINYINT(1) DETERMINISTIC
BEGIN
SET @nip = INET_ATON(ip);
IF(
ISNULL( @nip) OR
@nip BETWEEN 0 AND 16777216 OR
@nip BETWEEN 167772160 AND 171966464 OR
@nip BETWEEN 2130706432 AND 2130706433 OR
@nip BETWEEN 2851995648 AND 2851995649 OR
@nip BETWEEN 2886729728 AND 2886729729 OR
@nip BETWEEN 3221225472 AND 3221225473 OR
@nip BETWEEN 3221225984 AND 3221225985 OR
@nip BETWEEN 3227017984 AND 3227017985 OR
@nip BETWEEN 3232235520 AND 3232235521 OR
@nip BETWEEN 3323068416 AND 3323068417 OR
@nip BETWEEN 3325256704 AND 3325256705 OR
@nip BETWEEN 3405803776 AND 3405803777 OR
@nip BETWEEN 3758096384 AND 3758096385 OR
@nip BETWEEN 4026531840 AND 4026531841 OR
@nip > 4294967295) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;');
# {query => ; text => ; contact => }
# Time of last event of each client.
# Is it unsupported type of event?
# Is event from the future?
# Martane - Is IP from the private network?
my @configuration = ( my @configuration = (
{query => "SELECT hostname, service, MAX(received) FROM events WHERE valid = 't' GROUP BY hostname, service ORDER BY MAX(received) ASC;", text => "Hey, this is test of warning for admin!\n"}, {query => "SELECT hostname, service, MAX(received) FROM events WHERE valid = 't' GROUP BY hostname, service ORDER BY MAX(received) ASC;", text => "Uvedeny klient, nebo klienti jiz delsi dobu nereportovali zadne udalosti do Wardenu. Je mozne, ze nefunguji spravne.", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'},
{query => "SELECT requestor FROM clients WHERE service IN (SELECT service FROM events WHERE detected > '$date' AND type NOT IN ('portscan', 'bruteforce', 'probe', 'spam', 'phishing', 'botnet_c_c', 'dos', 'malware', 'copyright', 'webattack', 'test', 'other') AND valid = 't' GROUP BY service) GROUP BY requestor;", text => "Hey, this is test of warning!\n", contact => 'warden-administrator@cesnet.cz'}); {query => "SELECT requestor FROM clients WHERE service IN (SELECT service FROM events WHERE detected > '$date' AND type NOT IN ('portscan', 'bruteforce', 'probe', 'spam', 'phishing', 'botnet_c_c', 'dos', 'malware', 'copyright', 'webattack', 'test', 'other') AND valid = 't' GROUP BY service) GROUP BY requestor;", text => "Uvedeny klient, nebo klienti zasilaji nepodporovany nebo zastaraly typ udalosti na server Warden", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'},
{query => "SELECT hostname, service, type, COUNT(*) FROM events WHERE detected - received > 0 AND received > '$date' GROUP BY hostname, service, type;", text => "Uvedeny klient, nebo klienti odesilaji odesilaji udalosti s casem z budoucnosti. Cas prirazeny serverem pri prichodu udalosti (received) musi byt vzdy roven nebo vetsi casu detekce (detected).", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'},
$Text::Wrap::columns = 80; {query => "SELECT hostname, service, received, source, count(source) AS c, min(received), max(received) FROM events WHERE valid = 't' AND source_type = 'IP' AND iptest(source) GROUP BY hostname, service, source ORDER BY c DESC;", text => "Uvedeni klient, nebo klienti odesilaji udalosti se zdrojovou adresou, ktera by se nemela objevit v internetu (privatni rozsah), nebo je neplatna (prazdny oktet, oktet je vetsi nez 255, apod.). kvuli omezeni verzi MySQL serveru funguje zatim pouze pro IPv6.", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'});
my ($rc,$err) = update_procedures(\@procedures);
if (!$rc){
#print "Warden watchdog - $err\n";
syslog("err|Warden watchdog - $err\n");
}
my %bad_events; my %bad_events;
my $i = 0; my $i = 0;
while ($i < scalar(@configuration)) { while ($i < scalar(@configuration)) {
my ($rc,$err) = sendQuery(\@configuration,\%bad_events); my ($rc,$err) = send_query(\@configuration,\%bad_events);
if (!$rc){ if (!$rc){
print "Warden watchdog - $err\n"; #print "Warden watchdog - $err\n";
#syslog("err|Warden watchdog - $err\n"); syslog("err|Warden watchdog - $err\n");
} }
$i++; $i++;
} }
while (my ($contact, $text) = each(%bad_events)){ while (my ($contact, $text) = each(%bad_events)){
my %input = (contact => $contact, domain => $domain, text => $text); my %input = (contact => $contact, domain => $domain, text => $text);
my ($rc,$err) = sendReport(\%input); my ($rc,$err) = send_report(\%input);
if (!$rc){ if (!$rc){
# TODO syslog #print $err;
print $err; syslog("err|Warden client - networkReporter $err\n");
#syslog("err|Warden client - networkReporter $err\n");
} }
print "\n\n";
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment