Compare commits

...

4 Commits

9 changed files with 56 additions and 50 deletions

View File

@ -18,22 +18,22 @@ sub add {
my $self = shift;
my $params = shift;
die "No params" unless $params;
$self->{'config'}->db_connect();
$self->{'dbh'} = $self->{'config'}->get_dbh unless($self->{'dbh'});
my $dbh = $self->{'config'}->db_connect();
my $return = {};
$return = $self->addtoblacklist($params) if($params->{'list'} eq 'black');
$return = $self->addtorejectlist($params) if($params->{'list'} eq 'reject');
$return = $self->addtoblacklist($dbh, $params) if($params->{'list'} eq 'black');
$return = $self->addtorejectlist($dbh, $params) if($params->{'list'} eq 'reject');
return $return;
}
sub addtoblacklist {
my $self = shift;
my $dbh = shift;
my $work = shift;
my $host = $work->{'host'};
my $asn = $work->{'asn'} || 0;
my $iso = $work->{'iso'} || '';
return { retval => 0, retmsg => "No host specified" } unless($host);
my $sth = $self->{'dbh'}->prepare("
my $sth = $dbh->prepare("
SELECT COUNT(*)
FROM reject_iptables
WHERE ip = ? AND
@ -41,7 +41,7 @@ sub addtoblacklist {
$sth->execute($host);
my $rows = $sth->fetchrow_arrayref->[0];
unless($rows) {
my $sth = $self->{'dbh'}->prepare("INSERT INTO reject_iptables(ip,asn,iso) VALUES(?,?,?)") || return { retval => 0, retmsg => 'Failed to prepare statement in addtoblacklist '.DBI::errstr };
my $sth = $dbh->prepare("INSERT INTO reject_iptables(ip,asn,iso) VALUES(?,?,?)") || return { retval => 0, retmsg => 'Failed to prepare statement in addtoblacklist '.DBI::errstr };
$sth->execute($host,$asn,$iso) || return { retval => 0, retmsg => 'Failed to execute statement in addtoblacklist '.DBI::errstr };
system "/sbin/pfctl -q -t $self->{'block_table'} -T add $host";
system "/sbin/pfctl -q -k $host";
@ -54,13 +54,14 @@ sub addtoblacklist {
sub addtorejectlist {
my $self = shift;
my $dbh = shift;
my $work = shift;
my $host = $work->{'host'};
my $service = $work->{'service'} || '';
my $asn = $work->{'asn'} || 0;
my $iso = $work->{'iso'} || '';
return { retval => 0, retmsg => "No host specified" } unless($host);
my $sth = $self->{'dbh'}->prepare("INSERT INTO reject(ip,service,asn,iso) VALUES(?,?,?,?)") || return { retval => 0, retmsg => 'Failed to prepare statement in addtorejectlist '.DBI::errstr };
my $sth = $dbh->prepare("INSERT INTO reject(ip,service,asn,iso) VALUES(?,?,?,?)") || return { retval => 0, retmsg => 'Failed to prepare statement in addtorejectlist '.DBI::errstr };
$sth->execute($host,$service,$asn,$iso) || return { retval => 0, retmsg => 'Failed to executute statement in addtorejectlist '.DBI::errstr };
return { retval => 1, retmsg => "Added to reject list" };
}

View File

@ -22,6 +22,7 @@ sub new {
$self->parse if($self->load);
$self->{'config'}->{'test'} = $test;
$self->{'config'}->{'parse'} = $parse;
$self->{'db'} = undef;
return $self;
}
@ -122,38 +123,36 @@ sub get_fetcher_module {
sub db_connect {
my $self = shift;
if ($self->{'config'}->{'fetchers'}->{'db'}->{'dbh'}) {
#We pretend to be connected
if ($self->{'config'}->{'fetchers'}->{'db'}->{'dbh'}->ping()) {
my $dbh = $self->get_dbh();
if ($dbh) {
if ($dbh->ping()) {
return $self->get_dbh();
#We can ping, all is good
return 1;
} else {
#No can ping, time to reconnect
if ($self->{'config'}->{'fetchers'}->{'db'}->connect()) {
#all good
return 1;
} else {
#can't connect??
die "Can't connect to db";
}
return $self->{'db'}->connect();
}
} else {
#Never connected?
$self->{'config'}->{'fetchers'}->{'db'}->init();
return $self->{'db'}->connect();
}
return 0;
die "End of db_connect should never be reached";
}
sub set_db {
my $self = shift;
$self->{'db'} = shift;
}
sub get_dbh {
my $self = shift;
my $dbh = $self->{'config'}->{'fetchers'}->{'db'}->{'dbh'};
return $dbh;
return $self->{'db'}->{'dbh'};
}
sub set_dbh {
my $self = shift;
my $dbh = shift;
$self->{'config'}->{'fetchers'}->{'db'}->{'dbh'} = $dbh;
$self->{'db'}->{'dbh'} = $dbh;
return 1;
}

View File

@ -2,7 +2,6 @@ package My::parser::db;
use strict;
use warnings;
use DBI;
#use Scalar::Util qw(weaken);
sub new {
my $class = shift;
@ -19,8 +18,8 @@ sub new {
sub init {
my $self = shift;
my $parser = shift; ## not needed for this module as the db-connection is for all modules
$self->connect || die "Could not connect to db";
return 1;
$self->connect() || die "Could not connect to db";
return $self->{'config'}->get_dbh();
}
sub connect {
@ -32,13 +31,19 @@ sub connect {
my $db = $config->get_as_single_val('config','db');
my $dbh;
if($usr && $pwd && $host && $db) {
my $i = 0;
$self->{'config'}->{'logger'}->log('Connecting to DB');
while(1) {
last if($dbh = DBI->connect("DBI:mysql:database=$db;host=$host",$usr,$pwd, { PrintError => 1, mysql_auto_reconnect=>1, AutoCommit => 1 }));
sleep(10);
last if($dbh = DBI->connect("DBI:mysql:database=$db;host=$host",$usr,$pwd, { PrintError => 1, mysql_auto_reconnect=>0, AutoCommit => 1 }));
sleep($i);
$i++;
unless ($i % 10) {
$self->{'config'}->{'logger'}->log('Cannot connect to DB, reconnect retry '.$i);
}
}
$config->set_dbh($dbh);
#$self->{'config'}->{'logger'}->log("Sucsessfully connected to db"); FIXME add debug to config?
return 1;
return $config->get_dbh();
} else {
$self->{'config'}->{'logger'}->log("Unable to connect to db, not enough parameters");
return 0;

View File

@ -23,13 +23,8 @@ sub parser {
$host = $2;
};
} elsif($string =~ m/https\/1: (Timeout|Connection closed) during SSL handshake/) {
$_ = $string;
$reply = 'SSL handshake error';
$hostile = 1;
PARSE:
m/(:\ ($re_host):[0-9]{1,6})/gcix && do {
$host = $2;
};
$_ = $string;
$reply = 'SSL handshake error';
} elsif($string =~ m/http(s\~|) http(s|)\/\<NOSRV\>/) {
if($string =~ m/-1\/-1\/-1\/-1\/[0-9]{1,20} (400|0) 0/) {
#This one seems like someone is doing something bad. Return code 400/0

View File

@ -12,7 +12,8 @@ sub new {
sub islocal {
my $self = shift;
my $host = shift;
my @local_nets = ('127\.','10\.','192\.168\.','172\.((1[6-9])|(2[0-9])|(3[0-1]))\.','213\.236\.200\.(7|10)'); # array of regexes matching networks considered local and to be ignored
#SSL Labs - 64.41.200.0/24
my @local_nets = ('127\.','10\.','192\.168\.','172\.((1[6-9])|(2[0-9])|(3[0-1]))\.','64\.41\.200\.', '213.236.200.10','18.200.56.156'); # array of regexes matching networks considered local and to be ignored
my $local = 0;
foreach my $test(@local_nets) {
$local = 1 if($host =~ m/^$test/);

View File

@ -6,6 +6,7 @@ use My::parser::config;
use My::parser::geoip;
use My::parser::localcheck;
use My::parser::block;
use My::parser::db;
sub new {
my $class = shift;
@ -18,6 +19,9 @@ sub new {
$self->{'geoip'} = My::parser::geoip->new($self->{'config'});
$self->{'localcheck'} = My::parser::localcheck->new;
$self->{'block'} = My::parser::block->new($self->{'config'});
$self->{'db'} = My::parser::db->new($self->{'config'});
$self->{'db'}->init();
$self->{'config'}->set_db($self->{'db'});
return $self;
}
@ -105,7 +109,7 @@ sub dyninit {
my $parser = shift;
if(my $initr = $self->init($fetcher_loaded,$parser)) {
$self->{'config'}->set('fetchers',$fetcher_needed,$fetcher_loaded);
#$self->{'config'}->{'logger'}->log("Dependency $fetcher_needed initialized"); FIXME add debug in config?
#$self->{'config'}->{'logger'}->log("Dependency $fetcher_needed initialized");
return 1;
}
return 0;
@ -135,6 +139,7 @@ sub init {
my $self = shift;
my $fetcher = shift;
my $parser = shift;
$self->{'config'}->{'logger'}->log("Initializing $fetcher for $parser");
return 1 if($fetcher->init($parser));
return 0;
}

View File

@ -15,18 +15,17 @@ sub new {
sub fetch {
my $self = shift;
$self->{'config'}->db_connect();
$self->{'dbh'} = $self->{'config'}->get_dbh unless($self->{'dbh'});
my $dbh = $self->{'config'}->db_connect();
my $seq = $self->{'seq'} || 0;
my $retmsg;
my @toreturn;
unless($seq) {
my $seqsth = $self->{'dbh'}->prepare("SELECT seq FROM logs WHERE program = 'sshd' ORDER BY seq DESC LIMIT 1") or return { retval => 0, retmsg => DBI::errstr, error => 1 };
$seqsth->execute or return { retval => 0, retmsg => DBI::errstr, error => 1};
$seq = $seqsth->fetchrow_arrayref->[0] or return { retval => 0, retmsg => DBI::errstr, error => 1};
my $seqsth = $dbh->prepare("SELECT seq FROM logs WHERE program = 'sshd' ORDER BY seq DESC LIMIT 1") or return { retval => 0, retmsg => DBI::errstr, error => 1 };
$seqsth->execute() or return { retval => 0, retmsg => DBI::errstr, error => 1};
$seq = $seqsth->fetchrow_arrayref()->[0] or return { retval => 0, retmsg => DBI::errstr, error => 1};
}
my $sth = $self->{'dbh'}->prepare("SELECT msg,seq FROM logs WHERE program = 'sshd' AND seq > $seq") or return { retval => 1, retmsg => DBI::errstr, error => 1 };
$sth->execute or return { retval => 0, retmsg => DBI::errstr, error => 1};
my $sth = $dbh->prepare("SELECT msg,seq FROM logs WHERE program = 'sshd' AND seq > $seq") or return { retval => 1, retmsg => DBI::errstr, error => 1 };
$sth->execute() or return { retval => 0, retmsg => DBI::errstr, error => 1};
while(my $ref = $sth->fetchrow_hashref) {
my $string = $$ref{'msg'};
$seq = $$ref{'seq'};

View File

@ -47,7 +47,7 @@ sub parser {
m/(from\ ($re_host)) /gcix && do {
$host = $2;
};
} elsif($string =~ m/(Disconnecting|Received disconnect from|Disconnected from|Connection closed by|Connection reset by) (authenticating |invalid |)(user .* |)$re_host port [0-9]{1,6}(\: Too many authentication failures|)( \[preauth\]|)/) {
} elsif($string =~ m/(Disconnecting|Received disconnect from|Disconnected from|Connection closed by|Connection reset by) (invalid |)(user .* |)$re_host port [0-9]{1,6}(\: Too many authentication failures|)( \[preauth\]|)/) {
$_ = $string;
$reply = 'Received disconnect';
$hostile = 1;

View File

@ -18,8 +18,8 @@ sub new {
sub recent_hostile {
my $self = shift;
$self->{'dbh'} = $self->{'config'}->get_dbh unless($self->{'dbh'});
my $sth = $self->{'dbh'}->prepare("
my $dbh = $self->{'config'}->db_connect();
my $sth = $dbh->prepare("
SELECT COUNT(1)
FROM reject
WHERE time > DATE_SUB(NOW(), INTERVAL 5 MINUTE)")
@ -48,7 +48,7 @@ sub checker {
#### Mapping between checks and column in db
my %values = ('reject' => 'ip','blocks' => 'ip', 'iso' => 'iso', 'asn' => 'asn', 'block_iso' => 'iso', 'block_asn' => 'asn');
my %keys = ('reject' => $host, 'blocks' => $host, 'iso' => $iso, 'block_iso' => $iso, 'asn' => $asn, 'block_asn' => $asn);
$self->{'dbh'} = $self->{'config'}->get_dbh unless($self->{'dbh'});
my $dbh = $self->{'config'}->db_connect();
foreach my $time(@times) {
foreach my $c(keys %checks) {
my $fromcheck = $self->check($keys{$c},$time,$values{$c},$checks{$c});
@ -72,8 +72,9 @@ sub check {
my $retval;
my $rows;
my $msg;
my $dbh = $self->{'config'}->db_connect();
if($host && $allowed_time && $value && $table) {
my $sth = $self->{'dbh'}->prepare("
my $sth = $dbh->prepare("
SELECT COUNT(1)
FROM $table
WHERE $value = ? AND