pages in this section

Mailserver-Setup

In einem Anflug von Größenwahn habe ich "hier" ein etwas komplexeres Mailsetup auf die Beine gestellt, dass sich vielleicht lohnt, zu dokumentieren. Mit Postfix und Dovecot kann ich hier beliebig viele "virtuelle Domains" hosten, ähnlich wie man es von Apache kennt. Authentifizierung findet über Dovecot mit einer Datenbank im Hintergrund statt, das ginge aber auch mit LDAP, oder noch einfacher mit Systemusern.

Ich gehe hier nur auf die Teile der Konfiguration ein, die im Zusammenhang mit Virtual Domain Hosting interessant sind. Bevor man das in Angriff nimmt, sollte man sich eh mit der Grundkonfiguration der beteiligten Programme befassen und ein Minimalsetup am Laufen haben.

Dovecot

Ich zäum das Pferd mal von hinten auf und erkläre zuerst, wie die Mails gespeichert und zugänglich gemacht werden. Das muss sowieso vor dem Mailempfang fertig sein und in meinem Fall ist es auch besonders wichtig, weil ich Dovecots LDA zur lokalen Zustellung und dovecot_auth zur Authentifizierung von POP/IMAP- und SMTP-Nutzern verwende.

Aber immer langsam. Erstmal die Basics:

protocols = pop3s imaps
listen = *
mail_location = maildir:/srv/mail/%Ld/%Ln
mail_extra_groups = vmail

Die ersten zwei Zeilen sollten klar sein. protocols kann pop3 oder imap sein, für die SSL-Varianten hängt man s an. Mit listen kontrolliert man, an welchem Interface Dovecot lauscht. Der * steht für alle. Mit mail_location gibt man den Speicherort der Mailboxen an. In meinem Fall gibt es pro Domain (%d) und User (%u) ein Verzeichnis (alles lowercase, daher das L jeweils davor). Alle Mailboxen gehören vmail:vmail, deswegen muss man Dovecot mitteilen, dass es diese Rechte nicht droppen soll. [1]

Schon kann man anfangen, die einzelnen Dienste zu konfigurieren:

protocol imap {
  mail_plugins = quota imap_quota
}

protocol pop3 {
  mail_plugins = quota
}

protocol lda {
  postmaster_address = postmaster@wasteland.xen-host.de
  mail_plugins = quota
  auth_socket_path = /var/run/dovecot/auth-master
}

Auf die Plugins geh ich hier mal nicht ein, interessant ist der LDA-Abschnitt. Die Option auth_socket_path gibt einen Socket an, wo der LDA sich anmeldende User authentifizieren kann. Wie man den konfiguriert, kommt jetzt:

auth default {
  mechanisms = plain login
  passdb sql {
      args = /etc/dovecot/dovecot-sql.conf
  }
  userdb sql {
      args = /etc/dovecot/dovecot-sql.conf
  }
  userdb prefetch {
      args = /etc/dovecot/dovecot-sql.conf
  }
  user = postgres
  socket listen {
    master {
      path = /var/run/dovecot/auth-master
      mode = 0660
      user = vmail
      group = vmail
    }
    client {
      path = /var/spool/postfix/private/auth
      mode = 0660
      user = postfix
      group =
    }
  }
}

Das ist etwas komplexer, aber auch noch recht gut durchschaubar. Als Loginmechanismen sollen plain und login erlaubt sein. MD5 und sowas ginge auch, ist aber hier egal, weil ich eh nur SSL anbiete. Dann kommen die Angaben, woher Dovecot Userdaten (Name, Speicherort für Mails, UID) und Passworte herbekommt. Das wird aus Sicherheitsgründen (denn da steht ein Passwort drin) in einer separaten Datei mit strengeren Zugriffsrechten geregelt. Die dovecot.conf ist normalerweise world-readable.

Die Angabe von userdb prefetch ist optional, erspart aber einige SQL-Queries. Nach der Angabe der Userid, unter der dovecot-auth laufen soll, folgen zwei Sockets: ein "Master-Socket" für den Dovecot LDA, und ein "Client-Socket" für Postfix.

Und schon fehlt nur noch die dovecot-sql.conf

driver = pgsql
connect = host=localhost dbname=mails user=mailreader password=<secret password>
default_pass_scheme = PLAIN-MD5
user_query =
  SELECT u.storage || ':' || d.basedir || u.userid as mail,
     105 as uid, 109 as gid
  FROM mailuser u, domain d
  WHERE u.userid = '%Ln' AND u.domain = '%Ld' AND u.domain = d.name
password_query =
  SELECT u.userid as user, u.password,
   u.storage || ':' || d.basedir || u.userid as userdb_mail,
   105 as userdb_uid, 109 as userdb_gid
  FROM mailuser u, domain d
  WHERE u.userid = '%Ln' AND u.domain = '%Ld' AND u.domain = d.name

Das ist wohl größtenteils selbsterklärend, daher hierzu nur zwei, drei Kommentare. Wegen userdb prefetch weiter oben gibt man hier in der password_query auch die Felder zurück, die sonst nur von der user_query geliefert werden. Dadurch spart man wie erwähnt beim Einloggen eine Query.

Die Mailverzeichnisse kann man natürlich auch direkt in der DB speichern, aber ich zog es vor, das aus dem Basisverzeichnis der Domain und der Userid zusammenzusetzen. Wie man sieht, kann man hier auch pro User ein eigenes Speicherformat (mbox, Maildir) festlegen. Die Rekonstruktion des Datenbanklayouts überlasse ich mal dem Reader als exercise.

Ach, und 105/109 sind UID/GID von dem oben erwähnten User vmail auf meinem System.

[1]Leider ist es ohne SUID-Bit oder root-Rechte noch nicht möglich, pro Domain einen eigenen Eigentümer für die Mailboxen zu definieren.

Postfix

Zustellung

Will man Dovecots LDA für virtuelle Domains benutzen, muss man ihn zuerst in der master.cf spezifizieren:

dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}

Man beachte, dass die user-Angabe mit dem Eigentümer des master_auth-Sockets von Dovecot und den SQL-Queries übereinstimmt. Dadurch wird der Dovecot-LDA aber noch nicht benutzt, Postfix kennt ihn ersteinmal nur. Der Teil kommt jetzt in der main.cf:

mydestination = localdomain, localhost, localhost.localdomain
mailbox_command = /usr/lib/dovecot/deliver # betrifft nur $mydestination
virtual_transport = dovecot          # betrifft $virtual_mailbox_domains

In $mydestination stehen nur lokale Domains. Da hab ich nur die Dummies stehen, weil ich alles über die virtuellen Mailboxen abfackele:

virtual_mailbox_domains = well-adjusted.de wasteland.xen-host.de
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_alias_maps = hash:/etc/postfix/valias

In virtual_mailbox_domains listet man einfach die Domains auf, für die man Mails grundsätzlich annehmen will. In der Datei vmailbox werden die gültigen Empfängeradressen aufgelistet. Im einfachsten Fall ist das ein Listing wie:

@well-adjusted.de          valid
@wasteland.xen-host.de     valid

Das sind Catch-All-Einträge. Ich nehme also Mails an jede denkbare Adresse auf diesen Domains an. Was in der zweiten Spalte steht, ist egal. Die valias ist eine einfache Alias-Datei, die Mailadressen auf richtige Mailboxen mappt:

@well-adjusted.de          jrspieker@well-adjusted.de
@wasteland.xen-host.de     jrspieker@wasteland.xen-host.de

Das knüpft hier natürlich an die Catch-All-Einträge an. Hat man sowas nicht, stehen links auch richtige Mailadressen. Bei Gelegenheit lasse ich diese Lookups auch noch über die Datenbank machen. Wenn man das wie ich hier über hash: macht, darf man wie üblich nach Änderungen nicht vergessen, postmap darüberlaufen zu lassen.

Authentifizierung

Nun noch die Authentifizierung. Ich will, dass sich alle Clients, für die ich Mails zustelle, über eine gesicherte Verbindung anmelden müssen. Die Authentifizierung macht aber nicht Postfix, sondern Dovecot:

smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_authenticated_header = yes
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/postfix/keys/wasteland.pem
smtpd_tls_security_level = may

In der ersten Zeile wird Postfix angewiesen, in seiner Rolle als Server (also, wenn er Mails von Clients zur weiteren Zustellung annehmen soll) Benutzer per SASL zu authentifizieren. Die zweite Zeile gibt an, dass der Authentifizierungsdienst von Dovecot zu benutzen ist. Der smptd_sasl_path gibt den Socket an, wo das passiert. Man beachte, dass dieser Pfad (relativ zum chroot von Postfix) genau der Pfad ist, der in der Dovecont-Konfiguration für den "Client-Socket" angegeben wurde.

Mit smtpd_sasl_authenticated_header = yes wird im Header jeder ausgehenden Mail der Benutzername des authentifizierten Users vermerkt. [2] Die Option smtpd_tls_auth_only = yes sagt, dass Authentifizierung ausschließlich über verschlüsselte Verbindungen erfolgen darf.

[2]Leider ist das momentan nicht der vollständige Benutzername (user@domain), sonder nur der Localpart, also alles vor dem "@".

Zugriffsbeschränkungen

Zu guter letzt muss man Postfix noch sagen, von wem genau überhaupt Mails angenommen werden dürfen. Dazu sollte man mindestens das hier setzen:

smptd_client_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject

Sonst hätte man ein offenes Relay. Mt den weiteren Möglichkeiten der *_restrictions-Optionen sollte man sich auf jeden Fall mit Hilfe der (nach ein bißchen Einlesen) sehr brauchbaren Postfix-Doku auseinandersetzen.

Policy-weightd

Policyd-weight ist ein in Perl geschriebener Daemon, den man vor Postfix schalten kann, um frühzeitig Spam erkennen zu können. Er arbeitet mit einem statischen Regelsatz, der Punkte für Eigenschaften und das Verhalten einliefernder Systeme vergibt. Ab einer gewissen Punktzahl wird die Zustellung abgelehnt. Das bedeutet, dass man einen Großteil des Spams schon erkennt, bevor er überhaupt eingeliefert wird (und damit Rechenzeit, Speicherplatz und Traffic kosten würde).

Das ist schnell konfiguriert (main.cf):

smtpd_restriction_classes = check_policyd_weight
check_policyd_weight = check_policy_service inet:127.0.0.1:12525

Dazu muss natürlich der policyd_weight auf dem angegebenen Port laufen.

Wenn man will, kann man policyd_weight auch nur für einzelne User/Domains zuschalten. Dazu macht man:

smtpd_recipient_restrictions =
    ...
    check_recipient_access hash:/etc/postfix/policyd_weight_users,
    permit

und eine Lookup-Table wie:

well-adjusted.de        check_policyd_weight
wasteland.xen-host.de   check_policyd_weight

Den Erfolg kann man an diesen schicken Grafiken ablesen. Was dort als "Spam" dargestellt wird, wurde von policyd_weight erkannt. Die Differenz zur roten Linie ("Rejected") sind größtenteils unauthorisierte Versuche, über diesen Server zu relayen. False Positives sieht man hier natürlich nicht, aber ich habe auch erst einen gehabt, soweit ich weiß. (Witzigerweise eine Mail von Steve Langasek, Debian Release Manager.)

Zurück nach oben
Letzte Änderung: Tue Jul 17 15:48:06 2012
.