Hetzner - DokuWiki

DebianMailserver2

Inhaltsverzeichnis

Tutorial: Mailserver mit virtuellen Maildomains auf Entryservern mit Debian woody

Motivation

Nahezu jeder Eigentümer eines Entry-Servers braucht auf diesem auch einen Mailserver-Dienst. Leider sieht Hetzner hier keinen Handlungsbedarf zur Unterstützung von Neukunden. Man hofft auf die Community.

Das Netz ist voll von How-Tos zur Installation von Mailservern. Diese Quellen verzichten jedoch in aller Regel auf Erläuterungen und allzu oft auch auf Referenzen zu entsprechenden Dokumentationen. Hinzu kommt, dass wesentliche Bereiche (wie z.B. Cyrus-SASL oder PAM) überhaupt nur unzureichend dokumentiert sind. Stößt man also auf ein Problem, steht man gleich im Regen.

Ein Blick in das Hetzner-Forum zeigt, dass sehr viele Nutzer dieses Problem selbst leidvoll erfahren haben.

Dieses Tutorial reiht sich nun in die lange Liste bereits existierender Anleitungen ein, in der Hoffnung, dem spezifischen Nutzerkreis von Entryserver-Admins eine Hilfestellung zu sein, mit der sie einen laufenden Server aufsetzen können.

Scope

Es wird von einem LAMP-System ausgegangen, d.h. Apache, MySql und PHP4 sollten bereits vorhanden sein. PHP4 wird im Laufe dieses Tutorials jedoch auf ein Backport der Version 4.3.8 hochgezogen, um eine Reihe von Fehlern in der stable-Version zu umgehen.

Auch die anderen Pakete sind Backports der entsprechenden Sarge-Pakete. Dazu gehören:

   * Postfix 2.0.16
   * Cyrus 2.1.15
   * Web-Cyradm? 0.5.4

Ich verzichte dabei auf die Installation von Virenscanner, Spamfilter und Webmail-Interface. Diese Dienste werden hier im hauseigenen Mailserver zur Verfügung gestellt und stellen daher für uns eher ein "Nice-to-have" dar als eine Notwendigkeit.

Wer sich berufen fühlt, möge nicht zögern, die entsprechenden Verweise in diesem Wiki mit Inhalt zu füllen!

Der Mailserver hat aber alle Features, die auch im alten Tutorial "in Aussicht" gestellt wurden:

  • IMAP mit TLS und SSL Unterstützung
  • SMTP mit PLAIN und LOGIN Authentication, unverschlüsselt oder mit TLS
  • Virtual Hosts
  • Quotas pro Virtual Host und Mail Account
  • Mail User unabhängig von System User
  • Serverseitige Filter zum sortieren der Nachrichten, über Web-Frontend von jedem Benutzer selbst zu verwalten
  • Administration über Web-Frontend (leider nur teilweise...)

Quellen:

DebianMailserver
http://www.delouw.ch/linux/Postfix-Cyrus-Web-cyradm-HOWTO/html/
http://www.workaround.org/articles/ispmail-sarge/
http://postfix.state-of-mind.de/patrick.koetter/cyrus_sasl/vortrag_cyrus_SASL.pdf
http://linuxsilo.net/articles/postfix.html

Diskussion:

Für Anregungen, Korrekturen oder sonstige Kommentare steht ein Thread im Hetzner-Forum zur Verfügung.

Auf geht's:

Neue Einträge in /etc/apt/sources.list

# Mailserver
deb http://people.debian.org/~hmh/woody/ hmh/cyrus/
deb http://people.debian.org/~hmh/woody/ hmh/postfix/
deb http://people.debian.org/~hmh/woody/ hmh/misc/
deb http://people.debian.org/~aurel32/BACKPORTS stable main
# PHP4 4.3.8
#deb http://www-users.cs.umn.edu/~sdier/debian updates/wup/
deb http://debian.moolfreet.com ./

Package-List aktualisieren

~$ apt-get update

Pakete installieren

Ausgehend von einem LAMP-System werden apache und mysql hier nicht installiert. php4 allerdings wird auf eine neuere Version gezogen.

~$ apt-get install php4 php4-mysql php4-pear php4-imap \
                   postfix postfix-mysql postfix-doc postfix-tls postfix-pcre \
                   sasl2-bin libsasl2 libsasl2-modules libpam-mysql \
                   cyrus21-admin cyrus21-clients cyrus21-imapd cyrus21-pop3d \
                   metamail openssl

Pakete konfigurieren

Im Wesentlichen können die Vorgaben übernommen werden.

Bei der Installation wird automatisch eine Gruppe "sasl" angelegt. Der User postfix muss Mitglied dieser Gruppe sein, um aus seiner chroot-Umgebung auf den saslauthd (s.u.) zugreifen zu können. Das müssen wir leider von Hand machen:

~$ usermod -G sasl postfix

web-cyradm installieren

Es bietet sich an die CVS Version von Web-cyradm zu nutzen, sie ist stabil (jedenfalls nicht schlechter als die stable), hat aber deutlich bessere Features wie die Möglichkeit des Passwortänderns für Domainadmins.

~$ cd /var/www
~$ wget http://www.web-cyradm.org/web-cyradm-cvs-latest.tar.gz
~$ tar -xvzf web-cyradm-cvs-latest.tar.gz
~$ mv /var/www/web-cyradm-cvs-latest /var/www/web-cyradm
~$ mkdir /var/log/web-cyradm
~$ chown www-data /var/log/web-cyradm

Datenbank anlegen

Passwort von User admin im Skript /var/www/web-cyradm/scripts/create_mysql.sql ändern!

~$ /usr/bin/mysql -u root -p < \
      /var/www/web-cyradm/scripts/insertuser_mysql.sql

(Passwort des Users root in der Datenbank, standardmäßig leer.)

~$ /usr/bin/mysql mail -u mail -p < \
      /var/www/web-cyradm/scripts/create_mysql.sql

(Passwort des gerade eingetragenen Users mail, standardmäßig "secret", wie im Script /var/www/web-cyradm/scripts/create_mysql.sql. Dieses Passwort sollte nicht geändert werden, weil es bei der Authentifizierung zwischen postfix und mysql verwendet wird.)

Postfix konfigurieren

Zwei kleine Änderungen in /etc/postfix/master.cf:

An den Aufruf des smtpd die Option -v (ausführliche Meldungen) anhängen:

smtp      inet  n       -       -       -       -       smtpd -v

Die Aufrufparameter von Cyrus ändern. (Option "-e" existiert nicht, dafür Option "-r {sender}" hinzufügen, außerdem müssen die Anführungszeichen der -m Option entfernt werden (WICHTIG!) (bzw. die ganze zeile einfuegen weil nicht vorhanden (debian/sarge)):

cyrus     unix  -       n       n       -       -       pipe
  flags=R user=cyrus argv=/usr/sbin/cyrdeliver -r ${sender} -m ${extension} ${user}

Individuelle Anpassung und Anbindung an die mySql-Tabellen in /etc/postfix/main.cf:

mydestination = ..., mysql:/etc/postfix/mysql-mydestination.cf
mailbox_transport = cyrus
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual.cf
sender_canonical_maps = mysql:/etc/postfix/mysql-canonical.cf
# smtpd zur Verwendung von sasl überreden
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions =
          permit_sasl_authenticated,
          permit_mynetworks,
          reject_unauth_destination
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
broken_sasl_auth_clients = yes

Nun müssen die oben verwendeten Dateien (mysql-*.cf) angelegt werden.

/etc/postfix/mysql-virtual.cf:

#
# mysql config file for alias lookups on postfix
# comments are ok.
#
# the user name and password to log into the mysql server
hosts = localhost
user = mail
password = secret
# the database name on the servers
dbname = mail
# the table name
table = virtual
select_field = dest
where_field = alias
additional_conditions = and status = '1'

/etc/postfix/mysql-canonical.cf:

# mysql config file for canonical lookups on postfix
# comments are ok.
#
# the user name and password to log into the mysql server
hosts = localhost
user = mail
password = secret
# the database name on the servers
dbname = mail
# the table name
table = virtual
select_field = alias
where_field = username
additional_conditions = and status = '1' limit 1

/etc/postfix/mysql-mydestination.cf:

# mysql config file for local domain (like sendmail's sendmail.cw) lookups on postfix
# comments are ok.
#
# the user name and password to log into the mysql server
hosts = localhost
user = mail
password = secret
# the database name on the servers
dbname = mail
# the table name
table = domain
select_field = domain_name
where_field = domain_name

Da in diesen Dateien jeweils das Passwort für den Zugriff auf den SQL-Server steht, werden sie vor neugierigen Blicken geschützt:

~$ chown postfix /etc/postfix/mysql-*.cf
~$ chmod 600 /etc/postfix/mysql-*.cf

sasl konfigurieren

Dazu legen wir die Datei /etc/postfix/sasl/smtpd.conf an:

# Global parameters
log_level: 3
pwcheck_method: saslauthd
mech_list: PLAIN LOGIN

PAM konfigurieren

Datei /etc/pam.d/smtp anlegen mit folgendem Inhalt:

auth sufficient pam_mysql.so user=mail passwd=secret host=localhost \
                             db=mail table=accountuser usercolumn=username \
                             passwdcolumn=password crypt=1 logtable=log \
                             logmsgcolumn=msg logusercolumn=user loghostcolumn=host \
                             logpidcolumn=pid logtimecolumn=time
auth sufficient pam_unix_auth.so
account sufficient pam_mysql.so user=mail passwd=secret host=localhost \
                              db=mail table=accountuser usercolumn=username \
                              passwdcolumn=password crypt=1 logtable=log \
                              logmsgcolumn=msg logusercolumn=user loghostcolumn=host \
                              logpidcolumn=pid logtimecolumn=time
account sufficient pam_unix_acct.so

Da auch in dieser Datei das Passwort für den SQL-Server enthalten ist:

~$ chmod 640 /etc/pam.d/smtp

Diese Datei wird in identischer Form auch für imap, pop und sieve benötigt.

~$ ln -s /etc/pam.d/smtp /etc/pam.d/imap
~$ ln -s /etc/pam.d/smtp /etc/pam.d/pop
~$ ln -s /etc/pam.d/smtp /etc/pam.d/sieve

Die chroot-Umgebung für postfix aufbohren

Dazu müssen einige Datein und die Sockets von mysql und saslauthd umgesiedelt werden.

a) PAM-Module und -Konfiguration

~$ ln -s /etc/pam.conf /var/spool/postfix/etc/
~$ mkdir -p /var/spool/postfix/etc/pam.d
~$ ln -s /etc/pam.d/smtp /var/spool/postfix/etc/pam.d/
~$ mkdir -p /var/spool/postfix/lib/security
~$ ln -s /lib/security/pam_mysql.so /var/spool/postfix/lib/security/

b) mysql

~$ mkdir -p /var/spool/postfix/var/run/mysqld
~$ chown mysql /var/spool/postfix/var/run/mysqld
~$ /etc/init.d/mysql stop
~$ rm -r /var/run/mysqld
~$ ln -s /var/spool/postfix/var/run/mysqld /var/run/mysqld
~$ /etc/init.d/mysql restart

c) saslauthd

Zuerst das Verzeichnis anlegen und mit den benötigten Rechten ausstatten.

~$ mkdir -p /var/spool/postfix/var/run/saslauthd
~$ chgrp sasl /var/spool/postfix/var/run/saslauthd
~$ chmod 710 /var/spool/postfix/var/run/saslauthd

saslauthd liest seine Defaults beim Starten aus der Datei /etc/default/saslauthd. Die muss angepasst und ergänzt werden:

# This needs to be uncommented before saslauthd will be run automatically
START=yes
# You must specify the authentication mechanisms you wish to use.
# This defaults to "pam" for PAM support, but may also include
# "shadow" or "sasldb", like this:
# MECHANISMS="pam shadow"
MECHANISMS="pam"
PWDIR="/var/spool/postfix/var/run/saslauthd"
PARAMS="-m ${PWDIR}"

Das Startscript von saslauthd verwendet dpkg-statoverride, um das Verzeichnis zu ermitteln und ggf automatisch anzulegen. Darum tragen wir unser neues Socket-Verzeichnis? dort ein:

~$ dpkg-statoverride --remove /var/run/saslauthd
~$ dpkg-statoverride --add root sasl 710 /var/spool/postfix/var/run/saslauthd

Außerdem möchten wir auch für saslauthd einen Link an gewohnter Stelle (/var/run/saslauthd) haben:

~$ rm -r /var/run/saslauthd
~$ ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd

d) ACHTUNG: Neustart

Da /var/run/ von /etc/init.d/bootmisc.sh beim Booten "aufgeräumt" wird, brauchen wir ein Script, das nach dem Neustart die oben angelegten Links wieder anlegt.

Wir legen eine Datei /root/socketlinks mit folgendem Inhalt an:

#!/bin/sh
ln -s /var/spool/postfix/var/run/mysqld /var/run/mysqld
ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd

Dann klinken wir dieses Script in den Startprozess von Debian ein:

~$ chmod 750 /root/socketlinks
~$ ln -s /root/socketlinks /etc/rcS.d/S99socketlinks


e) saslauthd (Alternative)

„Wenn Moses nicht zum Berg kommt, kommt der Berg halt zu Moses“, oder auch einfach genau das gegenteil von c) & d). Hard link /var/run/saslauthd/* auf /var/spool/postfix/var/run/saslauthd/. Als erstes ein paar Modifikationen an /etc/init.d/saslauthd wie folgt (die freigestellten Sachen):

   #!/bin/sh -e
   NAME=saslauthd
   DAEMON="/usr/sbin/${NAME}"
   DESC="SASL Authentication Daemon"
   DEFAULTS=/etc/default/saslauthd
   PWDIR=/var/run/saslauthd
   PIDFILE="/var/run/${NAME}/saslauthd.pid"
   mklinks() {
       sleep 1
       cd /var/spool/postfix/var/run/saslauthd/
       ln /var/run/saslauthd/* .
       echo "Links zum Postfix chroot wurden erstellt."
   }
   rmlinks() {
       rm -f /var/spool/postfix/var/run/saslauthd/*
       echo "Links zum Postfix chroot wurden entfernt."
   }
   createdir() {
       # $1 = user
       # $2 = group
       # $3 = permissions (octal)
       # $4 = path to directory
       [ -d "$4" ] || mkdir -p "$4"
       chown -c -h "$1:$2" "$4"
       chmod -c "$3" "$4"
   }
   test -f "${DAEMON}" || exit 0
   # Source defaults file; edit that file to configure this script.
   if [ -e "${DEFAULTS}" ]; then
       . "${DEFAULTS}"
   fi
   # If we're not to start the daemon, simply exit
   if [ "${START}" != "yes" ]; then
       exit 0
   fi
   # If we have no mechanisms defined
   if [ "x${MECHANISMS}" = "x" ]; then
       echo "You need to configure ${DEFAULTS} with mechanisms to be used"
       exit 0
   fi
   # Add our mechanimsms with the necessary flag
   PARAMS="${PARAMS} -a ${MECHANISMS}"
   START="--start --quiet --pidfile ${PIDFILE} --startas ${DAEMON} --name ${NAME} -- ${PARAMS}"
   # Consider our options
   case "${1}" in
       start)
           echo -n "Starting ${DESC}: "
           dir=`dpkg-statoverride --list $PWDIR`
           test -z "$dir" || createdir $dir
           if start-stop-daemon ${START} >/dev/null 2>&1 ; then
               echo "${NAME}."
           else
               if start-stop-daemon --test ${START} >/dev/null 2>&1; then
                   echo "(failed)."
                   exit 1
               else
                   echo "${DAEMON} already running."
                   exit 0
               fi
           fi
           mklinks
           ;;
       stop)
           echo -n "Stopping ${DESC}: "
           if start-stop-daemon --stop --quiet --pidfile "${PIDFILE}" \
           --startas ${DAEMON} --retry 10 --name ${NAME} \
           >/dev/null 2>&1 ; then
               echo "${NAME}."
           else
               if start-stop-daemon --test ${START} >/dev/null 2>&1; then
                   echo "(not running)."
                   exit 0
               else
                   echo "(failed)."
                   exit 1
               fi
           fi
           rmlinks
           ;;
       restart|force-reload)
           $0 stop
           exec $0 start
           ;;
       *)
           echo "Usage: /etc/init.d/${NAME} {start|stop|restart|force-reload}" >&2
           exit 1
           ;;
   esac
   exit 0


Die entsprechenden Zielverzeichnisse anlegen und mit Rechten versehen.

   mkdir -p /var/spool/postfix/var/run/saslauthd
   chown root.sasl /var/spool/postfix/var/run/saslauthd

Das wars eigentlich auch schon. saslauthd neu starten und schon sollte alles problemlos funktionieren. Dieser Weg ist auch zu empfehlen, wenn /var auf einer extra Partition liegt.

Test

Vor dem Test müssen die Dienste neu gestartet werden:

~$ /etc/init.d/saslauthd restart (oder start, falls der Dienst noch nicht lief)
~$ /etc/init.d/postfix restart
~$ /etc/init.d/mysql restart

Wir testen die Verbindung über telnet und geben als Username und Passwort die Base64-kodierten Daten von cyrus/secret an, die beim Erzeugen der Datenbank bereits in der Tabelle accountuser angelegt werden.

Um diesen kodierten String zu erhalten, gibt man folgenden Befehl an:

~$ perl -MMIME::Base64 -e 'print encode_base64("cyrus\0cyrus\0secret");'

Dann kann's losgehen:

~$ telnet localhost 25
   220 debian ESMTP Postfix (Debian/GNU)
 > EHLO test
   250-debian
   250-PIPELINING
   250-SIZE 10240000
   250-VRFY
   250-ETRN
   250-AUTH LOGIN PLAIN
   250-AUTH=LOGIN PLAIN
   250-XVERP
   250 8BITMIME
 > auth plain Y3lydXMAY3lydXMAc2VjcmV0
   235 Authentication successful
 > quit

So sollte die Kommunikation mit dem smtpd aussehen. Falls die Authentifzierung nicht akzeptiert wird, sollte man /var/log/mail.log und ggf. /var/log/mysql.log konsultieren, um festzustellen, welche Fehlermeldungen aufgetaucht sind.

Nach erfolgreichem Test kann man in /etc/postfix/master.cf die Option -v vom Eintrag des smtpd wieder entfernen. Sonst wachsen die Logfiles zu schnell.

Zertifikat für Postfix und Cyrus (IMAP und POP3) erzeugen:

In diesem Beispiel wird ein selbstsigniertes CA-Zertifikat verwendet. Eleganter und sauberer wäre die Erzeugung einer Zertifikatsanforderung, die anschließend durch eine eigene oder noch besser durch eine kommerzielle Zertifizierungsautorität (Certificate Authority = CA) signiert wird.

~$ openssl req -new -outform PEM -out /etc/postfix/mailserver.cert -newkey rsa:2048 \
               -nodes -keyout /etc/postfix/mailserver.key -keyform PEM -days 365 -x509

Es werden einige Felder des Zertifikates abgefragt, die mit sinnvollen Werten zu belegen sind:

Country Name (2 letter code) AU:
State or Province Name (full name) Some-State:
Locality Name (eg, city) []:
Organization Name (eg, company) Internet Widgits Pty Ltd:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:
Email Address []:

Nur das Feld "Common Name" sollte unbedingt den FQDN des Mailservers enthalten, weil die Clients sonst einen Warnhinweis zeigen, wenn der Server, mit dem Verbunden wird, nicht mit dem "Common Name" des Zertifikats übereinstimmt. Die restlichen Felder sollte man so belegen, dass der Sinn und Zweck des Zertifikates deutlich wird.

Die Rechte des privaten Schlüssels sollten restriktiv vergeben werden. Damit sowohl Postfix als auch Cyrus das Zertifikat verwenden können, müssen folgende Einstellungen gemacht werden:

~$ chgrp sasl /etc/postfix/mailserver.key
~$ chmod 640 /etc/postfix/mailserver.key

Postfix mit TLS

Folgende Einträge sind in der Datei /etc/postfix/main.cf hinzuzufügen:

# TLS
smtpd_use_tls = yes
# Wenn SMTP AUTH nur ueber sichere TLS-Verbindungen akzeptiert werden soll:
# smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/postfix/mailserver.cert
smtpd_tls_key_file = /etc/postfix/mailserver.key
smtpd_tls_CAfile = /etc/postfix/mailserver.cert

Restart und Test:

~$ postfix reload
~$ telnet localhost 25

Beim Test (wie oben) sollte nach dem EHLO zusätzlich die Zeile

   250-STARTTLS

erscheinen. Dann läuft Postfix mit TLS.

Cyrus konfigurieren

In der Datei /etc/imapd.conf müssen folgende Einträge geändert werden:

unixhierarchysep: yes
admins: cyrus
sasl_mech_list: PLAIN
sasl_pwcheck_method: saslauthd
tls_cert_file: /etc/postfix/mailserver.cert
tls_key_file: /etc/postfix/mailserver.key
tls_ca_file: /etc/ssl/certs/ca.pem

In der Datein /etc/cyrus.conf werden nur zwei Kommentarzeichen entfernt. So werden zusätzlich die Dienste imaps und pop3s bereitgestellt. VORSICHT: imap auf Port 143 wird von web-cyradm benötigt und darf deswegen keinesfalls deaktiviert werden.

Anschließend sollte cyrus neu gestartet werden:

~$ /etc/init.d/cyrus21 restart

Optional: Wenn man Cyrus auf einem ext2-Dateisystem installiert, sollte man die Mail-Verzeichnisse? sicherheitshalber auf Synchron stellen, um Datenverlust vorzubeugen. Auf einem Journal-Filesystem? wie z.B. ext3 ist das nicht nötig.

~$ cd /var/lib/cyrus
~& chattr +S user quota user/* quota/*
~$ chattr +S /var/spool/cyrus/mail /var/spool/cyrus/mail/*

web-cyradm konfigurieren

~$ cd /var/www/web-cyradm/config/
~$ cp conf.php.dist conf.php

In der Datei conf.php braucht nur eine Zeile geändert zu werden:

DOMAIN_AS_PREFIX = 1;

Der web-cyradm hat in der Version 0.5.4 die sehr unangenehme Eigenschaft, dass er keine Fehlermeldungen anzeigt, wenn etwas schief geht. Statt dessen kommt es häufig vor, dass man nach einem normalerweise korrekten Login ohne weitere Meldung direkt wieder auf der Login-Seite? landet. Um solche Probleme zu finden, sollte man auf die Version 0.5.3 downgraden, denn diese Version zeigt die Fehlermeldungen noch an. Nach erfolgreichen Debugging kann man dann wieder auf die Version 0.5.4 wechseln. Das geht durch einfaches Umbenennen der Verzeichnisse.

Link zum Download der Vorversion: http://www.web-cyradm.org/web-cyradm-0.5.3-1.tar.gz

Einge Stolperfallen:

  • php.ini: safe_mode = Off
  • php.ini: register_globals = On
  • php.ini: include_path = ".:/usr/share/php"

Außerdem darf entweder keine open_basedir Restriktion gesetzt sein, oder die Verzeichnisse /var/log/web-cyradm/ und /usr/share/php/ müssen explizit zugelassen werden.

FAQ

  • Wie lautet denn der User und das Passwort zum Login in das web-Cryadmin Frontend, wenn ich keines angegeben habe?
  • Benutzername ist 'admin' und das Passwort ist 'test'.
  • Web-Cyradm unterstützt keine Rechtevergabe für IMAP Ordner. Wie kann ich es ergänzen?
  • Als Ergänzung eignet sich WebSieve, das auch nebenbei SIEVE-Skripte verwalten kann.
    Openmailadmin wird als der Nachfolger von web-cyradm gehandelt und vereinigt alles unter einer Oberfläche.


© 2018. Hetzner Online GmbH. Alle Rechte vorbehalten.