Sebastian Hempel bio photo

Sebastian Hempel

Software Crafter, Clean-Code-Developer, JEE Professional, Puppet-Master, OpenSource Fanboy

Email LinkedIn XING Github Fediverse

Der Jahreswechsel ist eine schöne Zeit. Nach den Feiertagen kommt man endgültig zur Ruhe und schöpft Kraft für das neue Jahr. Man blickt zurück auf das vergangene Jahr und schmiedet Pläne für das kommende. Es ist aber auch die Zeit schon länger geplante Tätigkeiten endlich durchzuführen und so das Jahr richtig gut zu beginnen. So ist es auch mir ergangen und ich habe endlich die Migration meiner bereits seit Jahren bestehenden Cyrus-IMAP Installation zum IMAP-Server Dovecot (vom englischen dovecote = Taubenschlag) durchgeführt.

dovecot logo

Was hat mich zur Migration bewogen?

Ich kann mich nicht über die Zuverlässigkeit von Cyrus-IMAP beschweren. Der Server lief in Zusammenarbeit mit Postfix all die Jahre ohne größere Probleme und Mailverluste.

Es waren aber die kleineren Probleme, die mich zu einem Wechsel des IMAP-Servers gebracht haben. Ab und an waren die Index-Dateien von Cyrus-IMAP nicht mehr in Ordnung und mit den mitgelieferten Werkzeugen nur umständlich wieder in den Griff zu bekommen. Die Konfiguration – gerade im Zusammenhang mit SASL – ist nicht als elegant und schön zu bezeichnen. Nicht zuletzt ist die Sicherung eines Cryus-IMAP Servers mit einer gewissen Downtime verbunden.

Nach kurzer Beschäftigung mit Dovecot stand für mich fest, dass ich auf diesen IMAP-Server migrieren möchte. Die Konfiguration ist einfach und elegant, die Sicherung kann auch im laufenden Betrieb erfolgen und die “Selbstheilung” bei defekten Index-Dateien ist einfach nur schön. Dovecot fühlt sich für mich einfach zuverlässiger und moderner an als das schon etwas in die Jahre gekommene Cyrus-IMAP System.

Aufstellen des Taubenschlages

Mein (LAN-) Server arbeitet unter der Stable-Version von Debian (lenny). In Lenny ist die nicht mehr ganz taufrische Version 1.0.15 von Dovecot enthalten. Über das offizielle Backports-Repository besteht die einfache Möglichkeit die Version 1.2.15 zu installieren.

aptitude install -t lenny-backports dovecot-common dovecot-imapd

Da sowohl das Paket dovecot-imapd als auch das Paket cyrus-imapd-2.2 das virtuelle Paket imap-server zur Verfügung stellen, wurde bei mir mit der Installation von Dovecot gleich Cyrus-IMAP deinstalliert. Da das Migrations-Skript direkt auf die Dateien von Cyrus-IMAP zugreift ist dies allerdings kein Problem.

Als Mail-Server (MTA) kommt die mit Debian Lenny ausgelieferte Version 2.5.5 von Postfix zum Einsatz.

Einrichten des Taubenschlages

Die mitgelieferte Konfigurationsdatei /etc/dovecot/dovecot.conf ist gut dokumentiert und die ideale Ausgangsbasis für die persönliche Konfiguration.

In meiner persönlichen Konfiguration setze ich die folgenden Anforderungen um:

  • Der Zugriff auf den IMAP-Server kann nur mit Verschlüsselung (SSL / TLS) erfolgen.

  • Der IMAP-Server hat eine eigenen Benutzerdatenbank. Für einen IMAP-Account muss der Benutzer nicht im System angelegt werden.

  • Die Authentifizierung eines Benutzers läuft nicht über “plain text” Passwörter.

  • Dovecot stellt virtuelle Mailboxen für Postfix zur Verfügung. Postfix stellt eMails an Dovecot zu.

  • Postfix nutzt die Benutzerdatenbank von Dovecot zur Authentifizierung von SMTP Sitzungen.

  • Über benutzerspezifische Sieve-Scripts erfolgt eine Sortierung / Filterung der eMails auf dem Server.

  • Dovecot stellt öffentliche Ordner für alle Benutzer zur Verfügung.

  • Postfix kann direkt eMails in öffentliche Ordner zustellen.

Ich stelle im folgenden die einzelnen Abschnitte der Konfigurationsdatei vor, mit denen ich die oben aufgeführten Anforderungen umgesetzt habe.

Zugang zum Taubenschlag sicher (SSL /TLS)

Dovecot unterstützt sowohl die Kommunikation über den Secure Socket Layer (SSL) auf Port 993 als auch die aktuelle Variante über die Transport Layer Security (TLS) auf Port 143. Damit ein Client eine Verbindung über SSL (imaps) aufbauen kann, muss dieses Protokoll in der Liste der aktivierten Protokoll aufgeführt sein (protocols).

# served protocolls (imap, imaps, pop3, pop3s, managesieve)
protocols = imap imaps

#
# ssl settings
#

# enforce ssl connections
ssl = required

# own key
ssl_key_file = /etc/ssl/private/imap.key.pem
# own certificate
ssl_cert_file = /etc/ssl/certs/imap.crt

# ca certificate
ssl_ca_file = /etc/ssl/certs/ca.crt

Damit der Server keine unverschlüsselten Verbindungen mehr annimmt ist die Variable ssl auf den Wert required zu setzen. Diese Variable ist erst ab der Version 1.2 von Dovecot verfügbar.

Wichtig für die vollständige Konfiguration von SSL / TLS ist die Konfiguration des Zertifikats des IMAP-Servers (ssl_cert_file), des privaten Schlüssels des Servers (ssl_key_file) sowie dem Zertifikat der Zertifizierungsstelle CA (ssl_ca_file).

Liste der Tauben im Taubenschlag festlegen

Dovecot kann auf die im System angelegten Benutzer zugreifen und im Home-Verzeichnis jedes dieser Benutzer die eMails in einem Maildir Verzeichnis verwalten. Dieses Standardverhalten gefällt mir nicht. Dies war damals schon der Grund, warum ich mich für Cyrus-IMAP entschieden hatte. Dieser IMAP-Server verwaltet eine eigene Liste an Benutzern und legt alle eMails in einem zentralen Verzeichnis ab.

Auch Dovecet bietet die Möglichkeit zur Verwaltung eines eigenen Benutzerverzeichnisses. Dabei unterscheidet Dovecot zwischen einer Datenbank für die Authentifizierung – Wer darf rein? - und einer Datenbank mit weiteren Benutzerinformationen – Rechte für Maildir Dateien. Der Einfachheit halber verwende ich für beide Zwecke – Authentifizierung und Benutzerinformationen – die gleiche Datenbank.

Ich habe mich für eine “Datenbank” im passwd-file Format entschieden. Alle Informationen werden dabei in einer Textdatei abgelegt, die im Aufbau einer von UNIX-Systemen bekannten passwd Datei angelehnt ist. Die Speicherung der Kennwörter erfolgt dabei nicht im Klartext sondern als MD5-Hash.

fritz:{CRAM-MD5}e9e003757faee7af7304a45ee5a66a472226b42418c1050c84030d79d9b95895:1010:1010
hans:{CRAM-MD5}cac9702fae5f9dd3deef390b4361210eaf5889880a26b3ef8b5f79f8a1e43716:1010:1010
frida:{CRAM-MD5}f16f9cd57afad6931bff9508ef68ea2db1b62513b604cf995e4f882bed6d4f1a:1010:1010

Alle Benutzer erhalten über die Datei die gleiche UserID (1010) und die gleiche Gruppen ID (1010). Im System sind diese beiden IDs dem Benutzer vmail und der Gruppe vmail zugeordnet. Somit werden alle Dateien der Benutzer (Maildir, Sieve-Scripts, etc.) auf dem Dateisystem mit dem Benutzer vmail und der Gruppe vmail abgelegt.

# root folder for imap mailboxes (Maildir)
mail_location = maildir:/srv/imap/%n

#
# authentication processes
#

auth default {
  # space separated list of wanted authentication mechanisms:
  #   plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi
  mechanisms = cram-md5

  # file for the authentication (password check)
  passdb passwd-file {
    # path to passdb (lookup username %n only)
    args = username_format=%n /etc/dovecot/dovecot-user.db
  }

  # file for additional user information
  userdb passwd-file {
    # path to passdb (lookup username %n only)
    args = username_format=%n /etc/dovecot/dovecot-user.db
  }
}

Über die mail_location wird der Pfad zu den einzelnen Maildir-Verzeichnissen der Benutzer festgelegt. Bei der Festlegung des Verzeichnisses können Variablen verwendet werden. Variablen beginnen in Dovecot mit dem Prozent-Zeichen %. Die von mir verwendete Variable %n enthält nur den Benutzernamen des Accounts. Somit wird für jeden Benutzer im Verzeichnis /srv/imap ein Maildir-Verzeichnis angelegt, das seinem Benutzernamen entspricht.

Über die Variable mechanisms werden die Authentifizierungsverfahren festgelegt, die vom IMAP-Server Clients angeboten werden. Die Vorgabe für diese Einstellung ist plain. Da ich allerdings nur das Verfahren mit einem MD5-Hash anbieten möchte, gebe ich an dieser Stelle den Wert cram-md5 an. Durch die Festlegung auf nur diesen einen Mechanismus kann sich kein Client mehr mit einer Kennwortübermittlung im Klartext (plain) mehr beim Server anmelden.

Sowohl für die Datenbank zur Authentifizierung (passdb) als auch für die Datenbank mit dem Benutzerinformationen (userdb) setze ich die passwd-file “Datenbank” ein. Den vollständigen Pfad zu dieser Datei gibt man über die Variable args an. Durch den zusätzlichen Parameter username_format lege ich auch hier fest, dass nur mit dem Benutzernamen – nicht mit der vollständigen eMail Adresse – in den Datenbanken nach einem Eintrag gesucht wird.

Für die Anmeldung am IMAP-Server kann als Benutzername nun entweder nur der Name des Accounts oder auch die zugehörige eMail-Adresse angegeben werden. So entspricht z.B. dem Benutzernamen fritz die eMail-Adresse fritz@example.local.

Einlieferung von Mitteilungen in den Taubenschlag

Der schönste IMAP-Server bringt nichts, wenn er nicht mit eMails bestückt wird, die man über den Server abrufen und verwalten kann. Hier kommt der MTA (message transfer agent) Postfix ins Spiel. Wenn dieser feststellt, dass eine empfangene eMail einem lokalen Benutzer zugestellt werden muss, ruft er den MDA (message delivery agent) auf, der sich um die “Zustellung” der Mitteilung kümmert. In Dovecot übernimmt der LDA (local delivery agent) deliver die Aufgabe der Zustellung von eMails in die Postfächer der einzelnen Benutzer.

#
# LDA (local delivery agent) specific settings
#

protocol lda {
  # address to use when sending rejection mails.
  postmaster_address = postmaster@example.local

  # hostname to use in various parts of sent mails, eg. in Message-Id.
  hostname = imap.example.local
}

Über die Variable postmaster_address gebe ich die eMail-Adresse an, die beim Versenden von eMail durch Dovecot selbst als Absender verwendet wird. Den hostname setze ich schließlich auf einen Alias meines Rechners. Gibt man diesen Wert nicht an, wird der “echte” Name des Rechners verwendet.

Der LDA benötigt Zugriff auf die Benutzerdatenbank, damit geprüft werden kann ob für den Empfänger der zuzustellenden eMail auch ein Postfach existiert. Ein entsprechender (UNIX-)Socket wird im auth Abschnitt – bei der Konfiguration der Authentifizierungs- und der Benutzerdatenbank – eingerichtet.

  # sockets for external programs
  socket listen {
    # access for LDA to check for valid recipient
    master {
      path = /var/run/dovecot/auth-master
      mode = 0600
      user = vmail # User running deliver
      group = vmail
    }
 }

Es wird ein Socket /var/run/dovecot/auth-master eingerichtet. Der Socket kann nur vom Benutzer vmail (Systembenutzer) genutzt werden. Es ist daher bei der Einbindung des LDA (deliver) darauf zu achten, dass dieser als Benutzer vmail ausgeführt wird.

Dovecot ist nun fertig eingerichtet um eMails zuzustellen; fehlt noch die Konfiguration von Postfix, damit dieser Mitteilungen auch an Dovecot zustellt.

In der Konfigurationsdatei master.cf von Postfix wird ein neuer Transport für die Zustellung über das Dovecot Programm deliver (LDA) eingerichtet.

dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail
    argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop}
    -m ${extension}

Über den Parameter user wird dabei festgelegt, dass das Programm deliver mit den Rechten des Benutzer vmail ausgeführt wird. Dies ist genau der Account, für den der Zugriff auf den Socket zum Zugriff auf die Dovecot-Benutzerdatenbank freigeschaltet ist.

Mitteilungen werden mit dem Envelope-From ${sender} und dem Empfänger / Postfach ${user}@${nexthop} zugestellt. Durch die Verwendung der Variablen %n statt %u bei der Konfiguration der Benutzerdatenbank (userdb passwd-file) wird nur mit dem ${user} Teil der eMail-Adresse ein Eintrag in der Benutzerdatenbank gesucht.

#
# settings for delivery to virtual domains
#

# only one recipient per call to service / transport
dovecot_destination_recipient_limit = 1

# domains with virtual mailboxes
virtual_mailbox_domains = example.local
# transport to use for virtual mailboxes
virtual_transport = dovecot

Die (lokale) Domain der Postfächer, die durch Dovecot verwaltet wird, wird in Postfix als Domain mit virtuellen Postfächern (virtual_mailbox_domains) konfiguriert. Sollen eMails an diese Domain(s) zugestellt werden, wird der Transport (virtual_transport) dovecot verwendet, denn wir im letzten Schritt in der master.cf angelegt haben.

Gemeinsames Postfach für alle Tauben

Ein gerne von mir genutztes Feature von Cyrus-IMAP sind die öffentlichen / gemeinsamen Ordner. Diese Möglichkeit bietet auch Dovecot durch die Einrichtung eines eigenen public Namespace.

# personal mailboxes
namespace private {
  separator = .
  prefix =
  inbox = yes
  subscriptions = yes
}

# public mailboxes
namespace public {
  separator = .
  prefix = Public.
  location = maildir:/srv/imap/public
  # each user manages the public folder subscriptions by it's own
  subscriptions = no
}

Wenn man keine öffentlichen Ordner nutzt, muss man auch keinen expliziten Namespace für die privaten Postfächer anlegen. Da ich habe einen Namespace public definiere, ist auch die Definition des Namespace private anzugeben.

In den persönlichen Postfächern befindet sich die INBOX des Benutzers (inbox = yes). Auch wird dort die Liste der vom Benutzer abonnierten Ordner geführt (subscriptions = yes).

Alle öffentlichen Ordner werden bei mir unter dem Prefix Public geführt. Die Maildir-Verzeichnisse der einzelnen Ordner werden unter dem Pfad /srv/imap/public abgelegt. Es ist dabei zu beachten, dass der “Wurzel-Ordner” Public keine echtes Maildir ist und somit darin auch keine Mitteilungen gespeichert werden können. Da in den öffentlichen Ordnern keine eigenen Abonnementlisten verwaltet werden sollen ist die Variable subscriptions auf no zu setzen.

Damit von Postfix direkt Mitteilungen in die einzelnen öffentlichen Ordner zugestellt werden können nutze ich einen kleinen Trick. Ich lege einen neuen Benutzer public an. Durch die Konfiguration von /srv/imap/%n als mail_location sind die persönlichen Ordner und die öffentlichen Ordner aller Benutzer identisch. Über die bereits erfolgte Freischaltung von extensions bei der Zustellung von eMails an Dovecot – Parameter -m beim Aufruf von deliver im Postfix Service – kann ich nun direkt eMails in die Ordner einsortieren.

public::1000:1000

Wird eine eMail an die Adresse public+postmaster@example.local adressiert, so wird diese in den Ordner postmaster (= den öffentlichen Ordner postmaster) einsortiert. Über entsprechende Eintragungen in der virtual_maps von Postfix können somit eMails von administrativen Accounts sehr einfach in für alle Benutzer zugänglichen öffentlichen Ordnern gespeichert werden.

Persönliches Sekretariat für Tauben

Bereits in Cyrus-IMAP habe ich die Möglichkeiten von Sieve-Scripts stark genutzt. Somit werden z.B. alle abonnierten Newsletter und Mitteilungen an Mailinglisten in jeweils eigene Mail-Ordner einsortiert. Im Posteingang landen somit nur noch “normale” eMails die auf diese Art und Weise nicht untergehen können. Die Bearbeitung von Newslettern und Mailinglisten kann ich somit getrost auf später verschieben.

Auch Dovecot bietet die Möglichkeit zur Nutzung von Sieve-Scripts. Hierzu ist jedoch die Aktivierung eines Plugins erforderlich. Mit Plugins kann die Funktionalität von Dovecot ohne direkt Eingriff in die Quellen von Dovecot selbst erweitert werden. Ein weiteres Plugin stellt z.B. die Möglichkeit zur Verwaltung von Quotas (max. Größe einer Mailbox) zur Verfügung.

Das Plugin wird durch mail_plugins = sieve in der Konfiguration des LDA aktiviert.

#
# LDA (local delivery agent) specific settings
#

protocol lda {
  # address to use when sending rejection mails.
  postmaster_address = postmaster@olymp.local

  # hostname to use in various parts of sent mails, eg. in Message-Id.
  hostname = imap.olymp.local

  # enable sieve plugin
  mail_plugins = sieve
}

Die Konfiguration des Plugins selbst erfolgt in einem Abschnitt plugin der Konfigurationsdatei. Ich lege dort nur den Pfad zu den (benutzerspezifischen) Sieve-Scripts fest. Auch wird wird durch den Parameter %n vermieden die vollständige eMail-Adresse der Benutzer im Dateinamen angeben zu müssen.

#
# plugin configuration
#

plugin {
  # location of the sieve scripts (username.sieve)
  sieve = /srv/imap/sieve-scripts/%n.sieve
}

Wenn für den Benutzer kein Sieve-Script ausgeführt werden soll, reicht es aus einfach keine entsprechende Datei in das Verzeichnis /srv/imap/sieve-scripts zu legen.

Postversand nur für Tauben des Taubenschlages

Normalerweise benötigt Postfix als MTA (message transfer agent) keine Informationen über Benutzer eines IMAP-Servers bzw. eines Netzwerks. Möchte man jedoch den Benutzern die Möglichkeit geben, auch aus nicht vertrauenswürdigen Netzwerken wie z.B. dem Internet über den eigenen Mail-Hub eMails zu versenden, wird oft eine Authentifizierung bei der Einlieferung der eMails erforderlich.

Dovecot bietet die Möglichkeit die eigene Benutzerdatenbank Postfix für den Zweck der Authentifizierung beim Einliefern von eMails zur Verfügung zu stellen. Für den Benutzer hat das den Vorteil, dass er sich für die Anwendung eMail nur ein Kennwort inkl. Benutzernamen merken muss.

Im Abschnitt auth der Dovecot-Konfiguration wird ein weiterer Socket für die Kommunikation mit Postfix zum Zwecke der Authentifizierung eingerichtet.

auth default {
  socket listen {
    # access for postfix to check for valid SMTP-Auth login
    client {
      # /private/auth for chrooted postfix
      path = /var/spool/postfix/private/auth
      mode = 0600
      user = postfix # User running postfix
      group = postfix
    }
  }
}

Der Socket wird im (chroot-)Vezeichnis von Postfix (/var/spool/postfix) angelegt. Zugriff auf den Socket bekommt nur der Benutzer postifx, unter dem der Daemon läuft.

In Postfix (main.cf) müssen die folgenden Einträge vorgenommen werden, damit Postfix zur Authentifizierung auf den Socket zugreift.

# enable sasl authentication for receiving mails
smtpd_sasl_auth_enable = yes
# use dovecot SASL
smtpd_sasl_type = dovecot
# (relative) path to the socket for authentication
smtpd_sasl_path = private/auth

Wichtig ist neben der Aktivierung der SMTP-Authentifizierung (smtpd_sasl_auth_enable) die Auswahl der Authentifzierung über Dovecot (smtpd_sasl_type) und die Festlegung des (relativen) Pfades zum Socket (smtpd_sasl_path).

Der Taubenschlag ist fertig eingerichtet

Mit der oben beschriebenen Konfiguration arbeite ich nun seit einigen Tagen und bin mehr als zufrieden. Auf der gleichen Hardware läuft Dovecot wesentlich schneller und flotter als Cyrus-IMAP. Auch kommt mir das gesamte System wesentlich stabiler vor – allerdings hatte ich auch mit Cyrus-IMAP keine Absturz des Daemons zu beklagen.

Wichtig ist mir aber das Gefühl, endlich ein sauber konfiguriertes Mail-System auch auf Seiten IMAP und eine sichere Konfiguration zu haben. Das ich mich nicht mehr mit den Untiefen von Cyrus-SASL beschäftigen muss, ist ein mehr als angenehmer Nebeneffekt.

Bei nächster Gelegenheit werde ich mich mit der Vergabe von Rechten (ACLs) in öffentlichen Ordnern beschäftigen. Meine Erkenntnisse werde ich in einem eigenen Artikel beschreiben.