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.