209 lines
6.4 KiB
Perl
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;
|