Spamassassin Spamtraining mittels Perl Script

Das Spamtraining mittels des Perlscripts setzt folgende installierte und laufende Programme voraus:

  • Postfix
  • Amavis
  • Spamassassin
  • Perl
  • Perl-Module: MIME::Tools und use MIME::Parser

In diesem Howto werden wir Postfix einen neuen virtuellen Transportweg beibringen. Dieses HowTo orientiert sich an der Verzeichnisstruktur von Debian. Daher kann es sein, dass unter anderen Distributionen wie SuSE andere Verzeichnisse und Benutzer gesetzt werden müssen. Das Ziel des Transportweges ist jedoch kein Mailserver oder eine Mailbox, sondern ein Perlscript, dass die Emails entgegen nimmt und die Email analysiert und je nachdem welche Adresse angesprochen wurde den Inhalt der Email als Basis für ein Spamtraining benutzt oder dem Spamfilter beibringt, dass es sich bei der Email nicht um eine Spammail handel.

Zunächst müssen wir Postfix zwei neue Emailadressen und ihre Domains bekannt gegeben. Hierzu einfach folgende Adressen in die Datei „/etc/aliases“ eintragen.

spam:        spam@spam.spam
nospam:      ham@ham.ham

Anschließend muss Postfix mitgeteilt werden, dass sich die aliases Datei verändert hat. Dies geschieht mit:

newaliases

In der Datei /etc/postfix/main.cf muss jetzt ein neues Transportfile eintragen werden. Mit diesem Transportfile teilen wir Postfix mit, was er machen soll, wenn eine Email an die Adressen spam@spam.spam oder ham@ham.ham gesendet werden soll. Einfach zustellen kann er diese Emails nicht, da er die Domänen nicht finden wird.

transport_maps = hash:/etc/postfix/transport

Nachdem wir Postfix gesagt haben, dass es eine neue Transportmap gibt müssen wir diese nun auch anlegen. Dazu einfach die Datei /etc/postfix/transport anlegen und folgenden Inhalt in die Datei einfügen:

spam.spam    sa-spam:
ham.ham        sa-ham:

Da Postfix die Datei in diesem Format nicht verarbeiten kann (wir haben Postfix gesagt, dass die Datei im Hashformat vorliegt) muss die Datei noch umgewandelt werden. Hierzu folgenden Befehl ausführen.

postmap /etc/postfix/transport

Folgende Zeilen müssen wir in der Konfiguratuionsdatei /etc/postfix/master.cf hinzufügen. Hiermit weiß Postfix dann, dass wenn eine Email an die Domäne spam.spam geschickt werden soll der virtuelle Transportweg sa-spam verwendet wird. Mit den folgenden Zeilen erklären wir Postfix dann, was sich hinter sa-spam verbirgt. Diese Zeilen einfach an das Ende der Konfigurationsdatei anhängen:

# Spam & Keinspam Training
sa-spam    unix    -    n    n    -    -    pipe user=amavis:amavis argv=/usr/local/bin/sa-wrapper.pl spam ${sender}
sa-ham    unix    -    n    n    -    -    pipe user=amavis:amavis argv=/usr/local/bin/sa-wrapper.pl ham  ${sender}

Achtung! Beim „pipe“ muss eventuell den User und die Gruppe angepasst werden. Hier sollte der User und die Gruppe eingetragen werden, mit der Dienst amavisd-new betrieben wird. Sollte hier ein anderer User eingetragen werden wird nicht die von Amavis verwendete Spamdatenbank erweitert, sondern die des Nutzers, der das Script gestartet hat. Das bringt dann natürlich nichts. Amavis verwendet die Datenbank auch erst dann, wenn mindestens 200 Emails jeweils als Spam und Ham ausgewertet wurden. Also vor dem Einsatz sollte man Amavis respektive Spamassassin trainieren.

Im Homeverzeichnis des Users amvais einen Unterordner „mime“ anlegen und auf amavis + gruppe berechtigen:

mkdir /var/lib/amavis/mime
chown amavis:amavis /var/lib/amavis/mime
chmod 770 /var/lib/amavis/mime

Das folgende Perlscript unter local abspeichern und ausführbar machen:

/usr/local/bin/sa-wrapper.pl
chmod 775 /usr/local/bin/sa-wrapper.pl

In dem Script sollten die folgenden Konstanten angepasst werden:

  • $DEBUG = 1 (damit wird in /tmp ein Logfile für jede analysierte Mail geschrieben)
  • $UNPACK_DIR = ‚/var/lib/amavis/mime‘; (Hier werden die Mails entpackt und analysiert)
  • @DOMAINS = qw/domain.com localhost localhost.localdomain/; (Hier die lokale/globale Domänen eintragen)

Es muss sichergestellt werden, dass die benötigten Perlmodule installiert sind:

MIME::Tools
MIME::Parser

— Schnipp —


#!/usr/bin/perl -w
# Time-stamp: <05 April 2004, 13:37 home>
#
# sa-wrapper.pl
#
# SpamAssassin sa-learn wrapper
# (c) Alexandre Jousset, 2004
# This script is GPL'd
#
# Thanks to: Chung-Kie Tung for the removal of the dir
#            Adam Gent for bug report
#
# v1.2
#Spamtraining
use strict;
use MIME::Tools;
use MIME::Parser;
my $DEBUG = 0;
my $UNPACK_DIR = '/var/lib/amavis/mime';
my $SA_LEARN = '/usr/bin/sa-learn';
my @DOMAINS = qw/patrick-wessel.de localhost localhost.localdomain/;
my ($spamham, $sender) = @ARGV;
sub recurs
 {
 my $ent = shift;
if ($ent->head->mime_type eq 'message/rfc822') {
 if ($DEBUG) {
 unlink "/tmp/spam.log.$$" if -e "/tmp/spam.log.$$";
 open(OUT, "|$SA_LEARN -D --$spamham --single >>/tmp/spam.log.$$ 2>&1") or die "Cannot pipe $SA_LEARN: $!";
 } else {
 open(OUT, "|$SA_LEARN --$spamham --single") or die "Cannot pipe $SA_LEARN: $!";
 }
$ent->bodyhandle->print(*OUT);
close(OUT);
 return;
 }
my @parts = $ent->parts;
if (@parts) {
 map { recurs($_) } @parts;
 }
 }
my ($domain) = $sender =~ /@(.*)$/;
 unless (grep { $_ eq $domain } @DOMAINS) {
 die "I don't recognize your domain !";
 }
if ($DEBUG) {
 MIME::Tools->debugging(1);
 open(STDERR, ">/tmp/spam_err.log");
 }
 my $parser = new MIME::Parser;
 $parser->extract_nested_messages(0);
 $parser->output_under($UNPACK_DIR);
my $entity;
 eval {
 $entity = $parser->parse(*STDIN);
 };
if ($@) {
 die $@;
 } else {
 recurs($entity);
 }
$parser->filer->purge;
rmdir $parser->output_dir;

— Schapp —

Das Script kann man sich auch hier herunter laden.

Jetzt müssen wir Postfix neustarten damit die Änderungen aktiv werden:

/etc/init.d/postfix restart

Um zu überprüfen ob alles korrekt funktioniert öffnen wir eine neue Konsole und betrachten das Maillogfile mittels tail um die Statusmeldungen des Servers zu sehen:

tail -f /var/log/mail.log

Jetzt muss man eine Mail mit Spam oder eine Mail die kein Spam erhält per message/rfc822 an spam@domain bzw. spam@localhost weiterleiten. Mit message/rfc822 ist gemeint, dass die Mail nicht inline, sondern als Anhang weitergeleitet wird. Die Email wird dann wie ein Dateianhang weitergeleitet und nicht verändert. Das ist wichtig, damit das Script auch die originalen Mailheader verarbeiten kann.

Der Mailclient Thunderbird leitet Emails in der Standardeinstellung genau so weiter wie wir es brauchen. Im Logfile sollte dann zu sehen sein, dass Postfix die Email angenommen hat und dann an über die Transportmap weiter an das Perlscript geleitet hat. Im Ordner /tmp sollte dann auch pro Mail ein entsprechendes Logfile geschrieben werden. Sollte man die Logfiles nicht mehr wünschen kann man Debug auf 0 setzen.

Diese Howto stützt sich auf diesen Artikel.

About the author