Daniels Blog
27Mrz/1024

Howto Spickzettel: Debian Lenny Mailserver: Postfix-SSL Courier-SSL SASL TLS MD5-CRAM VirtualAliases Procmail ClamAV Spamassassin

Ich hatte immer mal wieder mit Mailservern zu tun. Leider war ich häufiger etwas verwirrt, da - je nach Setup - sehr viele verschiedene Komponenten miteinander kommunizieren müssen. Aus diesem Grund hier mein Spickzettel für einen Mailserver auf einem Internethost mit FQDN. Ausprobiert wurde es auf einem Debian Lenny.

Alle Verbindungen nach außen sind verschlüsselt oder mit MD5-Cram Pasword Hashes verschleiert. Eingehende Mail wird auf Spam und Viren geprüft und Benutzer können ihre Mail über IMAP lesen.

Im Bild oben sind Daemons gelb, Datenbanken grau und gesichtere Verbindungen grün.

Was machen die einzelnen Komponenten?

  • Postfix empfängt Mails, die Clients versenden wollen. Diese leitet er weiter an den richtigen Server im Internet. Außerdem entfängt Postfix Mails aus dem Internet für Benutzer mit Mailboxen auf dem Server.
  • VirtualAliases(Teil von Postfix) ist eine Datenbank mit der Postfix empfangene Mails den einzelnen Mailusern zuordnen kann.
  • Saslauthd authentifiziert User die Mail über Postfix per SMTP verschicken wollen. Er überprüft Username und Passwort mit MD5-Cram Hashes.
  • Sasldb ist die Datenbank, aus der Saslauthd Usernamen und Passwörter anfragen kann.
  • Courier-IMAP stellt dem Mailclient eines Nutzers die Mails aus seinem Maildir zur Verfügung
  • Courier-Authdaemon authentifiziert  User, die Mail über den Courier-IMAP lesen. Er überprüft Username und Passwort mit MD5-Cram Hashes.
  • Userdb (Teil von Courier) ist die Datenbank, aus der Courier-Authdaemon Usernamen und Passwörter anfragen kann.
  • Procmail ist ein Filter, durch den jede eingehende Mail laufen muss. Procmail reicht die Mail an den Spamfilter und den Virenscanner durch und liefert sie danach an den User aus.
  • Clamassassin ist ein kleines Tool, das eine Schnittstelle zwischen Procmail und ClamAV bildet. Es reicht die Mails nur durch an ClamAV.
  • Spamassassin (spamd) Spamchecker. Gibt jeder Mail einen Score, der aussagt wie wahrscheinlich es ist, dass die überprüfte Mail SPAM ist.
  • Maildir Mailbox Hier liegen die Mails der Benutzer des Systems. Es ist ein normales Verzeichnis im Dateisystem. IMAP-Clients können sie von hieraus abrufen.

Vorbereitung

Alle benötigten Pakete installieren

apt-get update && apt-get upgrade
apt-get install postfix postfix-doc postfix libsasl2-2 sasl2-bin libsasl2-modules courier-imap-ssl procmail spamassassin clamav clamassassin

Konfigfragen von Courier

  • Verzeichnisse für WWW-Administration? Nein

Konfigfragen von Postfix

  • Internet-Server
  • E-Mail-Name:  Der per DNS auflösbare FQDN des Servers (z.B. meinedomain.de)

Konfiguration von Postfix fortsetzten

dpkg-reconfigure postfix

Weitere Konfigfragen von Postfix

  • Internet-Server
  • An wen sollen Mails für root weitergeleitet werden: Nichts eintragen, kommt später.
  • Rechner für die dieser Rechner als Zielsystem gilt: Alle Domains die mit Postfix Mails empfangen können und die einen DNS-Eintrag für die IP des Servers haben. (z.B. meinedomain.de, meinanderedomain.de, meinedrittedomain.de)

Postfix

Configdatei für Postfix

# /etc/postfix/main.cf

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
readme_directory = /usr/share/doc/postfix                                 

# TLS aktivieren
smtpd_use_tls=yes                                                         

smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
myhostname = meinedomain.de
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = meinedomain.de, meineanderedomain, meinedrittedomain , localhost, 127.0.0.1
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
html_directory = /usr/share/doc/postfix/html
inet_protocols = ipv4

# Auth über SASL
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
# Nur User Mail versenden lassen, die in SASL-DB stehen, nur MD5-Passwörter erlauben
smtp_sasl_security_options = noanonymous, noplaintext

# Nur Localhost (mynetworks) und über SASL angemeldete User dürfen Mails verschicken
smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination
smtpd_sasl_local_domain =

# Nur verschlüsselt Authentifizieren mit TLS
smtp_tls_auth_only = yes

#TLS aktivieren
smtp_use_tls = yes
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes

# Selbstgenerierter Schlüssel und das Zertifikat
smtpd_tls_key_file = /etc/postfix/cert/smtpd.key
smtpd_tls_cert_file = /etc/postfix/cert/smtpd.crt
smtpd_tls_CAfile = /etc/postfix/cert/cacert.pem

# SPäter auf 0 setzen, gut zum debuggen
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom

# Mails in Maildirs ausliefern
home_mailbox = Maildir/

# Dateiname der Virtual-Alias-Map mit der Zuordnung von E-Mail-Adresse zu lokaler Mailbox
virtual_alias_maps = hash:/etc/postfix/virtual

# Mail wird nicht direkt in Mailboxen gelegt sondern an Procmail übergeben
mailbox_command = procmail -a "$EXTENSION"

SASL

SASL stellt für verschiedene Daemons einen Authentifizierungsmechanismus zur Verfügung. In diesem Setup werden in einer SASL-Datenbank die Benutzer gespeichert, die über unseren Postfix Post verschicken dürfen. (Also der Username und das Passwort, die im E-Mail-Client als Zugangsdaten für den SMTP-Server eingetragen werden müssen)

Konfigdatei für SASL erstellen

# /etc/postfix/smtpd.conf
pwcheck_method: authdaemond
mech_list: CRAM-MD5

Postfix kann leider noch nicht den saslauthd benutzen um Benutzerdaten zu überprüfen, da Postfix in einer chroot-Umgebung läuft und noch keinen Zugriff auf den saslauthd hat.

# /etc/default/saslauthd
START=yes
DESC="SASL Authentication Daemon"
NAME="saslauthd"
MECHANISMS="pam"
MECH_OPTIONS=""
THREADS=5

# Mit -m legen wir das Socket von saslauthd in ein Verzeichnis, das Postfix aus dem chroot erreichen kann.
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"

Danach muss noch im "start-instance"-Block von /etc/init.d/saslauthd der Ort für die PID geändert werden, auch wieder damit Postfix das PID-File lesen kann.

# /etc/init.d/saslauthd
.
.
PIDFILE="/var/spool/postfix/var/run/${NAME}/saslauthd.pid"
.
.

TLS

Es können nun keine nicht-authentifizierten Sender mehr Mail über den Postfix SMTP versenden, allerdings gehen die Mails noch im Klartext durch LAN und Internet. Die TLS-Verschlüsselung wurde bereits oben in der Postfix-Konfigdatei main.cf aktiviert. Allerdings fehlen noch Key und Zertifikat.

mkdir /etc/postfix/cert
cd /etc/postfix/cert

openssl genrsa -des3 -rand /etc/hosts -out ./smtpd.key 1024
chmod 600 ./smtpd.key
openssl req -new -key ./smtpd.key -out ./smtpd.csr
openssl x509 -req -days 99999 -in ./smtpd.csr -signkey ./smtpd.key -out ./smtpd.crt
openssl rsa -in ./smtpd.key -out ./smtpd.key.tmp
mv -f ./smtpd.key.tmp ./smtpd.key
chmod 600 ./smtpd.key
openssl req -new -x509 -extensions v3_ca -keyout ./cakey.pem -out ./cacert.pem -days 99999

SASL DB erstellen

Mails werden nun bei der Übertragung verschlüsselt, Usernamen und Passwörter für den Mailversand über den SMTP-Server gehen jedoch noch im Klartext durchs Internet. Diese kann man zumindest mit der MD5-Cram-Methode kaschieren. Diese wurde bereits in der /etc/postfix/smtpd.conf aktiviert. Es fehlt nur noch die SASL-Datenbank selbst. Diese legt man an, indem man einfach einem späteren Mailuser einen Usernamen und ein Passwort gibt.

# Für Username einen lokalen Mailuser einsetzen um die SASL-DB zu erstellen mit einem ersten Benutzer
saslpasswd2 username

Postfix ist fertig. Er kann Mails empfangen und verschicken. Verbindungen zu Clients und anderen Mailservern sind verschlüsselt.

Courier

Couriers Konfigdateien

# /etc/courier/authdaemonrc

# UserDB zur authentifizierung benutzen
authmodulelist="authuserdb"

authmodulelistorig="authuserdb authpam authpgsql authldap authmysql authcustom authpipe"
daemons=5
authdaemonvar=/var/run/courier/authdaemon

# Gut zum debuggen
DEBUG_LOGIN=2
DEFAULTOPTIONS=""
LOGGEROPTS=""
#/etc/courier/authmodulelist

# courierauthdaemon nutzt MD5-cram
authcram
# /etc/courier/imapd

ADDRESS=0
PORT=143
MAXDAEMONS=40
MAXPERIP=20
PIDFILE=/var/run/courier/imapd.pid
TCPDOPTS="-nodnslookup -noidentlookup"
LOGGEROPTS="-name=imapd"

#Hier wird AUTH=CRAM-MD5 hinzugefügt

IMAP_CAPABILITY="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 IDLE"

IMAP_KEYWORDS=1
IMAP_ACL=1
IMAP_CAPABILITY_ORIG="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 AUTH=CRAM-SHA1 AUTH=CRAM-SHA256 IDLE"
IMAP_PROXY=0
IMAP_PROXY_FOREIGN=0
IMAP_IDLE_TIMEOUT=60
IMAP_MAILBOX_SANITY_CHECK=1
IMAP_CAPABILITY_TLS="$IMAP_CAPABILITY AUTH=PLAIN"
IMAP_CAPABILITY_TLS_ORIG="$IMAP_CAPABILITY_ORIG AUTH=PLAIN"
IMAP_DISABLETHREADSORT=0
IMAP_CHECK_ALL_FOLDERS=0
IMAP_OBSOLETE_CLIENT=0
IMAP_UMASK=022
IMAP_ULIMITD=65536
IMAP_USELOCKS=1
IMAP_SHAREDINDEXFILE=/etc/courier/shared/index
IMAP_ENHANCEDIDLE=0
IMAP_TRASHFOLDERNAME=Trash
IMAP_EMPTYTRASH=Trash:7
IMAP_MOVE_EXPUNGE_TO_TRASH=0
SENDMAIL=/usr/sbin/sendmail
HEADERFROM=X-IMAP-Sender
IMAPDSTART=YES
MAILDIRPATH=Maildir
SSLPORT=993
SSLADDRESS=externe.ip.des.servers
SSLPIDFILE=/var/run/courier/imapd-ssl.pid
SSLLOGGEROPTS="-name=imapd-ssl"
IMAPDSSLSTART=YES
IMAPDSTARTTLS=YES
IMAP_TLS_REQUIRED=1
COURIERTLS=/usr/bin/couriertls
TLS_KX_LIST=ALL
TLS_COMPRESSION=ALL
TLS_CERTS=X509
TLS_CERTFILE=/etc/courier/imapd.pem
TLS_TRUSTCERTS=/etc/ssl/certs
TLS_VERIFYPEER=NONE
TLS_CACHEFILE=/var/lib/courier/couriersslcache
TLS_CACHESIZE=524288
MAILDIRPATH=Maildir

# Auch hier kommt AUTH=CRAM-MD5 hinzu

IMAP_CAPABILITY="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 IDLE"

Spamassassin

Spamassassin muss aktiviert werden

# /etc/default/spamassassin
ENABLED=1
OPTIONS="--create-prefs --max-children 5 --helper-home-dir"
PIDFILE="/var/run/spamd.pid"
CRON=0

Procmail

Nachdem Postfix Mails aus dem Internet für einen lokalen Benutzer empfangen hat, übergibt er sie an procmail. Procmail wiederum übergibt die Mail an Spamassassin um sie auf Spam zu überprüfen und an clamassassin, der sie weiterreicht an den Virenscanner clamav.

# Eine Beispiel .procmailrc für die Homeverzeichnisse der Mailuser

PATH=$HOME/bin:/usr/bin:/bin:/usr/local/bin:.
MAILDIR=$HOME/Maildir/
DEFAULT=$HOME/Maildir/new
LOGFILE=$HOME/procmail.log

# SPAMASSASSIN
:0fw: /var/run/spam.lock
* < 256000
| spamc -f -u $LOGNAME

# Alle SPAMS mit Score 10-99 gleich weg
:0:
* ^X-Spam-Status: Yes, score=[1-9][0-9]\.
/dev/null

# Alle SPAMS mit Score > 3 gleich weg
#:0:
#* ^X-Spam-Status: Yes, score=[4-9]\.
#/dev/null

:0fw
| /usr/bin/clamassassin

# Rewrite Subject Line, if SpamLevel is high enough.
:0fw
* ^X-Virus-Status: Yes
| sed '1,/^$/s@^Subject:@Subject: /VIRUS!/@'

:0:
* ^X-Virus-Status: Yes
/dev/null

# Move SA SPAM MAILS TO SPAM
:0:
* ^X-Spam-Status: Yes
$MAILDIR/.Spam/new

# Alle Mails die es ohne Blessuren bis hier geschafft haben, landen automatisch in der Inbox des Users. "Sie haben Post!"

Puh! Das Mailsystem ist fertig! Es fehlen nur noch Benutzer, die Maildirs und die Konfiguration der Virtual-Aliases um festzulegen welche Email-Adressen in welchen lokalen Mailboxen laden. Das folgende Skript legt den UNIX-Systembenutzer an, und denselben Benutzer noch einmal für Postfix in der SASLdb und für Courier in der Courier-Userdb.

Skript zum anlegen neuer User

# Added einen neuen User zum Mailsystem                      

#!/bin/bash
clear
echo "Neuer User fuer das Mailsystem";
echo "Username eingeben: ";
read newuser                          

echo $newuser >> /root/scripts/mail/mail_users.dat

# Adding Unix User

adduser --ingroup users --quiet --shell /bin/false $newuser

echo
echo "Linux User wurde angelegt....."
echo

# Adding Courier Mailboxes

maildirmake /home/$newuser/Maildir
maildirmake -f Spam /home/$newuser/Maildir
maildirmake -f Virus /home/$newuser/Maildir
maildirmake -f LerneSpam /home/$newuser/Maildir
maildirmake -f LerneKeinSpam /home/$newuser/Maildir
maildirmake -f MeineOrdner /home/$newuser/Maildir
maildirmake -f Sent /home/$newuser/Maildir
maildirmake -f Trash /home/$newuser/Maildir
chown -R $newuser.users /home/$newuser/Maildir
echo
echo "IMAP Mailverzeichnisse wurden angelegt...."
echo

# Setting SASL Password for Postfix SMTP auth

echo
echo
echo "Passwort für SMTP-Auth angeben (Mails verschicken mit dem Client)"
saslpasswd2 $newuser

echo
echo
echo "Passwort für Courier angeben (Zuganspasswort für den IMAPSERVER)"

NEWUID=`cat /etc/passwd | grep $newuser | cut -d: -f3`

userdb $newuser set home=/home/$newuser uid=$NEWUID gid=100
userdbpw -hmac-md5 | userdb $newuser set imap-hmac-md5pw home=/home/$newuser
makeuserdb

/etc/init.d/courier-authdaemon restart
/etc/init.d/saslauthd restart

echo "OK. User angelegt"
echo "Weisen Sie dem neuen User bitte noch E-Mail-Adressen zu!"
echo
echo
echo "Datei /etc/postfix/virtual editieren."
echo "Danach einmalig ausführen: postmap /etc/postfix/virtual"
echo "Danach einmalig ausführen: /etc/init.d/postfix reload"

Skript zum löschen von Usern

echo "Diesen User loeschen:"
read DELUSER

# aus mail_users_dat kriegt lernespam die mailuser
cat /root/scripts/mail/mail_users.dat | grep -v "^$DELUSER$" > /root/scripts/mail/mail_users.dat.tmp
rm /root/scripts/mail/mail_users.dat
mv /root/scripts/mail/mail_users.dat.tmp /root/scripts/mail/mail_users.dat

deluser --remove-home $DELUSER
saslpasswd2 -d $DELUSER
userdb $DELUSER del
makeuserdb
/etc/init.d/courier-authdaemon restart
/etc/init.d/saslauthd restart

Skript zum manuellen Spam-lernen

#!/bin/bash

for user in $(cat /root/scripts/mail/mail_users.dat);
do

SADIR=/home/$user/.spamassassin
NOSPAM=/home/$user/Maildir/.LerneKeinSpam/cur/

for l in $(ls $NOSPAM );
do
PRINT=`cat $NOSPAM/$l | grep -e "^From:" | grep -o "[[:alnum:]\.\+\-\_]*@[[:alnum:]\.\-]*" | sort -u`
echo "whitelist_from $PRINT" >> $SADIR/user_prefs
done

# Let SA learn
/usr/bin/sa-learn -D  --spam /home/$user/Maildir/.LerneSpam/cur
/usr/bin/sa-learn -D  --ham /home/$user/Maildir/.LerneKeinSpam/cur

# Move Stuff
mv /home/$user/Maildir/.LerneKeinSpam/cur/* /home/$user/Maildir/cur/
rm /home/$user/Maildir/.LerneSpam/cur/*

done
exit

Virtual Aliases

Unser Postfix weiss noch gar nicht welche E-Mail-Adressen welchen lokalen Mailboxen zugeordnet sind. Diese Zuordnung wird in der Datei /etc/postfix/virtual geschaffen. Links stehen E-Mail-Adressen oder lokale Absender wie "root", rechts steht der Username für die IMAP-Mailbox oder eine Ziel-E-Mail-Adresse für Weiterleitungen

# /etc/postfix/virtual
root                                        daniel
daniel@meinedomain.de            daniel
daniel@meineanderedomain.de   daniel
fritz@meinedomain.de               fritz
alle@meinedomain.de                daniel,fritz
weiterleitung@meinedomain.de   daniel@gmail.com

Danach muss Postfix die virtuellen Aliase neu initialisieren. Das ist nach jeder Änderung der Datei notwendig.

postmap /etc/postfix/virtual

Jetzt ist wirklich alles fertig. Es müssen noch alle Dienste gestartet werden.

/etc/init.d/postfix restart
/etc/init.d/courier-imap restart
/etc/init.d/courier-imap-ssl restart
/etc/init.d/courier-authdaemon restart
/etc/init.d/saslauthd restart
/etc/init.d/spamassassin restart
/etc/init.d/clamav restart

Irgendwas wird sicherlich nicht funktionieren! Zum Debuggen eignet sich /var/log/mail.log ganz gut. In vielen Configdateien kann man das Loglevel hochsetzen um mehr Informationen zu bekommen.

Transport Maps

Um Mails an einen anderen SMTP weiterzurouten, benötigt man Transport-Maps. Sie werden in der Datei /etc/postfix/transport angelegt:

#/etc/postfix/transport
# Links lokales Ziel
# Rechts SMTP an den weitergeleitet wird

daniel-ritter.de       smtp:12.13.14.15
daniel-ritter.de       smtp:anderer.host.de

# Zusätzlich alle Subdomains
.daniel-ritter.de      smtp:anderer.host.de

#/etc/postfix/main.cf
transport_maps = hash:/etc/postfix/transport

# Aktivieren von Änderungen an den Transportmaps

postmap /etc/postfix/transport
/etc/init.d/postfix reload

Nutzer das Courier-Passwort selbst ändern lassen

echo "Courier Passwort ändern"
echo

echo
echo "Benutzername: "
read U
echo "Altes Passwort: "
read A
echo "Neues Passwort: "
read N

if [ $(echo $N | grep -e ^[0-9]) ];
then
echo "Entschuldigung. Passwörter dürfen nicht mit einer Zahl beginnen."
exit
fi

echo -e "$U\0$A\0$N\0" | /opt/courierpasswd --verbose --stderr --stdin --changepw