Skip to content

Commit

Permalink
Authentication success/failure lists are now split by user/IP and add…
Browse files Browse the repository at this point in the history
…ed $threshold_auth_ip_warning that can be used to always display users with logins from more than the threshold of different IP addresses, even if their total threshold is lower. Good for identifying hacked accounts!
  • Loading branch information
whataboutpereira committed Jun 7, 2018
1 parent 269e061 commit d6cb802
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 23 deletions.
63 changes: 40 additions & 23 deletions opensmtpd
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ my %Defaults = (
threshold_smtp_failures => 0,
threshold_auth => 0,
threshold_auth_failures => 0,
threshold_auth_ip_warning => 3,
threshold_relay => 0,
threshold_relay_failures => 0,
threshold_delivery => 0,
Expand Down Expand Up @@ -220,12 +221,12 @@ LINE: while ( <> ) {

if( $result eq 'ok') {
$Totals{SMTP}{auth}{success}++;
$Counts{SMTP}{auth}{success}{$user}++;
$Counts{SMTP}{auth}{success}{$user}{$hostip}++;
}

elsif( $result eq 'permfail' or $result eq 'tempfail') {
$Totals{SMTP}{auth}{failure}++;
$Counts{SMTP}{auth}{failure}{$hostip}{$user}++;
$Counts{SMTP}{auth}{failure}{$user}{$hostip}++;
}

else {
Expand Down Expand Up @@ -542,32 +543,19 @@ sub print_summary() {

if( $var->{auth} ) {
if( $var->{auth}{success} ) {
push @ret, count('Authenticated users', $var->{auth}, 'success', $Opts{threshold_auth} );
my $success = auth_summary('Authenticated users', $var->{auth}{success}, $Opts{threshold_auth}, $geoip_bin, $geoip_dat );

if( $success ) {
push @ret, $success;
}
}

if( $var->{auth}{failure} ) {
my $failures = '';

for my $ip ( sort { ipcmp( $a, $b ) } keys $var->{auth}{failure} ) {
my ( $iptotal, $ipstr, $users ) = ( 0, '', $var->{auth}{failure}{$ip} );

foreach my $k ( sort { $users->{$b} <=> $users->{$a} or $a cmp $b } keys $users ) {
if( $users->{$k} > $Opts{threshold_auth_failures} ) {
$iptotal += $users->{$k};
$ipstr .= sprintf("%16s %s\n", $users->{$k}, $k );
}
}

if( $ipstr ne '') {
$failures .= line( $iptotal, geoip( $geoip_bin, $geoip_dat, $ip ) ) . $ipstr;
}

}
my $failures = auth_summary('Authentication failures', $var->{auth}{failure}, $Opts{threshold_auth_failures}, $geoip_bin, $geoip_dat );

if( $failures ne '') {
push @ret, title('Authentication failures' . ( $Opts{threshold_auth_failures} ? "(threshold of $Opts{threshold_auth_failures})" : "") ) . $failures;
if( $failures ) {
push @ret, $failures;
}

}

delete $var->{auth};
Expand Down Expand Up @@ -709,6 +697,35 @@ sub count($$$;$;$) {

}

sub auth_summary($$$$$) {
my ( $title, $arr, $threshold, $geoip_bin, $geoip_dat ) = @_;

$threshold = 0 unless $threshold;

if( $arr ) {
my $ret = '';

foreach my $user ( sort { $arr->{$b} <=> $arr->{$a} or $a cmp $b } keys $arr ) {
my ( $iptotal, $ipstr, $ips ) = ( 0, '', $arr->{$user} );
my $ipcount = keys $ips;

for my $ip ( sort { $ips->{$b} <=> $ips->{$a} or ipcmp( $a, $b ) } keys $ips ) {
$iptotal += $ips->{$ip};
$ipstr .= sprintf("%16s %s\n", $ips->{$ip}, geoip( $geoip_bin, $geoip_dat, $ip ) );
}

if( $iptotal > $threshold or $ipcount > $Opts{threshold_auth_ip_warning} ) {
$ret .= line( $iptotal, $user . ( $ipcount > $Opts{threshold_auth_ip_warning} ? "\n *** WARNING! Logins from $ipcount IP addresses (threshold of $Opts{threshold_auth_ip_warning}) ***" : "") ) . $ipstr;
}
}

return unless $ret ne '';

return title( $title . ( $threshold > 0 ? " (threshold of $threshold)" : "") ) . $ret;

}
}

print_summary();

#
Expand Down
1 change: 1 addition & 0 deletions opensmtpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ $threshold_recipients = 1
$threshold_smtp_failures = 1
$threshold_auth = 1
$threshold_auth_failures = 0
$threshold_auth_ip_warning = 3 # Always display and warn about users with logins from many different IPs.
$threshold_relay = 1
$threshold_relay_failures = 1
$threshold_delivery = 1
Expand Down

0 comments on commit d6cb802

Please sign in to comment.