OpenLDAP in Dovecot und Postfix zum Login nutzen

In den letzten Beiträgen ging es von mir viel um OpenLDAP. Da ich gerne ein Mailsystem an den LDAP Server anbinden wollte, hab ich mal etwas mit der Dovecot und Postfix Konfiguration rumgespielt. Grundsätzlich gehe ich von einem OpenLDAP Server aus, der mit LDAPS abgesichert ist.
Viele Skripte stammen aus dem Blog von André, jedoch hat er dies mit einem Active Directory gemacht. Die Konfigurationen hier sind auf Debian 10 getestet worden außerem ist Sie vollständig kompatibel mit dem Mailserver Setup von Thomas Leister.

In diesem Setup ist das Verwalten von Gruppen/Aliasen, Mailboxen (mit Qouta) sowie Domains via LDAP konfigurierbar.

Mailboxen werden via RFC822 Mailbox Atribut in der ou=people abgelegt.
Domains werden via objectClass dNSDomain mit dem dc Atribut in der out=domains verwaltet.
Gruppen/Aliases werden in der ou=groups in objectClass groupOfNames zusammengefasst.
Als Default Passwort Schema wurde SSHA-512 gewählt.

OpenLDAP Schemas

Da wir für die User zwei Atribute brauchen (mailEnabled und mailQuota) und den Gruppen auch ein mail-Atribut zuordnen können müssen, habe ich ein weiteres Schema erstellt.
Wie man neue Schemas bei OpenLDAP hinzufügt habe ich bereits hier beschrieben.

attributetype (1.3.6.1.4.1.8869.2.3.1 NAME 'mailEnabled'
    DESC 'Mailbox Enabled'
    EQUALITY booleanMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE)


attributetype (1.3.6.1.4.1.8869.2.3.2 NAME 'mailQuota'
        DESC 'defines how much mail quota is available for the user'
        EQUALITY caseIgnoreMatch
        SUBSTR caseIgnoreSubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE)

attributetype (1.3.6.1.4.1.8869.2.3.3 NAME 'mailGroup'
        DESC 'RFC1274: RFC822 Mailbox'
        EQUALITY caseIgnoreIA5Match
        SUBSTR caseIgnoreIA5SubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256})

objectclass ( 1.3.6.1.4.1.8869.2.4.1 NAME 'mailExtension'
        DESC 'More Mail Options'
        SUP top AUXILIARY
        MUST ( cn  )
        MAY ( mailEnabled $ mailQuota )
        )

objectclass ( 1.3.6.1.4.1.8869.2.4.2 NAME 'groupMail'
        DESC 'Group mail address'
        SUP top AUXILIARY
        MUST ( cn  )
        MAY ( mailGroup )
        )

Dovecot

Für dovecot muss dovecot-ldap installiert sein. Anschließend folgende Datei anlegen.

/etc/dovecot/dovecot-ldap.conf
uris                 = ldaps://ldap.example.com
dn                   = cn=admin,dc=user,dc=mc8051,dc=de
dnpass               = XYZ
tls                  = no
auth_bind            = no
base                 = ou=people,dc=user,dc=mc8051,dc=de
scope                = subtree
default_pass_scheme  = SSHA-512
ldap_version         = 3
user_attrs = \
  =quota_rule=*:bytes=%{ldap:mailQuota}, \
  =home=/var/vmail/mailboxes/%d/%{ldap:uid}, \
  =mail=maildir:/var/vmail/mailboxes/%d/%{ldap:uid}/mail
user_filter          = (&(mail=%u)(objectClass=person)(mailEnabled=TRUE))
pass_attrs           = mail=user,userPassword=password
pass_filter          = (&(mail=%u)(objectClass=person)(mailEnabled=TRUE))
iterate_attrs        = mail=user
iterate_filter       = (objectClass=person)

Wie auch hier die Hinweise von André zu user_attrs:
– Die „ldap:mailQuota“ muss im LDAP nicht in Byte angegeben werden, auch möglich sind Werte wie 100M oder 2G.
– Der Parameter „home“ ist das Heimverzeichnis des Mailusers. Dieses sollte niemals dem Mailverzeichnis entsprechen.
– Jedoch können „home“ und „mail“ zwei komplett unterschiedliche Verzeichnisse sein.

Damit die Kompatibilität mit dem Setup von Thomas Leister existiert sind die home/mail Verzeichnisse wie folgt gewählt.

home: /var/vmail/mailboxes/domain.tld/username
mail: /var/vmail/mailboxes/domain.tld/username/mail

Zur Konfiguration von Dovecot nun noch die passdb und userdb anpassen mit dem LDAP Treiber.

passdb {
    driver = ldap
    args = /etc/dovecot/dovecot-ldap.conf
}

userdb {
    driver = ldap
    args = /etc/dovecot/dovecot-ldap.conf
}

Postfix

Für postifx muss das Paket postfix-ldap installiert worden sein. Die LDAP Filter lege ich in /etc/postfix/ldap/ ab.

/etc/postfix/ldap/sender_login_maps.cf
server_host      = ldaps://ldap.example.com
bind             = yes
start_tls        = no
version          = 3
bind_dn          = cn=admin,dc=user,dc=mc8051,dc=de
bind_pw          = XYZ
search_base      = ou=people,dc=user,dc=mc8051,dc=de
scope            = sub
query_filter     = (&(mail=%s)(objectClass=person)(mailEnabled=TRUE))
result_attribute = mail
/etc/postfix/ldap/virtual_group_maps .cf
server_host              = ldaps://ldap.example.com
bind                     = yes
start_tls                = no
version                  = 3
bind_dn                  = cn=admin,dc=user,dc=mc8051,dc=de
bind_pw                  = XYZ
search_base              = ou=groups,dc=user,dc=mc8051,dc=de
scope                    = sub
query_filter             = (&(objectClass=groupOfNames)(mailGroup=%s))
leaf_result_attribute    = mail
special_result_attribute = member
result_attribute         = mail
debuglevel               = 0
/etc/postfix/ldap/virtual_forward_maps.cf
server_host      = ldaps://ldap.example.com
bind             = yes
start_tls        = no
version          = 3
bind_dn          = cn=admin,dc=user,dc=mc8051,dc=de
bind_pw          = XYZ
search_base      = ou=people,dc=user,dc=mc8051,dc=de
scope            = sub
query_filter     = (&(mail=%s)(mailGroup=*)(mailEnabled=TRUE)(objectClass=person))
result_attribute = mailGroup
debuglevel       = 0
/etc/postfix/ldap/virtual_mailbox_domains.cf
server_host      = ldaps://ldap.example.com
bind             = yes
start_tls        = no
version          = 3
bind_dn          = cn=admin,dc=user,dc=mc8051,dc=de
bind_pw          = XYZ
search_base      = ou=domains,dc=user,dc=mc8051,dc=de
scope            = sub
query_filter     = (&(dc=%s)(objectClass=dNSDomain))
result_attribute = dc
/etc/postfix/ldap/virtual_mailbox_maps.cf
server_host      = ldaps://ldap.example.com
bind             = yes
start_tls        = no
version          = 3
bind_dn          = cn=admin,dc=user,dc=mc8051,dc=de
bind_pw          = XYZ
search_base      = ou=people,dc=user,dc=mc8051,dc=de
scope            = sub
query_filter     = (&(mail=%s)(objectClass=person)(mailEnabled=TRUE))
result_attribute = mail
result_format    = /var/vmail/mailboxes/%d/%u/mail/
debuglevel       = 0

Abschließend die Filter in der main.cf angeben.

/etc/postfix/main.cf
smtpd_sender_login_maps = ldap:/etc/postfix/ldap/sender_login_maps.cf
virtual_mailbox_maps = ldap:/etc/postfix/ldap/virtual_mailbox_maps.cf
virtual_alias_maps = ldap:/etc/postfix/ldap/virtual_forward_maps.cf ldap:/etc/postfix/ldap/virtual_group_maps.cf
virtual_mailbox_domains = ldap:/etc/postfix/ldap/virtual_mailbox_domains.cf
local_recipient_maps = $virtual_mailbox_maps

Das war alles.
Wer gerne etwas mehr Über die LDAP Filter wissen möchte, den Verweise ich gerne an diese Seite. Hier sind die Operanden ziemlich gut beschrieben.

Die Mailbox/Domain/Alias Verwaltung sieht dann beispielhaft wie folgt aus.

# Nutzer nico mit normalen Postfach nico@example.com mit 2 GB Quota
dn: uid=nico,ou=people,dc=ldap,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: mailExtension
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: nico
sn: ipsum
displayName: nico
mail: nico@example.com
mailEnabled: TRUE
mailQuota: 2G
uid: nico
userPassword:: EIN-PASSWORT

# Nutzer teemo mit der Email teemo@example.com
# Nutzer hat Mailweiterleitung aktiv an someone@gmail.com mit einer Kopie an sein eigenes Konto
dn: uid=teemo,ou=people,dc=ldap,dc=example,dc=com
objectClass: groupMail
objectClass: inetOrgPerson
objectClass: mailExtension
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: teemo
sn: ipsum
mail: teemo@example.com
mailEnabled: TRUE
mailGroup: someone@gmail.com,teemo@example.com
mailQuota: 500M
uid: teemo
userPassword:: EIN-ANDERES-PASSWORT

# Interne Alias Gruppe
# Mails an mailgruppe@example.com werden an die uid=nico weitergeleitet
dn: cn=mailgruppe,ou=groups,dc=ldap,dc=example,dc=com
objectClass: groupMail
objectClass: groupOfNames
objectClass: top
cn: mailgruppe
member: uid=nico,ou=people,dc=ldap,dc=example,dc=com
mailGroup: mailgruppe@example.com


dn: dc=example.com,ou=groups,dc=ldap,dc=example,dc=com
objectClass: dNSDomain
objectClass: domain
objectClass: top
dc: example.com

1 Kommentar

  1. Markus

    Erstmal vielen Dank für die tolle Anleitung! War ein guter Startpunkt für mich, jedoch musste ich trotzdem viele Sachen ändern um den bei uns gewünschten Funktionsumfang zu entsprechen…
    Ich hätte allerdings für diese „Grundkonfiguration“ noch ein paar Verbesserungsvorschläge bezüglich der angewandten filter:

    bei der virtual_group_maps.cf: wäre es da nicht besser, beim filter nach objectClass=groupMail zu suchen? das würde glaube ich die Suche stark verkürzen wenn man nur wenige Gruppen mit einer Mailadresse hat.

    ähnliches auch bei der sender_login_maps.cf, virtual_forward_maps.cf, virtual_mailbox_maps.cf: wenn man nur wenige Nutzer mit der mailExtension hat, gibt es einen ziemlichen Overhead wenn alle mit objectClass=person nach mailEnabled=true durchsucht werden. da kann man die searchbase drastisch reduzieren wenn man dem filter objectClass=mailExtension statt objectClass=person mitgibt.

    Gleiches auch in der dovecot-ldap.conf

    Oder spricht da etwas großartig gegen?

    Antworten

Schreiben Sie einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert