Startseite LUG Untermain

Startseite
 
Über uns
Stammtisch
 
Über Linux
SW-Patente
Rezensionen
 
Mailingliste
Online-Mail-Archiv
 
LUG-IRC Channel
LUG-IRC Statistik-NEU-
 
Gästebuch
 
Arbeitsgruppen
Softwaredownloads
Vorträge
FAQ & Hints
HOWTOs
Doku-Wiki -NEU-
 
LUG-Kalender
Links
 
Blog
LUGUM-Planet


hosted by
logo

User-Bereich
(passwortgeschützt)
Passwort vergessen?
219 Mitglieder

Anmelden - HIER -






Gemischtes Doppel: Mails transportieren, säubern und sortieren mit Exim, ClamAV, Procmail und Spamassassin


Nachdem Exim ja bekanntlich der Standard-MTA von Debian Sarge (dem von mir verwendeten Betriebssystem) ist und zudem als sehr flexibel und gut dokumentiert gilt, habe ich mich dazu entschlossen, auf meinem Router einen Mailserver um Exim herum aufzusetzen. Dabei galt es einige Besonderheiten zu berücksichtigen, wie z.B. ausgehende Mails abhängig von der Absenderadresse an verschiedene Mailprovider zu versenden. (Siehe auch mein esmtp-Howto.)

Dieses HowTo beschreibt, wie ich meine spezielle Konfiguration eingerichtet habe und wie sie funktioniert. Es kann und soll nicht die Dokumentationen der einzelnen Programme ersetzen. Außerdem gehe ich hier nicht auf das Einsammeln von Mails auf externen Server mittels Fetchmail o.ä. und das Zurverfügungstellen der Mails mittels IMAP oder POP.

Noch ein weiterer wichtiger Hinweis: Das HowTo beschreibt die beteiligten Programme und deren Konfiguration in einer logischen Reihenfolge. Es sollten aber unbedingt alle Schritte nachvollzogen werden, bevor das Mailsystem aktiviert wird. Falls nicht, kann es zu Problemen von Fehlermeldungen bis hin zu Mailverlust kommen.

Exim installieren und konfigurieren

Installation

Exim sollte bei einem frisch installierten Debian-System eigentlich installiert sein und laufen. Es schadet aber nichts, zur Sicherheit nochmals

# apt-get install exim4-daemon-heavy
auszuführen. Dazu kommt noch, daß Debian Exim in einer „Heavy“- und etwas abgespeckten „Light“-Version anbietet – mit obiger Zeile stellt man sicher, daß die Version mit allen Möglichkeiten installiert ist. Sollten bei der Installation einige Informationen abgefragt werden („Konfiguration in kleine Dateien aufteilen“, Konfigurationsart, etc.), so können diese beliebig beantwortet werden. Diese Konfiguration wird anschließend ohnehin überschrieben.

Anschließend legt man unter /etc/exim4/exim4.conf eine Datei folgenden Inhalts an:

CONFDIR = /etc/exim4
primary_hostname = tigersclaw.suchanek.lan

domainlist local_domains = @:localhost:suchanek.lan:suchanek.dyndns.org
domainlist relay_to_domains =
hostlist   relay_from_hosts = 127.0.0.1 : ::::1 : 10.1.0.0/16

av_scanner = clamd:/var/run/clamav/clamd.ctl

tls_certificate = /etc/exim4/exim4.cert.pem
tls_privatekey = /etc/exim4/exim4.key.pem
tls_advertise_hosts = *

acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data

never_users = root

host_lookup = *

rfc1413_hosts = *
rfc1413_query_timeout = 0s

ignore_bounce_errors_after = 2d

timeout_frozen_after = 7d


begin acl

acl_check_rcpt:

  accept  hosts = : 127.0.0.1

  deny    message       = Restricted characters in address
          domains       = +local_domains
          local_parts   = ^[.] : ^.*[@%!/|]

  deny    message       = Restricted characters in address
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./

  accept  local_parts   = postmaster
          domains       = +local_domains

  require verify        = sender

  accept  domains       = +local_domains
          endpass
          verify        = recipient

  accept  domains       = +relay_to_domains
          endpass
          verify        = recipient

  accept  hosts         = +relay_from_hosts

  accept  authenticated = *

  deny    message       = relay not permitted


acl_check_data:

  warn message = X-Virus: FOUND ($malware_name)
     demime = *
     malware = *

  warn condition = ${if !def:header_Date: {1}}
     hosts = :
     message = Date: $tod_full
  accept

begin routers

smarthost_list:
  debug_print = "R: smarthost list for $local_part@$domain"
  driver = manualroute
  domains = ! +local_domains
  senders = wildlsearch;CONFDIR/sender.smarthost.passwd
  transport = remote_smtp_list
  route_list = * ${extract{1}{:}{${lookup{$sender_address}wildlsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}
  host_find_failed = defer
  no_more

system_aliases:
  driver = redirect
  allow_fail
  allow_defer
  data = ${lookup{$local_part}lsearch{/etc/aliases}}
  file_transport = address_file
  pipe_transport = address_pipe

localuser:
  driver = accept
  check_local_user
  transport = procmail_pipe
  cannot_route_message = Unknown user


begin transports

remote_smtp:
  driver = smtp

remote_smtp_list:
  debug_print = "T: remote_smtp_list for $local_part@$domain"
  driver = smtp
  hosts_require_auth = ${extract{1}{:}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}

address_pipe:
  driver = pipe
  return_output

address_file:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  return_path_add

procmail_pipe:
  debug_print = "T: procmail_pipe for $local_part@$domain"
  driver = pipe
  path = "/bin:/usr/bin:/usr/local/bin"
  command = "/usr/bin/procmail"
  user = $local_part
  return_path_add
  delivery_date_add
  envelope_to_add


begin retry

*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h


begin authenticators

plain:
  driver = plaintext
  public_name = PLAIN
  client_send = "^${extract{2}{::}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}\
                 ^${extract{3}{::}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}"
  server_condition = \
                ${if eq {${readsocket{/var/run/courier/authdaemon/socket}\
                {AUTH ${strlen:exim\nlogin\n$2\n$3\n}\nexim\nlogin\n$2\n$3\n}}}{FAIL\n}{no}{yes}}
  server_set_id = $2
  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}

login:
  driver = plaintext
  public_name = LOGIN
  client_send = ": ${extract{2}{::}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}} \
                 : ${extract{3}{::}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}"
  server_prompts = Username:: : Password::
  server_condition = ${if eq {${readsocket{/var/run/courier/authdaemon/socket} \
                {AUTH ${strlen:exim\nlogin\n$1\n$2\n}\nexim\nlogin\n$1\n$2\n}}}{FAIL\n}{no}{yes}}
  server_set_id = $1
  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}

cram_md5:
  driver = cram_md5
  public_name = CRAM-MD5
  client_name = ${extract{2}{:}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}
  client_secret = ${extract{3}{:}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}

Allgemeiner Teil der Konfiguration

Zunächst ein paar Worte darüber, wie Exim Mails annimmt und verteilt: Wenn eine SMTP-Verbindung aufgebaut wird, werden während des SMTP-Dialoges zu bestimmten Zeitpunkten sogenannte ACLs abgearbeitet. Diese entscheiden darüber, ob die Mail angenommen oder abgelehnt wird. Sie bestehen aus Regelsätzen, die nacheinander abgearbeitet werden. So lange, bis eine Regel zutrifft.

Wird die Mail angenommen, kontrolliert Exim, ob auf sie die Bedingungen eines Routers zutreffen. Diese Router beschreiben, unter welchen Umstände eine Mail wohin zugestellt wird. Ein solcher Router übergibt die Mail schließlich an einen von mehreren Transports, der die Mail dann tatsächlich zustellt.

Eine genauere Beschreibung dieser Zusammenhänge finden sich in Kapitel 3 der Exim-Dokumentation. Dementsprechend gliedert sich die Exim-Konfigurations-Datei in unterschiedliche Blöcke:

  • Allgemeiner Teil, der unbedingt am Anfang stehen muß
  • Die Blöcke „acl“, „routers“, „transports“, „retry“, „rewrite“ und „authenticators“, die in beliebiger Reihenfolge stehen können.

Die oben gezeigte Konfiguration basiert zudem auf der mitgelieferten Beispiel-Konfiguration, die sich unter /usr/share/doc/exim4-base/example/example.conf.gz befindet und die in Kapitel 7 der Exim-Dokumentation ausführlich besprochen wird.

Im folgenden sollen die einzelnen Zeilen und Blöcke der Konfiguration etwas näher erklärt werden:

CONFDIR = /etc/exim4

Hier wird eine Variable als „Abkürzung“ zur späteren Verwendung definiert.

primary_hostname = tigersclaw.suchanek.lan

Mit dieser Zeile wird der Hostname gesetzt. Ist der Hostname im System bereits richtig gesetzt, kann auf diese Zeile auch verzichtet werden.

domainlist local_domains = @:localhost:suchanek.lan:suchanek.dyndns.org
domainlist relay_to_domains =
hostlist   relay_from_hosts = 127.0.0.1 : ::::1 : 10.1.0.0/16

Anschließend werden drei wichtige Listen definiert. (Exim verwendet als Listentrennzeichen einen Doppelpunkt.)
Die erste Liste, local_domains legt fest, an welche Domains Mails gerichtet sein dürfen, damit sie von Exim angenommen werden – sofern nicht eine ACL-Bedingung dagegen spricht. „@“ ist dabei die Abkürzung für den Namen des localhost.
Mit relay_to_domains wird festgelegt, für welche Domains Exim Mails annimmt, um sie anschließend dorthin weiterzuleiten (Relaying). Diese Liste sollte man tunlichst leer lassen, wenn man nicht sehr genau weiß, was man tut, da man sonst sehr schnell ein bei Spammern beliebtes „offenes Relay“ bauen kann.
Schließlich gibt es noch die relay_from_hosts-Liste, mit der festgelegt werden kann, von welchen Hosts E-Mails zum Relaying akzeptiert werden. (::::1 steht dabei für den IPv6-Ausdruck „::1“ für Localhost. Die Doppelpunkte müssen hier verdoppelt werden, um von Exim nicht mit Listentrennzeichen verwechselt zu werden.)
Allen drei Listen ist übrigens gemein, daß sie noch keine tatsächlichen Bedingungen zum Annehmen oder Ablehnen von Mails definieren, sondern lediglich Variablen-Deklarationen sind, die später noch Verwendung finden.

av_scanner = clamd:/var/run/clamav/clamd.ctl

Hierbei handelt es sich um eine spezielle Variablendeklaration, mir man Exim mit ClamAV bekanntmacht. Näheres zu diesem Virenscanner findet sich im entsprechenden Unterpunkt.

tls_certificate = /etc/exim4/exim4.cert.pem
tls_privatekey = /etc/exim4/exim4.key.pem
tls_advertise_hosts = *
Da Exim mit verschlüsselten Verbindungen betrieben werden soll, sind hier die Pfade zum TLS-Zertifikat und -Schlüssel angegeben. Die dritte Zeile weist Exim an, die Möglichkeit einer TLS-Verbindung allen anfragenden Hosts bekanntzugeben. (Als Antwort auf ein EHLO im SMTP-Dialog.)

acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data

Von den zahlreichen vorhandenen Möglichkeiten, zu verschiedenen Zeiten eine abbr lang="en" title="Access Control List">ACL abzuarbeiten, werden hier zwei genutzt: Einmal unmittelbar nach Senden des DATA-Kommandos im SMTP-Dialog. und einmal nach dem Ende der Mail, jedoch noch vor Exims Antwort mit einer abschließenden Bestätigung (oder Fehlermeldung).

never_users = root

Aus Sicherheitsgründen soll keine Postzustellung unmittelbar an root direkt vorgenommen werden. Dies ist jedoch nicht weiter problematisch, da üblicherweise ohnehin eine Umleitung dieser Mails an einen anderen Account mittels /etc/aliases erfolgt.

host_lookup = *

Durch das Setzen dieser Option erfragt Exim zu jeder IP-Adresse einer eigehenden Verbindung den zugehörigen Hostnamen im DNS. Wenn man das aus dem einen oder anderen Grund nicht möchte, können hier auch bestimmte Adressbereiche definiert werden, für die die Ausflösung erfolgen soll. (Bis zu einer leeren Liste, was gar keiner Auflösung entspricht.)

rfc1413_hosts = *
rfc1413_query_timeout = 0s

Mit diesen beide Optionen kann definiert werden, ob, wohin und mit welchem Timeout Exim bei SMTP-Verbindungen einen Identifikations-Anfrage gemäß RfC 1413 an den sendenden Host absetzen soll. Der Timeout von 0s deaktiviert dieses Verhalten komplett, da es bei mir zu Komplikationen mit Windows-Clients geführt hatte.

ignore_bounce_errors_after = 2d
timeout_frozen_after = 7d

Die letzten beiden Optionen des allgemeinen Teils definieren schließlich noch, daß Bounce-Mails, die ihrerseits Fehler hervorrufen nach zwei Tagen und „frozen“ („eingefrorene“, d.h. wegen Problemen auf Eis gelegte Mails) nach sieben Tagen kommentarlos aus der Warteschlange gelöscht werden sollen.

Access Control Lists

begin acl

acl_check_rcpt:

  accept  hosts = : 127.0.0.1 : ::::1

Mit den ersten beiden Zeilen wird der Konfigurationsblock der ACLs sowie die ACL „acl_check_rcpt“ eingeleitet.
Die dritte Zeile sorgt dafür, daß alle Mails von Localhost aus angenommen werden. Sowohl per Socket-Verbindung (erster, leerer Eintrag) als auch per TCP/IP. Das dient u.a. auch dazu, daß Mails, die von Fetchmail eingeliefert werden, angenommen werden, ohne daß es bei bestimmten Spam-Mails zu Fehlermeldungen kommt.

  deny    message       = Restricted characters in address
          domains       = +local_domains
          local_parts   = ^[.] : ^.*[@%!/|]

  deny    message       = Restricted characters in address
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./

Diese beiden Regeln sorgen dafür, daß Mails, die ungültige Zeichen in der Adresse enthalten, abgelehnt werden. (Eine detailierter Erklärung findet sich in Kapitel 7.2 der Dokumentation)

  accept  local_parts   = postmaster
          domains       = +local_domains

Der Postmaster-Account sollte immer erreichbar sein, daher werden Mails an ihn sehr früh in der ACL zugelassen.

  require verify        = sender

Damit wird festgelegt, daß Absenderadressen verifiziert werden müssen. Diese Maßnahme hilft u.a., das Spam-Aufkommen zu reduzieren. Dies gilt allerdings nur für Mails, welche direkt an den Server gesendet werden. Mails, die Fetchmail von externen Servern abgeholt hat, wurden ja bereits weiter oben ungefragt akzeptiert.

  accept  domains       = +local_domains
          endpass
          verify        = recipient

Alle Mails, die an die lokalen Domains gerichtet sind und deren Empfänger auch tatsächlich existiert, werden angenommen. Existiert der Empfänger nicht, wird die Mail abgelehnt (implizit) und keine weiteren ACL-Regeln mehr abgearbeitet („endpass“).

  accept  domains       = +relay_to_domains
          endpass
          verify        = recipient

Gleiches gilt für alle Domains, für die Relaying zugelassen werden soll.

  accept  hosts         = +relay_from_hosts

Hier werden nun tatsächlich Mails von bestimmten, oben definierten Hots zum Relaying angenommen. Dies ist eine Möglichkeit, das Versenden von Mails aus einem LAN heraus über Exim zuzulassen.

  accept  authenticated = *

Außerdem werden Mails grundsätzlich angenommen, wenn sich der Absender authentifziert hat. (Zu den Authentifizierungs-Mechanismen siehe weiter unten.)

  deny    message       = relay not permitted

Schließlich werden noch alle Mails, auf die keine der bisherigen Regeln zugetroffen hat, explizit mit der Meldung „relay not permitted“ abgelehnt.

acl_check_data:

  warn message = X-Virus: FOUND ($malware_name)
     demime = *
     malware = *

Hiermit beginnt die zweite ACL. Die letzten beiden Zeilen bewirken, daß bei allen Mails evtl. MIME-Container entpackt und einem Virenscan unterzogen werden sollen. Dazu wird der oben im allgemeinen Teil definierte „av_scanner“ verwendet. Wird ein Virus gefunden, wird die Header-Zeile „X-Virus: FOUND“ zusammen mit dem Namen des Viruses in die Mail geschrieben.

  warn condition = ${if !def:header_Date: {1}}
     hosts = :
     message = Date: $tod_full
  accept

Bei diesen Zeilen handelt es sich um eine kleine zusätzliche Spielerei: Ist kein Date-Header definiert, so wird er hiermit gesetzt.

Routers

begin routers

smarthost_list:
  debug_print = "R: smarthost list for $local_part@$domain"
  driver = manualroute
  domains = ! +local_domains
  senders = wildlsearch;CONFDIR/sender.smarthost.passwd
  transport = remote_smtp_list
  route_list = * ${extract{1}{:}{${lookup{$sender_address}wildlsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}
  host_find_failed = defer
  no_more

Mit diesen Zeilen wird zunächst der Router-Block eingeleitet und der erste Router definiert. Er kümmert sich um alle Mails, die nicht für die lokale Zustellung vorgesehen sind (also an externe Hosts weitergeleitet werden sollen). Dazu schaut er in einer Datei /etc/exim4/sender.smarthost.passwd nach, die wie folgt aufgebaut sein muß:

AbsenderAdresse:ExternerServer:Username:Passwort

Mehrere Zeilen sind natürlich möglich. Dadurch sendet Exim Mails an diejenigen externen Server, bei man jeweils einen Mail-Account hat. Für eine GMX-Adresse sähe dies beispielsweise so aus:

user@gmx.de:mail.gmx.net:1234567:Geheim

Damit wird jede Mail, die den Absender „user@gmx.de“ trägt, an GMX gesendet. (Username und Passwort werden später von den Authenticators ausgelesen.) Konnte kein passender externer Server gefunden werden, wird die Zustellung vorübergehend ausgesetzt (host_find_failed = defer), außerdem wird grundsätzlich kein weiterer Router bearbeitet (no_more), falls dieser Router sich um eine Mail gekümmer hat.

system_aliases:
  driver = redirect
  allow_fail
  allow_defer
  data = ${lookup{$local_part}lsearch{/etc/aliases}}
  file_transport = address_file
  pipe_transport = address_pipe

Dieser Router kümmert sich um Weiterleitungen von Mails, wie sie in /etc/aliases definiert sind.

localuser:
  driver = accept
  check_local_user
  transport = procmail_pipe
  cannot_route_message = Unknown user

Schließlich erfolgt die Zustellung an lokale User, indem die Mail an Procmail übergeben wird. Sollte der User nicht existieren, wird eine Fehlermeldung („Unkown User“) von Exim erzeugt.

Transports

begin transports

remote_smtp_list:
  debug_print = "T: remote_smtp_list for $local_part@$domain"
  driver = smtp
  hosts_require_auth = ${extract{1}{:}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}

Nun beginnt der Block der Transports. Dies werden immer durch einen Router und nie „selbständig“ aufgerufen.
Der erste Transport kümmert sich um die Einlieferung von Mails bei externen Servern.

address_pipe:
  driver = pipe
  return_output

address_file:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  return_path_add

Diese beiden Transports sind für die Zustellung durch eine Pipe und in eine mbox-Datei zuständig.

procmail_pipe:
  debug_print = "T: procmail_pipe for $local_part@$domain"
  driver = pipe
  path = "/bin:/usr/bin:/usr/local/bin"
  command = "/usr/bin/procmail"
  user = $local_part
  return_path_add
  delivery_date_add
  envelope_to_add

Hiermit wird eine Mail schließlich zur endgültigen Zustellung an Procmail übergeben.

Retry

begin retry

*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h

Im Retry-Block werden die Zeitintervalle definiert, nach denen Exim eine erneute Mailzustellung versucht, falls zuvor ein Fehler aufgetreten ist. Eine detailierte Beschreibung dieser Zeile findet sich in Kapitel 7.5 der Dokumentation.

Authenticators


begin authenticators

plain:
  driver = plaintext
  public_name = PLAIN
  client_send = "^${extract{2}{::}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}\
                 ^${extract{3}{::}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}"
  server_condition = \
                ${if eq {${readsocket{/var/run/courier/authdaemon/socket}\
                {AUTH ${strlen:exim\nlogin\n$2\n$3\n}\nexim\nlogin\n$2\n$3\n}}}{FAIL\n}{no}{yes}}
  server_set_id = $2
  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}

Schlußendlich werden noch die Authenticators definiert. Diese sind dafür zuständig, die Authentifizierung zu regeln. Sollen die Optionen das Verhalten von Exim als Server regeln, beginnen sie mit einem server_, für das Verhalten als Client (also bei der Anmeldung an einem fremden Server) mit client_.
Der erste Authenticator kümmert sich um den Plain-Mechanismus, bei dem Username und Passwort im Klartext übertragen werden. Wird ein externer Server angesprochen, werden Username und Passwort in der in Router beschriebenen Datei /etc/exim4/sender.smarthost.passwd nachgeschlagen (client_send-Zeile). Möchte sich ein Client bei Exim anmelden, erfolgt die Prüfung auf korrekte Anmeldung durch Rückfrage an einem Courier-Auth-Daemon. Dies hat den Vorteil, daß die Passwörter für IMAP/POP und SMTP stets automatisch konsistent gehalten werden. Unabhängig davon, ob die Userverwaltung über das Betriebssystem, über eine MySQL-Datenbank, über LDAP o.ä. erfolgt. Der Nachteil ist, daß eben ein Courier-Auth-Daemon laufen muß. Dies war jedoch Dank Courier-IMAP automatisch der Fall.
Diese Konfiguration ist im Übrigen aus /etc/exim4/conf.d/auth/30_exim4-config_examples entnommen.

Die letzte Zeile sorgt dafür, daß dieser Mechanis nur Clients angeboten wird, die über eine TLS-gesicherte Verbindung kommunizieren wollen. Dadurch wird verhindert, daß Usernamen und Passwort unverschlüsselt durchs Netz gesendet werden.

login:
  driver = plaintext
  public_name = LOGIN
  client_send = ": ${extract{2}{::}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}} \
                 : ${extract{3}{::}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}"
  server_prompts = Username:: : Password::
  server_condition = ${if eq {${readsocket{/var/run/courier/authdaemon/socket} \
                {AUTH ${strlen:exim\nlogin\n$1\n$2\n}\nexim\nlogin\n$1\n$2\n}}}{FAIL\n}{no}{yes}}
  server_set_id = $1
  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}

Dieser Block verhält sich im wesentlichen wie der vorhergehende, behandelt jedoch den LOGIN-Mechanismus.

cram_md5:
  driver = cram_md5
  public_name = CRAM-MD5
  client_name = ${extract{2}{:}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}
  client_secret = ${extract{3}{:}{${lookup{$sender_address}lsearch{CONFDIR/sender.smarthost.passwd}{$value}fail}}}

Schließlich wird noch die Möglichkeit zur Verschlüsselten CRAM-MD5-Anmeldung eingerichtet. Auf die Nutzung dieses Mechanismus durch externe Clients wurde hier verzichtet, da dies komplizierter einzurichten wäre und wegen der bereits beschriebenen TLS-Sicherung kein Grund für eine zweite Verschlüsselung besteht.

ClamAV

Die Installation und Konfiguration von ClamAV ist schnell erledigt:

# apt-get install clamav clamav-freshclam clamav-daemon

Danach sollte man sicherstellen, daß die Datei /etc/clamav/clamd.conf die Zeile AllowSupplementaryGroups enthält, was aber bei Debian Sarge standardmäßig der Fall ist. Schließlich muß noch der ClamAV-User der Exim-Gruppe hinzugefügt werden, um Problemen mit Zugriffsrechten aus dem Weg zu gehen:

# adduser clamav Debian-exim

Da Exim bei der Installation ClamAV normalerweise automatisch startet, muß ClamAV nun noch neu gestartet werden, um ihn mit der neuen Gruppenzugehörigkeit bekannt zu machen:

# /etc/init.d/clamav-daemon restart

Der zweite Daemon, Freshclam, dient im Übrigen dazu, ClamAVs Virendefinitionen auf dem aktuellen Stand zu halten. Sein Verhalten wird bereits mit einigen einfachen Fragen bei der Installation festgelegt.

Procmail

Procmail ist dafür zuständig, die Mails in die Postfächer in die User zuzustellen und dort auch ggf. auch in Unterordner einzusortieren. Ich habe mich dazu entschlossen, in Procmail auch die Spam-Filterung mit Spamassassin einzubauen. Dieses Verfahren bietet mehrere Vorteile:

  • Die Spamfilterung kann einfach userspezifisch (de-)aktiviert werden
  • Bestimmte Mails können auf einfache Art am Spamfilter vorbeigeschleust werden
  • Spamassassin baut userspezifische Datenbanken für den Bayes-Filter auf
  • Spamassassin kann so konfiguriert werden, daß erkannte Spam-Mails in einen Mailanhang verpackt werden (hilfreich bei übereifrigen Mailclients, die sonst durch das Nachladen von Grafiken in HTML-Mails über speziell präparierte URLs die eigene Adresse verfizieren können) und zudem ein detailierter Filterreport beigefügt wird.

Wer stattdessen eine zentrale Spamfilterung in Exim bevorzugt, findet im c't-Server-Forum eine Anleitung dazu.

Procmail selbst lässt sich ebenfalls sehr einfach installieren:

# apt-get install procmail

Falls – wie bei mir – ein IMAP-Server zum Einsatz kommen soll, sollte nun im Homeverzeichnis jedes Users ein Mailverzeichnis angelegt werden. Dies erledigen komfortabel die folgenden Zeilen:

# cd /home
# for a in *;
> do su $a -c "maildirmake /home/$a/Maildir";
> done

Ansonsten würden alle Mails an einen User in einer mbox-Datei unter /var/spool/mails/user landen.
Möchte man auch Quarantäne-Verzeichnise für Viren- und Spam-Mails einrichten, geschieht dies ebenfalls schnell und problemlos hiermit:

# cd /home
# for a in *;
> do su $a -c "maildirmake /home/$a/Maildir/VIRUS";
> done
# cd /home
# for a in *;
> do su $a -c "maildirmake /home/$a/Maildir/SPAM";
> done

Schließlich muß noch in jedem User-Home-Verzeichnis eine .procmailrc-Datei angelegt werden. Diese könnte zum Beispiel so aussehen:

SHELL=/bin/sh
PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
MAILDIR=$HOME/Maildir/
LOGFILE=$MAILDIR/procmail.log
LOGABSTRACT="all"
VERBOSE="on"

:0
* ^X-Virus: FOUND
.VIRUS/

:0fw
* < 256000
| spamc

:0
* ^X-Spam-Flag: YES
.SPAM/

:0
*
$HOME/Maildir/

Hierbei stehen am Anfang zunächst einige allgemeine, selbsterklärende Deklarationen. Danach folgen die Filterregeln, die nacheinander abgearbeitet werden, bis eine Bedingung zutrifft. Danach folgende Regeln werden nicht mehr geprüft.

Die erste Regel dient dazu, an Hand der Zeile „X-Virus: FOUND“ (siehe auch ClamAV) Mails mit Viren darin zu identifizieren und in das Unterverzeichnis „VIRUS“ zu verschieben.

Die zweite Regel ruft für alle Mails, die kleiner als 256 kB sind (Spam-Mails sind selten so groß), Spamassassin auf.
Hat Spamassassin eine Mail als Spam erkannt, was sich am „X-Spam-Flag: YES“-Header erkennen lässt, wird diese Mail in das „SPAM“-Unterverzeichnis verschoben.

Die letzte Regel sorgt schließlich dafür, daß alle Mails, die weder Spam noch Viren sind, im Mail-„Hauptverzeichnis“ abgelegt werden. Diese Regel ist äußerst wichtig, da Mail ansonsten kommentarlos verworfen werfen.
Weitere persönliche Filterregeln sollten also unbedingt vor dieser letzten Regel eingefügt werden.

Spamassassin

Installation

Spamassassin wird zunächst mit einigen weiteren Zusatzpaketen installiert:

# apt-get install spamassassin spamc pyzor razor

Konfiguration

Nun muß Spamassassin noch konfiguriert werden. Eine komfortable Möglichkeit bietet http://www.yrex.com/spam/spamconfig.php, wo man sich mit Hilfe eines Webformulars eine Basis-Konfiguration zusammenstellen kann. Meine eigene Konfiguration /etc/spamassassin/local.cf ist so aufgebaut:

required_score           5.0

rewrite_header subject         *****SPAM*****
report_safe             2

use_bayes               1
bayes_auto_learn        1
bayes_auto_learn_threshold_nonspam 0.2
bayes_auto_learn_threshold_spam 10
bayes_ignore_header X-purgate
bayes_ignore_header X-purgate-ID
bayes_ignore_header X-purgate-Ad
bayes_ignore_header X-GMX-Antispam
bayes_ignore_header X-Antispam
bayes_ignore_header X-Spamcount
bayes_ignore_header X-Spamsensitivity

skip_rbl_checks         0
use_razor2              1
use_dcc                 1
use_pyzor               1

ok_languages            en de
ok_locales              en

score ALL_TRUSTED 0

Spamassassin vergibt beim Scannen Punkte, für jede Regel, die zutrifft, die addiert werden. „required_score“ gibt dabei den Schwellwert an, ab dem eine Mail als Spam klassifiziert wird.

Die nächsten beiden Zeilen sorgen dafür, daß Spam-Mails um die Zeichenkette „*****SPAM*****“ im Betreff ergänzt werden und als Mail-Anhang verpackt werden sollen.

Die folgenden vier Optionen mit „bayes“ im Namen aktivieren das Bayes-Filter und konfigurieren ihn. Dabei handelt es sich um ein Filter, das nicht nach festen Regeln arbeitet, sondern eine statistische Analyse, basierend auf Spam- und Nicht-Spam-Mails, die man ihm zuvor zum Lernen vorgelegt hat, erstellt. Dieses Filter wird standardmäßig erst aktiv, nachdem es mindestens 200 Spam-Mails gelernt hat. Im Interesse einer guten Treffergenauigkeit sollte man dieses Filtertraining auch wirklich mit eigenen Mails durchführen und nicht mit generischen Spam-Mail-Katalogen aus dem Internet.
Außerdem wird noch die Autolearning-Funktion aktiviert. Diese bewirkt, daß Mails, die zuvor von festen Filtern als Spam oder Nicht-Spam erkannt wurden, automatisch als solche gelernt werden. Die dritte und vierte Option definieren Schwellwerte für die Spam-Punktezahl, die für das Lernen eingehalten werden müssen.
Schließlich wird das Bayes-Filter noch angewiesen, bestimmte Header anderer Spam-Filter unberücksichtigt zu lassen, um davon nicht beeinflusst zu werden.

Die vier nachfolgenden Zeilen aktivieren einige weitere Filter-Methoden.

Die „ok_languages„-Option gibt an, in welchen Sprachen man Mails empfängt. Spamassassin versucht, die Sprache, in der eine Mail verfasst ist, zu erkennen. Handelt es sich dabei um eine nicht „freigegebene„ Sprache, wird der Spam-Punktestand erhöht.
Die „ok_locales“ hat den selben Effekt für Zeichensätze. „en“ steht hier stellvertretend für alle Sprachen mit lateinischen Buchstaben.

Die nächste Zeile deaktiviert de facto die „ALL-TRUSTED“ Filterregel, in dem man ihr den Punktewert 0 zuweißt. Diese Regel für ansonsten verstärkt zu dem Problem, daß Spam-Mails nicht als solche erkannt werden.

Komfortables Spam-Lernen

Wie bereits erwähnt, arbeitet das Bayes-Filter auf der Basis einer statistischen Analyse. Dabei kann es natürlich vorkommen, daß diese Analyse falsch ist, was zu einer falschen Einstufung der Mail als Spam bzw. Nicht-Spam führen kann. Daher ist es notwendig, auch während des späteren Betriebs Spamassassin an Hand von Mails weiter lernen zu lassen. (Vorzugsweise von solchen Mails, die falsch erkannt wurden.)

Um diesen Lernvorgang komfortabel vom Mail-Client aus vornehmen zu können, habe ich folgendes System eingerichtet: Zunächst werden als Unterordner des „SPAM“-Ordners die zwei Unterordner „Spam lernen“ und „Ham lernen“ eingerichtet. Dies kann entweder vom IMAP-Mail-Client aus oder mittels maildirmake (vgl. Procmail) geschehen.

In diesem Unterordner kann man nun einfach per Mail-Client Mails, die netsprechend gelernt werden sollen, verschieben. Für den Lernprozeß selbst sorgt das folgende Shell-Script, das ich per cron regelmäßig alle 5 min laufen lasse:

#!/bin/sh

# Skript zum Lernen von Spam und Ham aus IMAP-Postfächern der User
# Sebastian Suchanek, 2006-01-13

cd /home
for user in *; do                        # alle User bearbeiten
  if [ -r "/home/$user/Maildir/.SPAM.Spam lernen/cur/" ]; then        # Schauen, ob es ein Spam-Lernen-Verzeichnis gibt
    cd /home/$user/Maildir/.SPAM.Spam\ lernen/cur/
    for mail in *; do                        # alle Spam-Mails lernen
      if [ "$mail" != "*" ]; then        # Schauen, ob Mails vorhanden sind
        /usr/bin/sa-learn --spam --dbpath /home/$user/.spamassassin/ /home/$user/Maildir/.SPAM.Spam\ lernen/cur/$mail
        cat $mail | procmail -d $user
        rm $mail                        # Spam-Mail lernen, neu sortieren und löschen
      else
        echo "No Spam to learn for user $user"
      fi
   done
  fi
  if [ -r "/home/$user/Maildir/.SPAM.Ham lernen/cur/" ]; then        # Schauen, ob es ein Spam-Lernen-Verzeichnis gibt
    cd /home/$user/Maildir/.SPAM.Ham\ lernen/cur/
    for mail in *; do                        # alle Ham-Mails lernen
      if [ "$mail" != "*" ]; then        # Schauen, ob Mails vorhanden sind
        /usr/bin/sa-learn --ham --dbpath /home/$user/.spamassassin/ /home/$user/Maildir/.SPAM.Ham\ lernen/cur/$mail
        cat $mail | /usr/bin/spamassassin -d | procmail -d $user
        rm $mail                        # Ham-Mail lernen, säubern, neu sortieren und löschen
      else
        echo "No Ham to learn for user $user"
      fi
    done
  fi
done

Die Kommentare im Skript sollten eigentlich für das Verständnis der Funktion ausreichen.

Inbetriebnahme und Ausblick

Nachdem nun alle beteiligten Programme konfiguriert sind, können sie nun (neu-)gestartet werden. Es ist dringend anzuraten, daß zuerst mit einigen Testmails die Funktionsfähigkeit des Systems überprüft wird, um späteren Produktivbetrieb keine Mails zu verlieren.

Hat man etwas an den ACLs geändert, so empfiehlt es sich außerdem, auf der Konsole folgenden Befehl einzugeben:

# telnet relay-test.mail-abuse.org

Dadurch veranlasst man einen kurzen Test, ob der eigene Mailserver möglicherweise doch ein offenes Relay ist. Das Ergebnis bekommt man unmittelbar danach über die Telnet-Verbindung ausgegeben.

Was nun zu einem wirklich kompletten Mailserver noch fehlt, ist die Zurverfügungstellung der Mails an externe Clients mittels IMAP oder POP, sowie ggf. das Abholen von Mails von externen Servern mittels Fetchmail. Beides überlasse ich anderen Tutorials und HowTos.
Auch sonst bietet Exim noch viel Raum für weitere Optionen und Spielereien, die möglicherweise irgendwann später ebenfalls in weiteren Texten beschrieben werden.


Anleitung von Sebastian Suchanek


Disclaimer
Impressum


News
- Microsoft übertrifft trotz Gewinnschwund die Erwartungen
 
- Amazon weiter mit wenig Gewinn
 
- Vic Gundotra verlässt Google
 
- Thilo Weichert: "Google Glass ist eine Waffe"
 
- Zero-Day-Lücke in Apache Struts 2
 
- Kunstwerke von Andy Warhol auf Amiga-Disketten gerettet
 
- Berliner Philharmoniker gründen eigenes Plattenlabel
 
- Bürgerrechtler kritisieren neue russische Internet-Gesetze
 
- SPD zeigt sich gespalten bei der Vorratsdatenspeicherung
 
- Magine streamt TV-Sender auch in Deutschland ins Netz