Files
parserfilter/lib/ssh_parser.pm

209 lines
6.4 KiB
Perl

package My::parser::ssh_parser;
use strict;
use warnings;
sub new {
my $class = shift;
my $self = {};
bless ($self, $class);
return $self;
}
sub parser {
my $self = shift;
my $string = shift;
my ($reply,$hostile,$host) = ('',0,'');
my $re_host = qr/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/;
my $re_user = qr/[\w\d_\-.]*/;
if($string =~ m/Accepted publickey for/) {
$reply = 'Accept publickey';
} elsif($string =~ m/Received disconnect from $re_host port [0-9]{1,5}:11: disconnected by user/) {
$reply = 'Normal disconnect';
} elsif($string =~ m/Failed unknown for (invalid user |)$re_user from $re_host port [0-9]{1,5} ssh2/) {
$reply = 'Log spam, also logged as a failure';
} elsif($string =~ m/Disconnected from user $re_user $re_host port [0-9]{1,5}$/) {
$reply = 'Normal disconnect';
} elsif($string =~ m/Did not receive identification string from /) {
$_ = $string;
$reply = 'No identification string';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/User $re_user from $re_host not allowed because /) {
$_ = $string;
$reply = 'Blocked user';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/(i|I)nvalid user .* from $re_host port/) {
$_ = $string;
$reply = 'Invalid user';
$hostile = 1;
PARSER:
m/(from\ ($re_host)) /gcix && do {
$host = $2;
};
} 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;
PARSER:
m/(\ ($re_host)\ port\ [0-9]{1,6})/gcix && do {
$host = $2;
};
} elsif($string =~ m/refused connect from .* \($re_host\)/) {
$_ = $string;
$reply = 'Blocked by tcpwrappers';
$hostile = 1;
PARSER:
m/ \(($re_host)\) /gcix && do {
$host = $1;
};
} elsif($string =~ m/error: maximum authentication attempts exceeded for (invalid user |)$re_user from ($re_host) port [0-9]{1,6} (ssh2 |)\[preauth\]/) {
$_ = $string;
$reply = 'Auth attempt limit exceeded';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/fatal: Unable to negotiate with/) {
$_ = $string;
$reply = 'Unable to negotiate';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/Bad protocol version identification/) {
$_ = $string;
$reply = 'Bad protocol';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/Could not write ident string to/) {
$_ = $string;
$reply = 'Could not write ident string';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/Disconnecting (authenticating|invalid) user.*Change of username or service not allowed/) {
$_ = $string;
$reply = "Change of username or service";
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/Failed publickey for $re_user from $re_host port [\d]{1,6}.*/) {
$_ = $string;
$reply = 'Failed publickey';
$hostile = 1;
PARSER:
m/\ ($re_host)\ /gcix && do {
$host = $1;
};
} elsif($string =~ m/ssh_dispatch_run_fatal/) {
$_ = $string;
$reply = 'ssh dispatch fatal';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/Unable to negotiate with $re_host port/) {
$_ = $string;
$reply = 'Unable to negotiate. Weak key exchange';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/Protocol major versions differ for/) {
$_ = $string;
$reply = 'Protocol major versions differ';
$hostile = 1;
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/Unable to negotiate with .* no matching MAC found/) {
$host = '';
$reply = 'no matching MAC, ancient client trying to connect';
} elsif($string =~ m/\/etc\/hosts\.allow/) {
$host = '';
} elsif($string =~ m/Disconnecting: Too many authentication failures/) {
$host = '';
} elsif($string =~ m/input_userauth_request: invalid user.*\[preauth\]/) {
$host = '';
} elsif($string =~ m/user $re_user login class/) {
$host = '';
$reply = 'Useless log info';
} elsif($string =~ m/(Disconnected|Connection closed) (from|by) (invalid|) user $re_user $re_host port [0-9]{1,6} \[preauth\]/) {
$host = '';
$reply = 'Log info';
} elsif($string =~ m/Fssh_kex_exchange_identification/) {
$hostile = 0;
$reply = 'kex exchange identification problem';
} elsif($string =~ m/Fssh_kex_protocol_error: type/) {
$reply = 'kex protocol error (no ip information)';
} elsif($string =~ m/fatal: Timeout before authentication for $re_host port [0-9]{1,6}/) {
$_ = $string;
$hostile = 1;
$reply = 'Timeout before auth';
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/banner exchange: Connection from $re_host port [0-9]{1,6}: (invalid format|Permission denied|could not read protocol version|Broken pipe)/) {
$_ = $string;
$hostile = 1;
$reply = 'Error during banner exchange';
PARSER:
m/ ($re_host) /gcix && do {
$host = $1;
};
} elsif($string =~ m/Authentication error for( illegal user|) $re_user from $re_host$/) {
$_ = $string;
$hostile = 1;
$reply = 'Authentication error';
PARSER:
m/from\ ($re_host)$/gcix && do {
$host = $1;
};
} elsif($string =~ m/reverse mapping checking getaddrinfo for/) {
$reply = 'Reverse check failed';
} elsif($string =~ m/but this does not map back to the address/) {
$reply = 'Reverse map failure';
} elsif($string =~ m/Timeout before authentication for connection from/) {
$_ = $string;
$hostile = 1;
$reply = 'Timeout before authentication';
PARSER:
m/from\ ($re_host)\ to\ ($re_host),\ pid/gcix && do {
$host = $1;
};
} elsif($string =~ m/penalty\: exceeded LoginGraceTime/) {
$_ = $string;
$hostile = 1;
$reply = 'exceeded LoginGraceTime';
PARSER:
m/drop\ connection\ \#([0-9]{1,9})\ from\ \[($re_host)\]:([0-9]{1,9})\ on\ \[($re_host)\]:([0-9]{1,9})\ penalty:\ exceeded\ LoginGraceTime/gcix && do {
$host = $2;
};
} else {
$reply = 'No match for '.$string;
}
return { retval => 1, retmsg => $reply, hostile => $hostile, host => $host, string => $string };
}
1;