#! /usr/bin/perl

# compare-rbl.pl
#
# extract client ip addresses from mail.log and
# find out which (if any) RBLs would block them.
#
# $Id: compare-rbls.pl,v 1.3 2004/12/09 21:23:58 root Exp $
#
# Copyright Craig Sanders <cas@taz.net.au> 2001
#
# this program is licensed under the terms of the GNU General Public 
# License (GPL)
#
# the latest version can always be found at http://taz.net.au/postfix/scripts

use File::MMagic ;
use Net::DNS;
use strict ;

# add bin directory to @INC for openlogfile.pl
use FindBin;
use lib "$FindBin::Bin";

my $FH ;
require "openlogfile.pl" ;

my (%seen, %list, %count, $total);
#my @dnsrbls = qw(blackholes.mail-abuse.org relays.mail-abuse.org
#                 dialups.mail-abuse.org
#                 relays.osirusoft.com 
#                 inputs.orbz.org outputs.orbz.org
#                 or.orbl.org
#                 relays.ordb.org);

my @dnsrbls = qw(cn-kr.blackholes.us
                 taiwan.blackholes.us
                 brazil.blackholes.us
                 hongkong.blackholes.us
                 list.dsbl.org
                 sbl-xbl.spamhaus.org
                 dul.dnsbl.sorbs.net
                 dnsbl.sorbs.net
                 Dynablock.njabl.org
                 relays.ordb.org
                );

my $resolver = new Net::DNS::Resolver;

push @ARGV, "/var/log/mail.log" if (@ARGV == 0) ;

foreach my $file (@ARGV) {
    $FH = &open_log_file($file) ;

    while (<$FH>) {
        my ($domain,$ip,$reverse);
        chomp ;
        next unless s/.* postfix\/smtpd.* connect from // ;
        ($domain, $ip) = m/(.*)\[(.*)\]/;
        next if $seen{$ip} ;
        ($reverse = $ip) =~ s/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/$4.$3.$2.$1/;
        $seen{$ip} = $domain ;

        #print "$domain\t$ip\t$reverse\n" ;
        foreach my $rbl (0..(@dnsrbls -1)) {
            #print "\t$reverse\.$dnsrbls[$rbl]\t\t\t" ;
            my $query = $resolver->search("$reverse\.$dnsrbls[$rbl]") ;
            if ($query) {
                foreach my $rr ($query->answer) {
                    next unless $rr->type eq "A";
                    #print $rr->address, "\t";
                    ($list{$ip}{$rbl} = $rr->address) =~ s/127\.0\.0\././ ;
                    $count{"$rbl"}++ ;
                    $count{"$ip"}++ ;
                } ;
            } ;
            #print "\n" ;
        } ;
        $total++ if ($count{"$ip"} gt 0);

    }
    close($FH);
} ;

#my @sortkeys = (sort {$count{$a} <=> $count{$b} } @dnsrbls) ;

print "\n\nKEY:\n" ;
foreach (0..(@dnsrbls -1)) { 
    my $hits = ($count{$_} gt 0) ? $count{$_} : 0 ;
    printf "%2i: %-30s %4i/%i = %3.0f%%\n", $_, $dnsrbls[$_], $hits, $total, $hits/$total*100 ;
} ;
print "\ntotal rbl-listed IP addresses: $total\n" ;
print "\n" ;

printf "%15s", "IP  /  RBL" ;
foreach (0..(@dnsrbls -1)) { printf "%3s", $_ } ;
printf "\t%s\n", "domain" ;

printf "%15s", "---------------" ;
foreach (0..(@dnsrbls -1)) { printf "%3s", " --" } ;
printf "\t%s\n", "--------------" ;

foreach my $ip (sort keys %seen) {
    next unless $count{$ip} ;
    printf "%15s",$ip ;
    foreach my $rbl (0..(@dnsrbls -1)) {
        printf "%3s", ($list{$ip}{$rbl} || " -") ;
    } ;
    printf "\t%s\n", $seen{$ip} ;
}

