Re: [exim] Automatic Generation of White Lists and Black Lis…

Top Page
Delete this message
Reply to this message
Author: Marc Perkel
Date:  
To: exim-users
Subject: Re: [exim] Automatic Generation of White Lists and Black Lists (DNS)
OK - Here's a few of the pieces: Here's one that could be prettier but
don't know how else to run a script from and exim filter.

Within a filter I do conditionals on if the message is spam or ham and run:

if "" is "${run {/etc/exim/sql/ip-report spam
$h_X-Sender-Host-Address:}{}{}}"
then
endif

if "" is "${run {/etc/exim/sql/ip-report ham
$h_X-Sender-Host-Address:}{}{}}"
then
endif

In practice I have a few other codes for nonspam and lowspam that create
lower scored. The ip-report script looks like this:

echo "$*" | nc -w 4 mail.ctyme.com 109
exit 0

This sends a one line message to a common server from 3 email servers.
On the receiving server I run xinetd with this config:

service pop2
{
        wait            = no
        port            = 109
        log_type        = FILE /dev/null
        socket_type     = stream
        protocol        = tcp
        user            = mail
        server          = /etc/exim/sql/log-ip
        disable         = no
}


The log-ip script looks like this:

#!/bin/bash
/bin/cat >> /ip-log/karma.log

Every 6 hours I rotate the karma log files. I keep spam infor for 2 days
and ham for about a week. Here's the rotate script.

#!/bin/bash

/bin/rm /ip-log/karma.log.30
/bin/mv /ip-log/karma.log.29 /ip-log/karma.log.30
/bin/mv /ip-log/karma.log.28 /ip-log/karma.log.29
/bin/mv /ip-log/karma.log.27 /ip-log/karma.log.28
/bin/mv /ip-log/karma.log.26 /ip-log/karma.log.27
/bin/mv /ip-log/karma.log.25 /ip-log/karma.log.26
/bin/mv /ip-log/karma.log.24 /ip-log/karma.log.25
/bin/mv /ip-log/karma.log.23 /ip-log/karma.log.24
/bin/mv /ip-log/karma.log.22 /ip-log/karma.log.23
/bin/mv /ip-log/karma.log.21 /ip-log/karma.log.22
/bin/mv /ip-log/karma.log.20 /ip-log/karma.log.21
/bin/mv /ip-log/karma.log.19 /ip-log/karma.log.20
/bin/mv /ip-log/karma.log.18 /ip-log/karma.log.19
/bin/mv /ip-log/karma.log.17 /ip-log/karma.log.18
/bin/mv /ip-log/karma.log.16 /ip-log/karma.log.17
/bin/mv /ip-log/karma.log.15 /ip-log/karma.log.16
/bin/mv /ip-log/karma.log.14 /ip-log/karma.log.15
/bin/mv /ip-log/karma.log.13 /ip-log/karma.log.14
/bin/mv /ip-log/karma.log.12 /ip-log/karma.log.13
/bin/mv /ip-log/karma.log.11 /ip-log/karma.log.12
/bin/mv /ip-log/karma.log.10 /ip-log/karma.log.11
/bin/mv /ip-log/karma.log.09 /ip-log/karma.log.10
/bin/cat /ip-log/karma.log.08 | grep ham | grep -v dom > 
/ip-log/karma.log.09
/bin/mv /ip-log/karma.log.07 /ip-log/karma.log.08
/bin/mv /ip-log/karma.log.06 /ip-log/karma.log.07
/bin/mv /ip-log/karma.log.05 /ip-log/karma.log.06
/bin/mv /ip-log/karma.log.04 /ip-log/karma.log.05
/bin/mv /ip-log/karma.log.03 /ip-log/karma.log.04
/bin/mv /ip-log/karma.log.02 /ip-log/karma.log.03
/bin/mv /ip-log/karma.log.01 /ip-log/karma.log.02
/bin/cp /ip-log/karma.log    /ip-log/karma.log.01
true > /ip-log/karma.log


/sbin/service xinetd restart > /dev/null

Then there's my Pascal program that totals up the counts by IP address
it is run from a script I call zonegen:

#!/bin/bash

cp /etc/exim/scripts/zone.stub.karma
/var/named/hostkarma.junkemailfilter.com
cp /etc/exim/scripts/zone.stub.fromwl /var/named/fromwl.junkemailfilter.com
cp /etc/exim/scripts/zone.stub.domain
/var/named/domainkarma.junkemailfilter.com
cat /ip-log/*|sort -k 2|/etc/exim/scripts/ip-log-score > /dev/null
chown named:named /var/named/*
chmod 700 /var/named/*
/sbin/service named reload
/sbin/service xinetd reload
scp /var/named/*.junkemailfilter.com dns.ctyme.com:/var/named > /dev/null
ssh dns.ctyme.com service named reload > /dev/null

And the pascal program that receives the list sorted by IP address is:


Type Str80 = String[80];



var St : Str80;
    IP, RevIP, LastIP, SpamClass : Str80;
    IPCount, LineCount, HitCount : LongInt;
    Ham, Spam, LowSpam, NonSpam, FromWL, DomHam, DomSpam : LongInt;
    SpamFactor, HamFactor, SpamScore : Real;
    P : Byte;
    blackfile, whitefile,yellowfile,yellowfile2,brownfile : text;
    karmazonefile,domainzonefile,fromwlzonefile : text;
    autobounce : text;
    Enoughdata : Boolean;



Procedure WriteZone (Code : Byte);
begin
   if Code = 1 then begin
      Writeln(karmazonefile,RevIP,#9,'A',#9,'127.0.0.1');
      Writeln(karmazonefile,#9#9,'TXT',#9,'"',LastIP,' whitelisted 
ham=',HamFactor:0:0,' spam=',SpamFactor:0:0,' 
http://wiki.ctyme.com/index.php/Spam_DNS_Lists"');
   end;
   if Code = 2 then begin
      Writeln(karmazonefile,RevIP,#9,'A',#9,'127.0.0.2');
      Writeln(karmazonefile,#9#9,'TXT',#9,'"',LastIP,' blacklisted 
ham=',HamFactor:0:0,' spam=',SpamFactor:0:0,' 
http://wiki.ctyme.com/index.php/Spam_DNS_Lists"');
   end;
   if Code = 3 then begin
      Writeln(karmazonefile,RevIP,#9,'A',#9,'127.0.0.3');
      Writeln(karmazonefile,#9#9,'TXT',#9,'"',LastIP,' yellowlisted 
ham=',HamFactor:0:0,' spam=',SpamFactor:0:0,' 
http://wiki.ctyme.com/index.php/Spam_DNS_Lists"');
   end;
   if Code = 4 then begin
      Writeln(karmazonefile,RevIP,#9,'A',#9,'127.0.0.4');
      Writeln(karmazonefile,#9#9,'TXT',#9,'"',LastIP,' brownlisted 
ham=',HamFactor:0:0,' spam=',SpamFactor:0:0,' 
http://wiki.ctyme.com/index.php/Spam_DNS_Lists"');
   end;
   if Code = 5 then begin
      Writeln(fromwlzonefile,LastIP,#9,'A',#9,'127.0.0.1');
      Writeln(fromwlzonefile,#9#9,'TXT',#9,'"count=',FromWL,'"');
   end;
   if Code = 6 then begin
      Writeln(domainzonefile,LastIP,#9,'A',#9,'127.0.0.1');
      Writeln(domainzonefile,#9#9,'TXT',#9,'"ham=',DomHam,'"');
   end;
   if Code = 7 then begin
      Writeln(domainzonefile,LastIP,#9,'A',#9,'127.0.0.2');
      Writeln(domainzonefile,#9#9,'TXT',#9,'"spam=',DomSpam,'"');
   end;
end;



begin
Assign(input,'');
Reset(input);
Assign(output,'');
ReWrite(output);
Assign(blackfile,'/etc/exim/dnslists/black.txt');
ReWrite(blackfile);
Assign(whitefile,'/etc/exim/dnslists/white.txt');
ReWrite(whitefile);
Assign(yellowfile,'/etc/exim/dnslists/yellow.txt');
ReWrite(yellowfile);
Assign(brownfile,'/etc/exim/dnslists/brown.txt');
Assign(yellowfile2,'/etc/exim/dnslists/yellow2.txt');
ReWrite(yellowfile2);
ReWrite(brownfile);
Assign(karmazonefile,'/var/named/hostkarma.junkemailfilter.com');
Append(karmazonefile);
Assign(domainzonefile,'/var/named/domainkarma.junkemailfilter.com');
Append(domainzonefile);
Assign(fromwlzonefile,'/var/named/fromwl.junkemailfilter.com');
Append(fromwlzonefile);
Assign(autobounce,'/etc/exim/acllists/autobouncedomains.txt');
ReWrite(autobounce);

   IPCount := 0;
   LineCount := 0;
   LastIP := '';
   Ham := 0;
   Spam := 0;
   LowSpam := 0;
   NonSpam := 0;
   FromWL := 0;
   DomHam := 0;
   DomSpam := 0;
   HitCount := 0;
   while not eof(input) do begin
      readln(input,St);
      P := pos(' ',St);
      SpamClass := copy(St,1,P-1);
      IP := copy(St,P+1,80);
      if LineCount = 0 then LastIP := IP;
      if (IP <> LastIP) then begin
         St := LastIP;


         P := pos('.',St);
         RevIP := copy(St,1,P-1);
         delete(St,1,P);


         P := pos('.',St);
         RevIP := copy(St,1,P-1)+'.'+RevIP;
         delete(St,1,P);


         P := pos('.',St);
         RevIP := copy(St,1,P-1)+'.'+RevIP;
         delete(St,1,P);


         RevIP := St+'.'+RevIP;


         SpamFactor := Spam + (LowSpam / 8);
         HamFactor := Ham + (NonSpam / 8);
         Enoughdata := HamFactor * 2 + SpamFactor > 25;
         if (SpamFactor + HamFactor) > 0 then begin
            SpamScore := (HamFactor) / (HamFactor + SpamFactor);
         end;


{         Writeln(output,LastIP,' ',Ham,' ',NonSpam,' ',LowSpam,' 
',Spam,' ',SpamScore:4:2);}


         if Enoughdata then begin
            if SpamScore >= 0.99 then begin
               Writeln(whitefile,LastIP);
               WriteZone(1);
            end else begin
               if SpamScore <= 0.01 then begin
                  Writeln(blackfile,LastIP);
                  WriteZone(2);
               end else begin
                  Writeln(yellowfile,LastIP);
                  Writeln(yellowfile2,LastIP);
                  WriteZone(3);
               end;
            end;
         end else begin
            if Ham > 2 then begin
               Writeln(yellowfile,LastIP);
               WriteZone(3);
            end;
            if (SpamFactor > 6) and (HamFactor = 0) then begin
               Writeln(brownfile,LastIP);
               WriteZone(4);
            end;
            if (FromWL > 1) and (pos('..',LastIP) = 0) and 
(length(LastIP) < 50) then begin
               if pos('_',LastIP) + pos('+',LastIP) = 0 then begin
                  WriteZone(5);
               end;
            end;
            if DomHam + DomSpam > 50 then begin
               if DomSpam = 0 then begin
                  WriteZone(6);
               end;
               if DomHam = 0 then begin
                  WriteZone(7);
                  if DomSpam > 50 then begin
                     Writeln(autobounce,LastIP);
                  end;
               end;
            end;
         end;


         LastIP := IP;
         Ham := 0;
         Spam := 0;
         LowSpam := 0;
         NonSpam := 0;
         FromWL := 0;
         DomHam := 0;
         DomSpam := 0;
         HitCount := 0;
         IPCount := IPCount + 1;
      end;
      if SpamClass = 'spam' then Spam := Spam + 1;
      if SpamClass = 'honey' then Spam := Spam + 3;
      if SpamClass = 'lowspam' then LowSpam := LowSpam + 1;
      if SpamClass = 'nonspam' then NonSpam := NonSpam + 1;
      if SpamClass = 'ham' then Ham := Ham + 1;
      if SpamClass = 'fromwl' then FromWL := FromWL + 1;
      if SpamClass = 'dom-ham' then DomHam := DomHam + 1;
      if SpamClass = 'dom-spam' then DomSpam := DomSpam + 1;
      HitCount := HitCount + 1;
      LineCount := LineCount + 1;
   end;     


close(blackfile);
close(whitefile);
close(yellowfile);
close(yellowfile2);
close(brownfile);
close(karmazonefile);
close(domainzonefile);
close(fromwlzonefile);
close(autobounce);
Close(Input);
Close(OutPut);
end.