In diesem Blog-Eintrag geht es um die Einrichtung eines Mailservers, der dovecot, Exim, OpenLDAP und getmail verwendet. Folgendes wird mit der Konfiguration erreicht:
- Mails können von Benutzern, die in OpenLDAP eingetragen sind per IMAP abgerufen und per SMTP versendet werden (auch mit TLS-Verschlüsselung).
- Benutzer können Mails von externen POP3/IMAP-Accounts direkt in ihr IMAP Postfach legen lassen
- Benutzer können Mails mit einer externen Absenderaddresse via lokalem Mailserver verschicken, der sie über den entsprechenden externen Mailserver verschickt
Am Beispiel sollte es klarer werden. Paul ist mit der Userid paul in OpenLDAP eingetragen und hat auf dem lokalen Rechner mit der Domain myserver die Mailaddresse paul@myserver. Paul kann per IMAP Mails abrufen (Login: paul@paul Server: myserver) und ebenfalls per SMTP Mails verschicken. Außerdem hat Paul eine weitere E-Mailadresse aus der Zeit als er sich noch keine eigene Domain leisten konnte. Diese lautet paulpanzer@gmx.de. Paul möchte seine E-Mails zukünftig auf seinem lokalen Server speichern und nicht mehr bei GMX. Er bzw. der Administrator trägt dazu die POP3-Zugangsdaten von GMX in OpenLDAP ein. Danach werden alle E-Mails automatisch heruntergeladen und Paul kann über den Login paul@paulpanzer@gmx.de auf dem Server myserver seine GMX-Mails per IMAP abrufen. Trägt Paul bzw. der Administrator auch die SMTP-Daten für die E-Mailaddresse paulpanzer@gmx.de in OpenLDAP ein, so kann Paul außerdem Mails indirekt via GMX- Mailserver verschicken, indem er als SMTP-Login paul@paulpanzer@gmx.de auf seinem lokalen Server wählt. So sieht das fertige Schema mit der verwendeten Software aus:
Der Zugriff per Webinterface auf Mails und der Abruf der Mails vom externen Server bzw. das Empfangen von Mails ist hier dargestellt:
Einrichtung
Bevor man überhaupt daran denkt, ein E-Mail-Serversystem aufzusetzen, müssen zwei Bedingungen erfüllt sein. Die erste betrifft eine genaue Systemzeit, der zweite den Hostnamen. Obwohl fast alles im Blog detailliert beschrieben ist, empfehle ich, die Konfigurationsdateien für das Mailsystem herunterzuladen.
Genaue Systemzeit mit Ubuntu
Leider installiert Ubuntu standardmäßig das Paket ntpdate. Durch dieses Paket wird jedes Mal, wenn man mit dem Internet verbunden ist (genauer gesagt beim ifup), die Zeit mit einem NTP-Server im Internet abgeglichen und ggfs. die Systemzeit entsprechend geändert. An sich ja keine schlechte Sache, aber dovecot reagiert auf Zeitänderungen sehr verstimmt und quittiert den Dienst. Deshalb setze ich stets ntpd ein. Dies ist ein NTP-Server, der systematisch die Differenz zwischen Systemzeitgeber und dem Internetserver beobachtet und so systematisches zu schell bzw. zu langsam gehen des Systemzeitgebers korrigieren kann. Man erhält damit eine genauere Systemzeit und damit auch ein stabiles dovecot. Deshalb installiere ich ntpd und entferne ntpdate:
sudo apt-get autoremove --purge ntpdate && sudo apt-get install ntp
Um für den Ausfall des Ubuntu NTP-Servers gewappnet zu sein, habe ich die Server-Einträge in /etc/ntp.conf noch um Server aus dem öffentlichen NTP-Pool ergänzt:
# You do need to talk to an NTP server or two (or three).
server 0.pool.ntp.org
server 1.pool.ntp.org
server 2.pool.ntp.org
server ntp.ubuntu.com
Nach einem Speichern der Konfigurationsdatei und einem Neustart des NTP-Servers mit
sudo /etc/init.d/ntp restart
haben wir den ersten Punkt erledigt. Christoph Langner beschreibt die Installation von ntpd noch etwas ausführlicher.
Hostname für den Mailserver
Der zweite wichtige Punkt ist der Hostname. Der fully qualified domain name (FQDN) des Rechners muss bekannt sein. Nachprüfen lässt sich das über
hostname --fqdn
Bekommt man keine Ausgabe wie host.domain.de, dann muss man die /etc/hosts anpassen, so dass die Reihenfolge der Servernamen stimmt:
127.0.0.1 myserver localhost
Bitte unbedingt beachten, dass das beispielhaft aufgeführte myserver kein FQDN ist. Ein FQDN besteht immer auch aus einer Top-Level-Domain.
Erzeugen von SSL-Zertifikaten
Damit wir mit imaps, dem durch Verschlüsselung abgesicherten IMAP, auf unseren Server zugreifen können, und auch den SMTP- und LDAP-Zugriff verschlüsseln können, benötigen wir entsprechende SSL-Zertifikate. Am einfachsten lassen sich solche Zertifikate mit easy-rsa aus dem Paktet openvpn erzeugen. Übrigens gibt es gibt es dazu gute Anleitungen von linux.neoberserker.de oder im OpenVPN-Wiki. Das Paket openvpn müssen wir jedoch nicht installieren. Es genügt, wenn wir mit
mkdir openvpn && cd openvpn && apt-get source openvpn
den Quelltext herunterladen. Wir führen alle folgenden Befehle zur Zertifikatserstellung als root aus (wichtig, damit später nicht jeder Benutzer die geheimen Dateien lesen kann). Zunächst kopieren wir das entsprechende Unterverzeichnis in /etc/ssl und löschen anschließend die nicht mehr benötigten Verzeichnisse mit
sudo -s
cp -R openvpn-2.1~rc11/easy-rsa/2.0 /etc/ssl/easy-rsa
cd .. && rm -rf openvpn
cd /etc/ssl/easy-rsa
Nun editieren wir die Datei vars und passen Sie entsprechend an. Bei mir habe ich folgende Zeilen am Ende angepasst:
export KEY_COUNTRY="DE"
export KEY_PROVINCE="RP"
export KEY_CITY="Ludwigshafen"
export KEY_ORG="Effinger"
export KEY_EMAIL="nospam@effinger.org"
Anschließend führen wir folgende Schritte durch, um die CA-Dateien zur Ausstellung eigener Zertifikate zu erzeugen. Beim Schritt ./build-ca kann man alle Punkte mit Enter bestätigen bis auf common name. Hier sollte man einen einfachen Namen, z.B. MyCA, angeben (am Besten nur Buchstaben und Zahlen verwenden – keine Leerzeichen oder sonstige Sonderzeichen).
. ./vars
./clean-all
./build-ca
./build-dh
Im nächsten Schritt erstellen wir für unseren Mailserver ein Server-Schlüsselpaar mit dem Befehl
./build-key-server myserver
myserver sollte dabei durch den DNS-Eintrag des Servers ersetzt werden (Thunderbird fragt ansonsten jedes Mal sicherheitshalber nach, ob das Zertifikat akzeptiert werden soll, weil der Zertifikatsname nicht mit dem Hostnamen übereinstimmt). Auch hier bestätigen wir wieder alles mit Enter bis auf den Punkt Sign the certificate? Hier antworten wir mit ja (y) und bestätigen die darauf erfolgende Rückfrage ebenfalls mit y. Ein Client-Zertifikat kann man mit
./build-key myclient
analog erzeugen. Dieses benötigt man jedoch nur, wenn man ausschließlich Clients mit gültigem Zertifikat auf den Mailserver zugreifen lassen möchte. Bei dovecot ist das der Fall, wenn der Parameter ssl_require_client_cert=yes gesetzt ist. Da dovecot sich mit dem LDAP-Server verbindet, können wir dazu ebenfalls ein Client-Zertifikat verwenden. Wir erzeugen es mit
./build-key dovecot-client
Im Unterverzeichnis keys sind nun einige Dateien, die wir noch in das richtige Verzeichnis kopieren müssen. Wichtig ist, dass niemand unbefugt auf die geheimzuhaltenden Dateien zugreifen kann, die allesamt mit der Erweiterung .key enden. Am Besten ist es, vor dem Kopieren die Berechtigungen zu prüfen. Die öffentlichen Zertifikate werden in das Verzeichnis /etc/ssl/certs und die geheimen Zertifikate in /etc/ssl/private kopiert mit
cp /etc/ssl/easy-rsa/keys/myserver.crt /etc/ssl/easy-rsa/keys/ca.crt /etc/ssl/certs/
cp /etc/ssl/easy-rsa/keys/myserver.key /etc/ssl/private/
chown root.ssl-cert /etc/ssl/private/myserver.key
chmod 640 /etc/ssl/private/myserver.key
Die letzten beiden Zeilen dienen dazu, Exim, Dovecot und LDAP den Zugriff auf die geheime Key-Datei zu gewähren. Die entsprechendenBenutzer müssen dazu in der Gruppe ssl-cert sein (Anleitung erfolgt bei der Installation des jeweiligen Programms). Falls man später doch noch OpenVPN nutzen möchte, kann man den Diffie-Hellman Parameter ebenfalls kopieren
cp /etc/ssl/easy-rsa/keys/dh1024.pem /etc/ssl/
Die Client-Zertifikate muss man nun natürlich dem E-Mail-Programm bekannt machen. Bei Thunderbird fügt man über Extras>Einstellungen>Erweitert>Zertifikate>Zertifikate>Zertifizierungsstellen>Importieren die Datei ca.crt hinzu, wechselt anschließend auf den Reiter Ihre Zertifikate, um dort dann die Dateien myclient.p12 importieren. Letzere Datei erzeugt man durch ein
openssl pkcs12 -export -name "myclient" -in myclient.crt -inkey myclient.key -out myclient.p12
OpenLDAP installieren
Als nächstes installieren wir OpenLDAP und die ldap-utils nach meinem OpenLDAP 1×1. Hier die Schritte in Kurzform (falls Schritte unklar sind – im OpenLDAP 1×1 ist alles sehr ausführlich erklärt):
- Alle folgenden Befehle als root ausführen mit einem
sudo bash
oder
sudo -s
-
apt-get install slapd ldap-utils
Unbedingt das Administrator-Passwort bei der Einrichtung merken.
-
/etc/init.d/slapd stop
- Die automatisch bei der Einrichtung erzeugte Datenbank löschen (Vorsicht, wenn OpenLDAP bereits im Einsatz ist! Dieser Befehl kann die aktive Datenbank löschen)
- Die folgende Datei database.ldif passen:
# Database settings dn: olcDatabase=hdb,cn=config objectClass: olcDatabaseConfig objectClass: olcHdbConfig olcDatabase: hdb # The base of your directory olcSuffix: o=effinger # rootdn directive for specifying a superuser on the database. This is needed # for syncrepl. olcRootDN: cn=admin,o=effinger # Superuser Password for the database # {SSHA}pEvotN6PmSjx0JV/mZl5BWeSVOKR1Ejt equals "test" # CHANGE this for your installation!!! olcRootPW: {SSHA}pEvotN6PmSjx0JV/mZl5BWeSVOKR1Ejt # Where the database file are physically stored olcDbDirectory: /var/lib/ldap # The dbconfig settings are used to generate a DB_CONFIG file the first # time slapd starts. They do NOT override existing an existing DB_CONFIG # file. You should therefore change these settings in DB_CONFIG directly # or remove DB_CONFIG and restart slapd for changes to take effect. # For the Debian package we use 2MB as default but be sure to update this # value if you have plenty of RAM olcDbConfig: set_cachesize 0 2097152 0 # Sven Hartge reported that he had to set this value incredibly high # to get slapd running at all. See http://bugs.debian.org/303057 for more # information. # Number of objects that can be locked at the same time. olcDbConfig: set_lk_max_objects 1500 # Number of locks (both requested and granted) olcDbConfig: set_lk_max_locks 1500 # Number of lockers olcDbConfig: set_lk_max_lockers 1500 # Indexing options olcDbIndex: objectClass eq # Save the time that the entry gets modified olcLastMod: TRUE # Checkpoint the BerkeleyDB database periodically in case of system # failure and to speed slapd shutdown. olcDbCheckpoint: 512 30 # The userPassword by default can be changed # by the entry owning it if they are authenticated. # Others should not be able to see it, except the # admin entry below # These access lines apply to database #1 only olcAccess: to attrs=userPassword,shadowLastChange by dn="cn=admin,o=effinger" write by anonymous auth by self write by * none # Ensure read access to the base for things like # supportedSASLMechanisms. Without this you may # have problems with SASL not knowing what # mechanisms are available and the like. # Note that this is covered by the 'access to *' # ACL below too but if you change that as people # are wont to do you'll still need this if you # want SASL (and possible other things) to work # happily. olcAccess: to dn.base="" by * read # The admin dn has full write access, everyone else # can read everything. olcAccess: to * by dn="cn=admin,o=effinger" write by * read # For Netscape Roaming support, each user gets a roaming # profile for which they have write access to #olcAccess: to dn=".*,ou=Roaming,o=morsnet" by dn="cn=admin,o=effinger" write by dnattr=owner write
Bitte unbedingt das Passwort (olcRootPW) ändern.
Falls gewünscht auch die RootDN (hier „o=effinger“) anpassen. Dadurch müssen einige der folgenden Befehle/Dateien angepasst werden. - Eine neue Datenbank mit Hilfe der database.ldif erzeugen (Administratorpasswort aus Schritt 2 wird benötigt)
/etc/init.d/slapd start ldapadd -f database.ldif -x -D "cn=admin,cn=config" -W
rm /etc/ldap/slapd.d/cn\=config/olcDatabase\=\{1\}hdb.ldif && rm /var/lib/ldap/*
Jetzt haben wir eine saubere Datenbank mit der RootDN „o=effinger“ und dem entsprechenden Administrator „cn=admin,o=effinger“, die wir nun weiter konfigurieren können. Bevor wir damit loslegen, muss man sich jedoch Gedanken machen, wie die Daten in OpenLDAP strukturiert werden sollen. Ich habe mich für folgendes Setup entschieden:
- Benutzer werden im Kontext ou=users,o=effinger gespeichert also z.B. uid=paul,ou=users,o=effinger. Hier wird auch die lokale Mail-Addresse paul abgelegt. Die Domainendung (@myserver) wird hier weggelassen, da teilweise die Domain nicht angegeben ist bzw. oft anders addressiert ist, z.B. paul@localhost
- Externe Mail-Accounts des Benutzers werden jeweils unter dem zugehörigen Benutzereintrag gespeichert, also z.B. dcSubMailAddress=paulpanzer@gmx.de,uid=paul,ou=users,o=effinger, zusammen mit den Angaben zu Logins für SMTP und den Mailabruf, z.B. mit POP3.
- Da dovecot jedoch nicht ganz flexibel mit LDAP umgehen kann, müssen wir Parameter wie uid, Angaben zum Speicherort der Mails, die unter uid=paul,ou=users,o=effinger verfügbar sind auch unter dcSubMailAddress=paulpanzer@gmx.de,uid=paul,ou=users,o=effinger verfügbar machen. Das geht mit dem DynList/DynGroup Overlay von OpenLDAP. Eine Alternative wäre das slapo-rwm Overlay gewesen, das allerdings in der aktuellen Ubuntu-Version noch einen Bug aufweist und deshalb außen vor bleibt.
Nach den konzeptionellen Überlegungen machen wir uns nun an die Arbeit. Wir konfigurieren das DynList-Overlay, wobei mir eine Anleitung für Gentoo und die kurze Einführung für Ubuntu sehr geholfen haben und ergänzen OpenLDAP mit einem von mir erstellten Schema (dovecot.schema.ldif).
- Folgenden Inhalt unter dem Namen dyngroup.schema.ldif abspeichern:
dn: cn=dyngroup,cn=schema,cn=config objectClass: olcSchemaConfig cn: dyngroup olcObjectIdentifier: NetscapeRoot 2.16.840.1.113730 olcObjectIdentifier: NetscapeLDAP NetscapeRoot:3 olcObjectIdentifier: NetscapeLDAPattributeType NetscapeLDAP:1 olcObjectIdentifier: NetscapeLDAPobjectClass NetscapeLDAP:2 olcObjectIdentifier: OpenLDAPExp11 1.3.6.1.4.1.4203.666.11 olcObjectIdentifier: DynGroupBase OpenLDAPExp11:8 olcObjectIdentifier: DynGroupAttr DynGroupBase:1 olcObjectIdentifier: DynGroupOC DynGroupBase:2 olcAttributeTypes: ( NetscapeLDAPattributeType:198 NAME 'memberURL' DESC 'Identifies an URL associated with each member of a group. Any type of labeled URL can be used.' SUP labeledURI ) olcAttributeTypes: ( DynGroupAttr:1 NAME 'dgIdentity' DESC 'Identity to use when processing the memberURL' SUP distinguishedName SINGLE-VALUE ) olcAttributeTypes: ( DynGroupAttr:2 NAME 'dgAuthz' DESC 'Optional authorization rules that determine who is allowed to assume the dgIdentity' EQUALITY authzMatch SYNTAX 1.3.6.1.4.1.4203.666.2.7 X-ORDERED 'VALUES' ) olcObjectClasses: ( NetscapeLDAPobjectClass:33 NAME 'groupOfURLs' SUP top STRUCTURAL MUST cn MAY ( memberURL $ businessCategory $ description $ o $ ou $ owner $ seeAlso ) ) olcObjectClasses: ( DynGroupOC:1 NAME 'dgIdentityAux' SUP top AUXILIARY MAY ( dgIdentity $ dgAuthz ) )
und mit einem
ldapadd -D "cn=admin,cn=config" -x -W -f dyngroup.schema.ldif
hinzufügen (Administrator-Passwort wird benötigt).
- Als nächstes folgenden Inhalt unter dem Namen dovecot.schema.ldif abspeichern
dn: cn=dovecot,cn=schema,cn=config objectClass: olcSchemaConfig cn: dovecot olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.1.1.1 NAME 'dcMailMessageStore' DESC 'Path to the maildir/mbox on the mail system' EQUALITY caseExactIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.1.1.2 NAME 'dcMailAlias' DESC 'Secondary (alias) mailaddresses for a user' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.1 NAME 'dcSubMailAddress' DESC 'A users secondary e-mail address for which mail from on another Mailserver has to be fetched' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.2 NAME 'dcAccountStatus' DESC 'The status of a user account: active, noaccess, disabled, deleted' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.3 NAME 'dcSMTPServer' DESC 'Outgoing mails should be delivered to this Mailserver via SMTP.' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.4 NAME 'dcSMTPLogin' DESC 'Login credential to send Mail with the SMTP server' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.5 NAME 'dcSMTPPassword' DESC 'A separate text that stores the SMTP account password in clear text' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.6 NAME 'dcRetrieveType' DESC 'Tells getmail what mail account to retrieve mail from, and how to access that account, e.g. SimplePOP3Retriever and BrokenUIDLPOP3SSLRetriever' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.7 NAME 'dcRetrieveServer' DESC 'Incoming mails have to be downloaded from this server' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.8 NAME 'dcRetrieveLogin' DESC 'Login credential to receive Mail from the server' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.9 NAME 'dcRetrievePassword' DESC 'Password for mail retrieval in clear text' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.10 NAME 'dcMailQuota' DESC 'The size of space the user can have until further messages get bounced.' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.11 NAME 'dcMailSizeMax' DESC 'The maximum size of a single messages the user accepts.' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.2.1.12 NAME 'dcMailAlternateAddress' DESC 'Secondary (alias) mailaddresses for an external Mail Account' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) olcAttributeTypes: ( 1.3.6.1.4.1.32589.1.3.1.1 NAME 'dcPosixOwnerURL' DESC 'Identifies an URL associated with the posixOwner of the entry. Any type of labeled URL can be used.' SUP labeledURI ) olcObjectClasses: ( 1.3.6.1.4.1.32589.1.1.2.1 NAME 'dcMailUser' DESC 'Dovecot-LDAP User' SUP top AUXILIARY MUST dcMailMessageStore MAY dcMailAlias ) olcObjectClasses: ( 1.3.6.1.4.1.32589.1.2.2.1 NAME 'dcExternalMailAccount' DESC 'Dovecot-LDAP external mail account' SUP top STRUCTURAL MUST ( dcSubMailAddress $ dcAccountStatus ) MAY ( dcSMTPServer $ dcSMTPLogin $ dcSMTPPassword $ dcRetrieveType $ dcRetrieveServer $ dcRetrieveLogin $ dcRetrievePassword $ dcMailQuota $ dcMailSizeMax $ dcMailAlternateAddress ) ) olcObjectClasses: ( 1.3.6.1.4.1.32589.1.3.2.1 NAME 'dcPosixSubAccount' DESC 'LDAP-URL for retrieving the respective posixAccount of an entry' SUP top AUXILIARY MAY dcPosixOwnerURL )
und ebenfalls in die Konfiguration übernehmen mit
ldapadd -D "cn=admin,cn=config" -x -W -f dovecot.schema.ldif
- Jetzt aktivieren wir das DynList-Modul und speichern dazu Folgendes als dynlist_moduleLoad.ldif
dn: cn=module{0},cn=config changetype: modify add: olcModuleLoad olcModuleLoad: dynlist.so
um es anschließend zur OpenLDAP-Konfiguration hinzuzufügen mit einem
ldapmodify -D "cn=admin,cn=config" -x -W -f dynlist_moduleLoad.ldif
- Dem Dynlist-Overlay müssen wir außerdem mitteilen, dass das Attribut dcPosixOwnerURL jeweils auf den zugehörigen Benutzer verweist. Das machen wir, indem wir den folgenden Inhalt als dynlist_activateOnSuffix.ldif abspeichern
dn: olcOverlay=dynlist,olcDatabase={1}hdb,cn=config objectClass: olcOverlayConfig objectClass: olcDynamicList olcDLattrSet: dcPosixSubAccount dcPosixOwnerURL olcOverlay: dynlist
und dann
ldapadd -D "cn=admin,cn=config" -x -W -f dynlist_activateOnSuffix.ldif
ausführen.
- Nun müssen wir einen Grundeintrag in LDAP vornehmen, bevor wir starten können. Außerdem benötigen wir einen Benutzer secmail, um Mails von externen Servern in festen Intervallen abzurufen und in das jeweilige lokale IMAP-Postfach abzulegen. Daher legen wir mit der folgenden LDIF-Datei database-content.ldif zunächst den Grundeintrag und den Benutzer secmail an (Passwort wieder unbedingt mit slappasswd anpassen) an
# effinger dn: o=effinger objectclass: organization objectclass: top o: effinger # users, effinger dn: ou=users,o=effinger objectClass: organizationalUnit objectClass: top ou: users # secmail, users, effinger dn: uid=secmail,ou=users,o=effinger objectClass: posixAccount objectClass: account objectClass: top cn: secmail gidNumber: 134 homeDirectory: /home/secmail uid: secmail uidNumber: 121 # This password equals test userPassword: {SSHA}R+pQv9aIQINrPYdgljEJ0B7jzCp2cCzz
und fügen sie mit einem
ldapadd -D "cn=admin,o=effinger" -x -W -f database-content.ldif
zum LDAP-Verzeichnis hinzu (Achtung Passwort verwenden, das für database.ldif erzeugt wurde)
- SSL/TLS aktivieren, dazu folgenden Inhalt als ssl-tls_init.ldif abspeichern
dn: cn=config changetype: modify add: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/ssl/certs/ca.crt dn: cn=config changetype: modify add: olcTLSCertificateFile olcTLSCertificateFile: /etc/ssl/certs/myserver.crt dn: cn=config changetype: modify add: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/ssl/private/myserver.key
und folgende Befehle ausführen:
ldapmodify -D "cn=admin,cn=config" -x -W -f ssl-tls_init.ldif sudo adduser openldap ssl-cert
Ein Neustart ist ebenfalls erforderlich, da ich die Erfahrung gemacht habe, dass ohne einen Neustart der Zugriff über TLS nicht funktioniert.
/etc/init.d/slapd restart
- Im nächsten Schritt der LDAP-Konfiguration richten wir Zugriffsrechte ein. Generell soll auf die Login-Daten bei externen Mailservern nur der jeweilige Benutzer selbst und der LDAP-Administrator lesend und schreibend zugreifen können, während der secmail Benutzer nur Leserechte benötigt. Diese Zugriffsrechte werden in der Datei add_acl.ldif mit dem Inhalt
dn: olcDatabase={1}hdb,cn=config changetype: modify add: olcAccess # The information to send and receive mails from remote servers # can only be modified by the user itself and the admin # the secmail user which will retrieve mails must have read access olcAccess: {1}to dn.regex=".*uid=([^,]+),ou=users,o=effinger" attrs=dcRetrieveType,dcRetrieveLogin,dcRetrievePassword,dcRetrieveServer,dcSMTPLogin,dcSMTPPassword,dcSMTPServer by dn="cn=admin,o=effinger" write by dn.exact,expand="uid=$1,ou=users,o=effinger" write by dn="uid=secmail,ou=users,o=effinger" read by * none # Users shall have write access to their attributes # admin shall have write access as well # all other users have only read access olcAccess: {2}to dn.regex=".*uid=([^,]+),ou=users,o=effinger" attrs=dcMailAlternateAddress by dn="cn=admin,o=effinger" write by dn.exact,expand="uid=$1,ou=users,o=effinger" write by * read
durch den Befehl
ldapmodify -D "cn=admin,cn=config" -x -W -f add_acl.ldif
zum LDAP-Verzeichnis hinzugefügt.
- Im letzten Schritt indizieren wir wichtige Felder für die Suche im LDAP-Verzeichnis. Das schont Ressourcen und sorgt außerdem dafür, dass die dezenten Hinweise von OpenLDAP in der Syslog, dass einzelne Attribute indiziert werden sollten, verschwinden. Was die einzelnen Indexoptionen bedeuten ist auf zytrax.com erklärt. Wir legen die Datei add_attribute_indices.ldif mit dem Inhalt
dn: olcDatabase={1}hdb,cn=config changetype: modify add: olcDbIndex olcDbIndex: cn pres,eq,sub olcDbIndex: sn pres,eq,sub olcDbIndex: uid pres,eq olcDbIndex: mail pres,eq,sub olcDbIndex: dcMailAlias pres,eq olcDbIndex: givenName pres,eq,sub olcDbIndex: dcSubMailAddress pres,eq olcDbIndex: dcMailAlternateAddress pres,eq olcDbIndex: dcAccountStatus pres,eq
an und fügen sie mit dem Befehl
ldapmodify -D "cn=admin,cn=config" -x -W -f add_attribute_indices.ldif
dem Verzeichnis hinzu.
Zugriff auf OpenLDAP-Server absichern
Durch die Anpassung der Datei ldap.conf können wir festlegen, an welchen LDAP-Server Anfragen standardmäßig gerichtet werden sollen und unter welchen Bedingungen eine Verbindung mit diesem akzeptiert wird. Wir möchten die Konfiguration so anpassen, dass der OpenLDAP-Server ein gültiges Zertifikat vorweisen muss und standardmäßig der gerade eingerichtete LDAP-Server befragt wird. Standardmäßig werden die Anfragen zwar sowieso an den lokalen Rechner gerichtet, aber die Angabe des DNS-Namens ist notwendig, da sonst die Gültigkeitsprüfung für das Serverzertifikat fehlschlagt. In der Datei /etc/ldap/ldap.conf tragen wir folgende Zeilen ein (myserver durch den DNS-Namen ersetzen):
URI ldap://myserver
TLS_CACERT /etc/ssl/certs/ca.crt
TLS_REQCERT demand
Ein anschließender Test mit dem Befehl
ldapsearch -x -b "o=effinger" -ZZ
sollte Einträge des LDAP-Servers zurückgeben. Eigentlich wäre es auch das Beste, wenn der LDAP-Server nur TLS-verschlüsselte Verbindungen akzeptieren würde. Das kann man über ACL mit den Security Strength Factors (SSF) einstellen, allerdings unterstützt Exim bislang keine TLS-verschlüsselten LDAP-Verbindungen, so dass wir hierauf verzichten.
LDAP-Einträge hinzufügen
Jetzt können wir Einträge in OpenLDAP anlegen. Sehr komfortabel kann man dazu JXplorer verwenden (zur Installation siehe Abschnitt Die nächsten Schritt mit LDAP im OpenLDAP 1×1). Wir starten JXplorer und wählen im Menü Datei>Verbinden. Dort tragen wir folgendes ein (localhost bzw. myserver anpassen):
Die Daten noch mal im Überblick:
- Host: myserver Port:389 (myserver anpassen)
- Base DN: o=effinger (ggfs. anpassen)
- Benutzer DN: cn=admin,o=effinger (ggfs. anpassen)
- Kennwort: Das Passwort, das wir für die Datei database.ldif gewählt haben (s.o.).
Nach der erfolgreichen Verbindungsherstellung sehen wir die LDAP-Hierarchie und erweitern den Baum unter o=effinger, so dass wir folgendes sehen:
Im nächsten Schritt fügen wir unseren ersten Benutzer Paul hinzu. Dazu Rechtsklick auf users im LDAP-Baum und Neu auswählen. Im nachfolgenden Dialog ändern wir die RDN auf uid=paul und fügen die Klassen top, person, organizationalPerson, inetOrgPerson, posixAccount und dcMailUser hinzu.
Nun sehen wir im nächsten Dialog einige fett gedruckte Attribute – diese sind Pflichtattribute und müssen daher ausgefüllt werden.
- cn steht für common name und ist einfach eine Bezeichnung für den Eintrag, am einfachsten ist es, man wählt hier Vornamen und Nachnamen des Benutzers
- dcMailMessageStore gibt das Grundverzeichnis an, in welchem die E-Mails abgelegt werden sollen. Wir werden Dovecot später so konfigurieren, dass wir dieses Verzeichnis (z.B. /home/paul/mail) um die E-Mail-Addresse ergänzen, so dass man z.B. /home/paul/mail/paul/ erhält. Letzeres wird in Dovecot das Home-Verzeichnis sein, in dem u.a. die .dovecot.sieve gespeichert wird. Die Mails werden später als Maildir im Unterverzeichnis maildir abgelegt, also /home/paul/mail/paul/maildir
- gidNumber gibt die GruppenID des Benutzers Paul an. Paul sollte bereits als Benutzer auf dem Rechner angelegt sein, so dass man über ein
id paul
die gid herausfinden kann.
- homeDirectory das Heimverzeichnis des Benutzers Paul. Den korrekten Wert kann man herausfinden durch ein
cat /etc/passwd | grep paul | cut -d: -f6
- sn steht für surname, also den Nachnamen des Benutzers
- givenName steht für den Vornamen des Benutzers, ist allerdings ein optionales Attribut
- uidNumber die BenutzerID von Paul. Der korrekte Wert ist analog zur gidNumber herauszufinden – statt gid dann den Wert von uid verwenden.
- userPassword Damit Paul sich einloggen kann, legen wir ein Passwort für ihn fest. Das Passwort sollte keinen Slash „/“ enthalten, da in der Exim-Konfiguration dieses Zeichen zur Trennung einer zusammengesetzten Zeichenfolge aus Login und Passwort verwendet wird.
- mail Dieses Attribut steht für die lokale E-Mail-Addresse von Paul. Die lokale E-Mail-Addresse wird dabei ohne die Domain angegeben. In diesem Fall genügt also der Eintrag „paul“ für die Addresse paul@myserver
Danach klicken wir auf den Button Abschicken und Paul ist als Benutzer in LDAP verfügbar.
Jetzt richten wir noch den externen MailAccount von Paul ein, damit er auch seine Mails von GMX abrufen bzw. über GMX schicken kann. Dazu erweitern wir die Ansicht der LDAP-Hierarchie, so dass wir mit einem Rechtsklick auf paul erneut den Eintrag Neu wählen können.
Im erscheinenden Dialogfeld wählen wir die Klassen dcExternalMailAccount und dcPosixSubAccount aus. RDN setzen wir auf dcSubMailAddress=paulpanzer@gmx.de. Folgende Attribute können bzw. müssen wir eintragen:
- dcSubMailAddress steht für die Mail-Addresse des externen Accounts. Lokale Mails an diese Addresse werden ohne den Umweg über den externen Mailprovider zugestellt.
- dcAccountStatus kann die Werte active, noaccess, disabled und deleted annehmen. Wir wählen active.
- dcMailQuota ist ein Attribut, das wir nicht verwenden werden, allerdings könnte man hier zukünftig eine Größenbeschränkung für die paulpanzer@gmx.de-Mailbox einrichten.
- dcMailSizeMax verwenden wir ebenfalls nicht, allerdings könnte man hier zukünftig eine Beschränkung der Größe der zu versendenden E-Mails festlegen.
- dcRetrieveType gibt den Protokoll/Typ an, mit dem die Mails abgerufen werden sollen. Beispielhafte Werte sind SimplePOP3Retriever, BrokenUIDLPOP3Retriever oder SimpleIMAPSSLRetriever. Eine detaillierte Auflistung findet sich in der Dokumentation von getmail.
- dcRetrieveLogin der Benutzername für den Mailabruf, bei GMX üblicherweise die E-Mail-Addresse
- dcRetrievePassword das zugehörige Passwort, um Mails abzurufen.
- dcRetrieveServer der Name/IP des Servers für das Abrufen von Mails. Bei GMX mit POP3 ist es pop.gmx.net.
- dcSMTPLogin der Benutzername für den SMTP-Server, bei GMX üblicherweise die E-Mail-Addresse.
- dcSMTPPassword das zugehörige Passwort, um Mails zu versenden.
- dcSMTPServer der Name/IP des SMTP-Servers. Bei GMX ist es mail.gmx.net.
- dcMailAlternateAddress steht für eventuelle Alias-Addressen der bei dcSubMailAddress angegebenen E-Mail-Addresse. Besitzt Paul Panzer also für die Addresse paulpanzer@gmx.de noch den Alias p.panzer@gmx.de kann er die Mail hier eintragen und Mails über den lokalen Server werden direkt ohne Umwege über GMX zugestellt.
- dcPosixOwnerURL dient dazu, dass dovecot wichtige Parameter, wie uid, uidNumber,gidNumber und dcMailMessageStore vom übergeordneten Benutzereintrag von Paul bekommt. Hier tragen wir folgende LDAP-URL ein:
ldap:///uid=paul,ou=users,o=effinger?uid,uidNumber,gidNumber,dcMailMessageStore?base?(&(objectClass=posixAccount)(objectClass=dcMailUser))
Und so sieht das bei mir aus:
Nun wieder auf Abschicken klicken und der Eintrag sollte vorhanden sein. Wichtig ist, jetzt nochmal zu prüfen, ob auch das Dynlist-Overlay funktioniert. Das machen wir mit einem
ldapsearch -b "dcSubMailAddress=paulpanzer@gmx.de,uid=paul,ou=users,o=effinger" -x
Dieser Befehl sollte unter anderem die Zeilen mit den Attributen uid, uidNumber,gidNumber und dcMailMessageStore augeben:
dcMailMessageStore: /home/paul
gidNumber: 1000
uidNumber: 1000
uid: paul
Testen und Mitschneiden von Anfragen an OpenLDAP
Zum Testen und Debuggen ist es oft hilfreich, zu überprüfen, welche LDAP Anfragen an den OpenLDAP-Server gestellt wurden. Dazu kann man unter cn=config (mit cn=admin,cn=config einloggen) den Parameter olcLogLevel von none auf einen numerischen Wert ändern. 256 hat sich für mich als gut bewährt, bei Terrence Miao findet man aber eine detaillierte Auflistung der einzelnen Loglevels. Die LDAP-Anfragen werden dann in die syslog geschrieben.
Da der Artikel nun schon ziemlich lang ist, folgt die Konfiguration von dovecot in einem zweiten Teil.
[…] OpenLDAP und getmail unter Ubuntu – (4) getmail Nachdem wir in den drei ersten Teilen zunächst OpenLDAP, Dovecot und Exim eingerichtet haben, geht es nun daran, getmail so einzurichten, dass Mails von […]
[…] Exim, OpenLDAP und getmail unter Ubuntu – (3) Exim Nach der Einrichtung von OpenLDAP im ersten Teil, der Anpassung und Konfiguration von dovecot im zweiten Teil befasst sich der dritte Teil mit der […]
[…] In den letzten vier Blogartikeln wurde das Zusammenspiel der Grundkomponenten mit Dovecot, Exim, OpenLDAP und getmail konfiguriert. Jetzt geht es ans Feintuning – das Einrichten eines Spamfilters mit […]
[…] ähnlich wie zu der Beschreibung in meinen anderen Blog-Artikeln (Das kleine OpenLDAP 1×1, OpenLDAP im Mailserversetup unter Ubuntu) beschrieben hatte, allerdings gibt es an der ein oder anderen Stelle ein paar Unterschiede. Damit […]
Hi! Vielen dank erstmal für den Blogpost. Das ist definitiv eine Hilfe 🙂
ein kleines Problemchen gibts aber noch: wenn ich eine Datenbank mithilfe von database.ldif erzeugen will, laufe ich trotz vermutlich richtigem passwort (das bei der slapd Installation vergeben wurde) immer wieder gegen die Wand:
ldap_bind: Invalid credentials (49)
was mach‘ ich verkehrt?
Ein falsches Passwort ist das Erste, was mir einfällt. Mit einem
sollte sich das Passwort aber zurücksetzen lassen. Ansonsten kommen ggfs. noch zerschossene Konfigurationsdateien insbesondere die verschiedenen ldap.conf in Frage.
Das Problem hatte ich auch, das hat irgendwie mit der Basisinstallation und -konfig von OpenLDAP (Credentials über SASL oder so?) zu tun. Sämtliche Einträge für die cn=config kann man mit folgendem Befehl als root durchführen:
ldapadd -Y EXTERNAL -H ldapi:/// -f name-des.ldif
Jetzt muss ich nur noch rausfinden, warum das Mistding den SSL-Handshake verweigert.
Hallo,
erst einmal vielen Dank für dein umfangreiches Tutorial. Mich würde interessieren, ob es möglich ist für die Einzelnen Mail-Accounts mehrere externe IMAP/POP und SMTP-Konten hinzuzufügen?
Viele Grüße,
André
Hallo,
ich versuche jetzt schon seit drei Wochen mein Debian Wheezy Server entsprechend zu installieren ohne Erfolg. Ich würde mich sehr freuen wenn Du Dich mal melden würdest. Mein Problem konnte ich auf den Teil LDAP Einrichtung eingränzen. Irgendwie funktionieren die ldapsearch Aufrufe nicht, obwohl die Einträge vorhanden sind.
Lieben Gruß von Stefan Harbich
Hallo,
irgendwie komme ich bei dem Schritt ein Benutzer einrichten „In Deinem Beispiel paul…“ nicht weiter. Der Benutzer wird doch im LDAP eingerichtet, oder? D.h. das er in der lokalen /etc/passwd bzw /etc/group nicht vorhanden ist, oder? Und genau das ist das Problem im zweiten Schritt. Bei den Suchabfragen wird aber immer auf die lokalen Dateien referrenziert. Oder mache ich da was falsch?
Lieben Gruß von Stefan Harbich
Hallo Stefan,
um dein Problem besser zu verstehen wäre es gut, wenn du noch genauer beschreibst, was du mit dem Problem im zweiten Schritt meinst.
Viele Grüße Markus
Hallo Markus,
wenn ich den Befehl „ldapsearch -b „dcSubMailAddress=sharbich@xyz.de,uid=stharbich,ou=users,dc=xyz,dc=de“ -x, auf dem Server als user stharbich ausführe, bekomme ich nicht die Ergebnisse wie in Deinen Blog aufgelistet (z.B. uid, guid, etc.).
Führe ich Befehl als root aus, bekomme ich die ähnlichen Ergebnisse wie Du angezeit.
Bei der “ Konfiguration von dovecot in einem zweiten Teil“ habe ich auch Probleme, die ich Dir gepostet habe.
Viele Grüße von Stefan Harbich
Das hört sich so an, als ob Schritt 7 mit den ACLs nicht korrekt durchgeführt wurde, d.h. dem Benutzer selbst die Berechtigungen für die eigenen Einträge fehlen. Kannst du das prüfen?
Ja, da hast Du Recht. Nun geht es. Allerdings habe ich noch ein Problem beim Einrichten und testen von Dovecot im zweiten Teil. Ich habe es Dir im zweiten Teil gepostet.
Lieben Gruß von Stefan Harbich