www.dr-lotz.de

TLS-gesicherter IMAP-Server

(TLS: Transport Layer Security; IMAP: Internet Message Access Protocol)

System: SuSE 9.1

Das Ziel ist die Einrichtung eines IMAP-Servers, der den Zugriff auf alle Emails sowohl im lokalen Netz als auch vom Internet aus über eine TLS-gesicherte Verbindung ermöglicht. Für Cyrus-imapd habe ich mich entschieden, weil er Unterordner unterstützt. TLS unterstützt er ebenfalls von Haus aus, so dass keine zusätzlichen Programme wie stunnel erforderlich sind, um eine sichere Verbindung zu ermöglichen.

Bis zum Ziel sind sind eine ganze Reihe von Schritten erforderlich:

  1. Eigene Certification Authority (CA) erzeugen
  2. Zertifikat für den Server erzeugen
  3. Cyrus imapd konfigurieren und Benutzer anlegen
  4. Postfix anpassen, damit er die Mails an Cyrus übergibt

1. Eigene Certification Authority (CA) erzeugen

Eine CA zertifiziert die Zugehörigkeit von einem Schlüssel zu einer Identität. Dabei werden, vereinfacht ausgedrückt, öffentlicher Schlüssel und Identitüt, etwa eine e-Mail-Adresse, in eine Datei geschrieben, und diese Datei mit dem privaten Schlüssel der CA signiert. Mit dem öffentliche Schlüssel der CA kann diese Unterschrift später geprüft und festgestellt werden, ob Schlüssel oder Identität manipuliert wurden. Solche Zertifikate kann man bei verschiedene kommerziellen Anbietern bekommen, für private Zwecke genügt aber eine eigene CA völlig.

Das Zertifikat der CA - das ist der von der CA selbst signierte Public Key der CA - kann in den Browser importiert werden, um damit die Authentizität von Zertifikaten zu verifizieren, die von der CA unterschrieben sind.

Als Programm zum Erzeugen der Zertifikate und Schlüsselpaare kommt openssl zum Einsatz. Die Aufrufe sind relativ komplex.

Zunächst legt man sich eine Verzeichnisstruktur an, z.B. im Heimatverzeichnis von root und erzeugt zwei Dateien:

pluto:~ # mkdir MeineCA
pluto:~ # cd MeineCA
pluto:~/MeineCA # mkdir certs newcerts crl private
pluto:~/MeineCA # touch index.txt
pluto:~/MeineCA # echo "01" > serial

Mach den Aufrufen von openssl werden verschiedene Informationen abgefragt. Man kann sich Tipparbeit sparen, indem man die Datei /etc/ssl/openssl.cnf die Variablen modifizert, die auf default enden. Auch die Anpassung der Variablen dir ist empfehlenswert.

# /etc/ssl/openssl.cnf
...
[ CA_default ]

dir                 = /root/MeineCA  # Where everything is kept

...

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = de
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = By

localityName                    = Locality Name (eg, city)
localityName_default            = Muenchen

0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = 

# we can do this but it is not needed normally :-)
#1.organizationName             = Second Organization Name (eg, company)
#1.organizationName_default     = World Wide Web Pty Ltd

organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = IT-Abteilung

commonName                      = Common Name (eg, YOUR name)
commonName_default              = mond
commonName_max                  = 64

emailAddress                    = Email Address
emailAddress_default            = ...@...
emailAddress_max                = 64

...

Der nächste Schritt ist das Erzeugen der CA, die in diesem Beispiel 10 Jahre gültig ist.

pluto:~ # openssl req -new -x509 -keyout private/MeineCA_prv_key.pem \
                -out MeineCA_cert.pem -days 3650

Das Schlüsselpaar der CA wird erzeugt und verschiedene Informationen werden abgfragt. Die Passphrase ist wichtig, an ihr hängt zum großen Teil die Sicherheit der CA - wer sie kennt, kann von der CA signierte Zertifikate ausstellen. Und vergessen darf man sie natürlich auch nicht, denn dann kann man keine neuen Zertifikate mehr ausstellen.

2. Zertifikat für den Server erzeugen

Als nächstes erzeugt man das Schlüsselpaar für den Server. und einen sog. Certificate Request. Das Schlüsselpaar aus privatem und öffentlichen Schlüssel wird für den Aufbau der SSL-Verbindung benötigt. Der Certificate Request enthält den öffentlichen Schlüssel des Servers und wird dann bei der CA zum Signieren eingereicht. Die Gültigkeit muss innerhalb der Gültigkeit der CA liegen, hier ist es ein Jahr.

pluto:~ # openssl req -new -keyout certs/mailserver_prv_key.pem \
          -out certs/mailserver_req.pem -days 365

Wichtig ist, dass man bei den Abfragen bei "Common Name" den Namen des Servers eingibt, etwa mailserver.example.com. Ansonsten erhält man beim Kontaktieren des Servers eine Meldung vom Browser, dass der Name des Servers und der im Zertifikat angegebene Name nicht übereinstimmen.

Die Passphrase ist hier nicht von so entscheidender Bedeutung, da wir später einen unverschlüsselten privaten Schlüssel benötigen.

pluto:~ # openssl rsa < certs/mailserver_prv_key.pem >
             mailserver_prv_key-unverschluesselt.pem

Der öffentliche Schlüssel (der Certificate Request) wird jetzt mit dem privaten Schlüssel der CA unterschrieben.

pluto:~ # openssl ca -policy policy_anything -notext \
         -out certs/mailserver_cert.pem -infiles certs/mailserver_req.pem

Nach Eingabe der Passphrase der CA und zwei Rückfragen ist das Zertifikat für den Server fertig.

Das Zertifikat der CA, das für den Server sowie der private Schlüssel für den Server müssen auf dem Server an geeigneter Stelle abgelegt werden. Ich habe sie unterhalb von /etc/ssl/ abgelegt.

/etc/ssl/certs/MeineCA_cert.pem
/etc/ssl/ServerCerts/mailserver_cert.pem
/etc/ssl/private/mailserver_prv_key-unverschluesselt.pem

Den privaten Schlüssel des Mailservers dürfen nur die Serverprozesse lesen können, die ihn tatsächlich brauchen, und sonst keiner. Recht elegant lässt sich das mit POSIX-ACLs verwirklichen.

mailserver:/etc/ssl # ls -ld private/
drwxr-x--- 2 root root 136 Jul 30 22:07 private/

mailserver:/etc/ssl # ls -l private/mailserver_prv_key-unverschluesselt.pem
-rw------- 1 root root 887 Jul 29 20:52
private/mailserver_prv_key-unverschluesselt.pem

mailserver:/etc/ssl # setfacl -m u:cyrus:rx private/

mailserver:/etc/ssl # setfacl -m u:cyrus:r
private/mailserver_prv_key-unverschluesselt.pem

mailserver:/etc/ssl # ls -ld private/
drwxr-x---+ 2 root root 136 Jul 30 22:07 private/
mailserver:/etc/ssl # getfacl private
# file: private
# owner: root
# group: root
user::rwx
user:cyrus:r-x
group::---
mask::r-x
other::---

mailserver:/etc/ssl # ls -l private/mailserver_prv_key-unverschluesselt.pem
-rw-r-----+ 1 root root 887 Jul 30 22:03
private/mailserver_prv_key-unverschluesselt.pem
mailserver:/etc/ssl # getfacl  private/mailserver_prv_key-unverschluesselt.pem
# file: private/mailserver_prv_key-unverschluesselt.pem
# owner: root
# group: root
user::rw-
user:cyrus:r--
group::r--
mask::r--
other::---

Ein Tipp für Debian/Ubuntu-Nutzer: Wenn die Kommandos setfacl und getacl nicht existieren, kann man diese per apt-get install acl nachinstallieren. Man muss dann noch in der Datei /etc/fstab die ACL-Unterstützung (Option acl) für das zu verwendende Laufwerk hinzufügen und sie mit mount -o remount /mountpoint aktivieren. (Dank an Axel Sylvester für den Hinweis.)

3. Konfiguration von Cyrus

Die Konfiguration umfasst zum einen die Anpassung der Dateien /etc/imapd.conf und /etc/cyrus.conf sowie dem Anlegen der Benutzer bzw. Mailkonten.

Die Benutzerauthentifizierung geschieht mit Hilf von SASL (Simple Authentication Security Layer). Für diese Authentifizierung gibt es verschiedene Verfahren, sowohl Klartext als auch verschlüsselt. Da die Authentifizierung hier innerhalb des verschlüsselten Tunnels stattfindet, ist die Verwendung der Authentifizierung im Klartext möglich, ansonsten ist dieses Verfahren im beschriebenen Szenario ungeeignet.

In der Datei /etc/imapd.conf muss das richtige Verfahren für SASL eingetragen werden, bei Klartextpasswörtern und einer separaten Datenbank für Benutzer und Passwörter (also nicht PAM und /etc/passwd und /etc/shadow) ist dies "auxprop". In dieser Datei wird auch eingetragen, wo sich die für die SSL-Verschlüsselung erforderlichen Dateien befinden.

# /etc/imapd.conf
...
#sasl_pwcheck_method: saslauthd
sasl_pwcheck_method: auxprop
sasl_mech_list: plain login
#
# if you want TLS, you have to generate certificates and keys
#
tls_cert_file: /etc/ssl/ServerCerts/mailserver_cert.pem
tls_key_file: /etc/ssl/private/mailserver_prv_key-unverschluesselt.pem
tls_ca_file: /etc/ssl/certs/MeineCA_cert.pem
tls_ca_path: /etc/ssl/certs

Die Benutzer und Passwörter werden mit dem Befehl saslpasswd2 erzeugt. Dieser legt sie in der Datei /etc/sasldb2 ab. Die Passwörter lassen sich zwar nicht direkt mit less oder cat auslesen, aber strings /etc/sasldb2 zeigt sie. Daher müssen die Rechte für die Datei so gesetzt sein, dass nur root und cyrus sie lesen können. Das geht wie bereits oben beschrieben mit POSIX-ACLs sehr gut.

Wenn die Variable sasl_pwcheck_method bzw. sasl_mech_list falsch sind oder der Benutzer cyrus die Datei /etc/sasldb2 nicht lesen kann, kommt es bei den nächsten Schritten zu Fehlermeldungen, die oft auch nicht besonders hilfreich sind. Gelegentlich hilft die Logdatei /var/log/messages weiter.

Der Benutzer, der in sasldb2 auf jeden Fall vorhanden sein muss, ist der Benutzer cyrus. Die weiteren werden genauso angelegt.

pluto:~ # saslpasswd2 cyrus
Password:
Again (for verification):

Anschließend started man den imapd (er muss dafür am imap-Port 143 lauschen) und kann man sich mit dem gerade festgelegten Passwort anmelden, um die Benutzeraccounts anzulegen.

mailserver:~ # cyradm -user cyrus -auth login -server localhost
localhost > createmailbox user.tux
localhost > exit
mailserver:~ # 

Je nachdem, ob man nur verschlüsselte oder auch unverschlüsselte Verbindungen zulassen möchte, muss zuletzt noch die Datei /etc/cyrus bearbeitet und die entsprechenden Zeilen mit einem Kommentarzeichen versehen bzw. das Kommentarzeichen entfernt werden.

...
# UNIX sockets start with a slash and are put into /var/lib/imap/socket
SERVICES {
  # add or remove based on preferences
#  imap         cmd="imapd" listen="imap" prefork=0
  imaps         cmd="imapd -s" listen="imaps" prefork=0
#  pop3         cmd="pop3d" listen="pop3" prefork=0
  pop3s         cmd="pop3d -s" listen="pop3s" prefork=0
  sieve         cmd="timsieved" listen="sieve" prefork=0
...

In dem obigen Beispiel sind nur verschlüsselte Verbindungen erlaubt. Zum Anlegen von Benutzern muss man jedoch zumindest vorrübergehend auch das Kommentarzeichen vor imap entfernen.

Nach einem Neustart sollte (hoffentlich) alles funktionieren. Wenn nicht hilft oft ein tail -f /var/log/messages in einem zweiten Terminalfenster weiter, während man versucht, eine Verbindung zum IMAP-Server aufzubauen.

Wenn die IMAP-Funktionalität da ist, sollte zur Sicherheit noch mit ethereal sichergestellt werden, dass wirklich keine Passwörter und Inhalte im Klartext über die Leitung gehen.

4. Postfix anpassen, damit er die Mails an Cyrus übergibt

Bei Postfix muss in /etc/postfix/main.cf eine Variable gesetzt sein, damit die Mails nicht nach /var/spool/mail/ geschrieben sondern an Cyrus übergeben werden. (Bei SUSE kommt es gelegentlich vor, dass eine Variable in der Datei zweimal vorkommt - der letzte Eintrag zählt. Es empfiehlt sich nachzuschauen, ob die Variable wirklich nur einmal in der Datei vorkommt.)

mailbox_transport = cyrus

Weitere Links

Mein Anleitung hier ist recht knapp. Mir haben verschiedene Quellen im Internet weitergeholfen. Eine kleine Auswahl:

Was noch offen ist ...

In der jetztigen Form existiert insofern noch ein Schönheitsfehler, dass es bei Kontakt über das Internet zu einer Meldung des Browsers kommt, dass Name des Servers und Name im Zertifikat nicht übereinstimmen, da der Server intern einen anderen Namen als der Dyn-DNS-Name im Internet.

Außerdem würde ich gerne auch den Client mit einem Zertifikat authentifizieren und nur Verbindungen mit Clients zulassen, die sich mit einem Zertifikat ausweisen können. Diesbezüglich habe ich noch keine Idee, ob und wenn ja wie das geht.

Lösungsvorschläge sind willkommen.

Zu guter Letzt

Hinweise, Fehler, Anmerkungen? Bitte nicht zögern, mir eine Mail zu schicken. Ich freue mich über Mails und Fehler bessere ich so schnell es geht aus.