Hello,

I always wanted to write this. Maybe it is useful to somebody. This
tutorial is about analysing simscan rejects to create a very harsh
qmail-smtpd.rules file.

Condition:
To reject ADSL networks at port 25, you must prepare another qmail-smtpd
service. Use the standard submission port (587) for example. Make sure,
nobody is able to deliver mails there without authentication. Example:
> :allow,SMTPAUTH="TLSREQUIRED",NOPBS="",AUTHREQUIRED="",SANITYCHECK="",RCPTCHECK="",SENDERCHECK="",LOGLEVEL="3"

Simscan:
Normally, you use simscan to reject high level junk mails during SMTP
transmission. Doing this can be very expensive. But it has advantages
too: The user doesn't have to handle 1000 mails in his junk folder every
day and the bounce handling must be done by the sending mailserver.

Simple script (Attached):
$ cat /var/log/qmail/qmail-smtpd/current |tail -n 200|log-reject.pl 
> .com (1)
>   corvel.com (1)
>     corvelusers64.corvel.com (1)
> 
> .net (2)
>   bezeqint.net (1)
>     bzq-79-183-18-2.red.bezeqint.net (1)
>   comunitel.net (1)
>     static-43-54-226-77.ipcom.comunitel.net (1)
It does a reverse DNS lookup of the rejected hosts and orders the data
according to its TLD and its domain. The numbers are hit counters. No
surprise here: Most of it comes from trojaned ADSL networks.

So, what to do if you get hit hard by a big German ADSL provider:
- p4fd751fa.dip.t-dialin.net
- p5dc53d87.dip.t-dialin.net
- p4ff0d754.dip.t-dialin.net
You have to reflect on it: Are there any good mails coming from? If
not, add this line to your qmail-smtpd.rules file:
> =.dip.t-dialin.net:allow,550GREETING="Access 
> Denied",SMTP550DISCONNECT="",LOGLEVEL="3"
It rejects all connecting hosts with dip.t-dialin.net in their FQHN.

Complete example:
> 127.0.0.1:allow,RELAYCLIENT=""
>
> # localhost
> =localhost:allow,550GREETING="You are not 
> me",SMTP550DISCONNECT="",LOGLEVEL="3"
> 
> # DE
> =.dip.t-dialin.net:allow,550GREETING="Access 
> Denied",SMTP550DISCONNECT="",LOGLEVEL="3"
>
> # Main rule: $TCPREMOTEHOST needed
> =:allow,QMAILQUEUE="/var/qmail/bin/simscan",SANITYCHECK="",REJECTEXEC="",RETURNMXCHECK="",RCPTCHECK="",SENDERCHECK="",BLOCKRELAYPROBE="",LOGLEVEL="3"
>  
> # Drop connections without $TCPREMOTEHOST
> :allow,421GREETING="Reverse DNS lookup 
> failed",SMTP550DISCONNECT="",LOGLEVEL="3"

This example also blocks hosts without a reverse DNS entry which is too
effective to ignore it. But it only returns a temporary 421 error.

Some numbers:
- No reverse DNS: About 50%
- Rejected reverse DNS entry: About 30%
- About >10% gets rejected by simscan using spamassassin and clamav.
- The rest gets deliverd. Only a few mails still enter the junk folders.
  They are mostly a result of crazy mail forwards.

Again, this is very aggressive and cannot be done in every situation.

I still hope that this text is of some use to somebody of you. Thank
you for your time. :)

So long,
    Aiko
-- 
:wq ✉
#!/usr/bin/perl -w
use strict;


my (%dnscache,%ip);
my (%tld,%domain,%host);


sub lookup
{
    my $input       = shift;
    my $dnscache    = shift;
    my $timeout     = 30;
    my $hostname    = "localhost";

    if ( $input !~ m/^\d+\.\d+\.\d+\.\d+$/ )
    {
        return($input);
    }

    if ( !$dnscache->{$input} )
    {
        eval
        {
#            alarm($timeout);
            ($hostname) = gethostbyaddr(pack('C4',split('\.',$input)),2);
#            alarm(0);
        };

        if ( $@ || !$hostname )
        {
            return($input);
        }
        
        $dnscache->{$input} = $hostname;
    }

    return lc($dnscache->{$input});
}


while ( $_ = <STDIN> )
{
    $_ =~ s/\n//;
    my ($addr,$fqhn,$tld,$domain);

    if ( $_ =~ m/.+ simscan:\[\d+\]:SPAM REJECT/ )
    {
        # Remove the beginning, so that using tai64nlocal makes no difference
        $_ =~ s/.+ simscan:\[\d+\]://;

        # IP address
        (undef,undef,undef,$addr) = split(/:/, $_);

        # FQHN
        $fqhn = lookup($addr, \%dnscache);
        if ( $host{$fqhn} )
        {
            $host{$fqhn} += 1;
        }
        else
        {
            $host{$fqhn} = 1;
        }

        # TLD
        $tld  = $fqhn;
        $tld  =~ s/.+\.(\S+)$/$1/;
        if ( $tld{$tld} )
        {
            $tld{$tld} += 1;
        }
        else
        {
            $tld{$tld} = 1;
        }

        # Domain
        $domain  = $fqhn;
        $domain  =~ s/.+\.(\S+\.\S+)$/$1/;
        if ( $domain{$domain} )
        {
            $domain{$domain} += 1;
        }
        else
        {
            $domain{$domain} = 1;
        }
    }
}


foreach my $tld (sort keys %tld)
{
    print ".".$tld." (".$tld{$tld}.")\n";

    foreach my $domain (sort keys %domain)
    {
        if ( $domain =~ m/\.$tld$/ )
        {
            print "  ".$domain." (".$domain{$domain}.")\n";
    
            foreach my $host (sort keys %host)
            {
                if ( $host =~ m/\.$domain$/ )
                {
                    print "    ".$host." (".$host{$host}.")\n";
                    delete $host{$host};
                }
            }
            delete $domain{$domain};
        }
    }
    print "\n";
}

Reply via email to