Dernière mise à jour : 09/09/2009
Nous allons couvrir dans cet article comment paramétrer un serveur de mail pour s'authentifier à un serveur OpenLDAP (utilisateurs virtuels) et pouvoir envoyer/recevoir des emails de façon transparente avec authentification SMTP/TLS. Ce tutoriel a été effectué sur une Debian. Je vous conseille d'avoir un serveur OpenLDAP bien configuré. Afin de simplifier les commandes, on considère que le serveur LDAP est local. Dans cet exemple, la base LDAP est frlinux.net (dc=frlinux,dc=net).
Attention : Avant de continuer, je tiens à préciser que cette page me sert plus de pense-bête que de tutoriel facile à suivre. Donc il se peut que j'ai oublié des choses, mais la configuration d'un serveur LDAP avec cette méthode n'est pas aisée, donc je ne peux pas vraiment vous aider si quelque chose ne fonctionne pas chez vous (et cela essentiellement du à tous les paquets à installer pour que cela fonctionne).
Installez les paquets suivants : apt-get install postfix postfix-ldap postgrey slapd amavisd-new courier-maildrop libnet-ldap-perl courier-authdaemon courier-authlib-ldap ldap-utils. Il faut commencer par ajouter les bons schémas dans OpenLDAP, éditez donc /etc/ldap/slapd.conf pour ajouter les lignes suivantes :
include /etc/ldap/schema/courier.schema include /etc/ldap/schema/ISPEnv2.schema include /etc/ldap/schema/amavis.schema include /etc/ldap/schema/ppolicy.schema
Il se peux qu'il vous manque le fichier /etc/ldap/schema/courier.schema. Voici donc une copie du miens :
#$Id: authldap.schema,v 1.5 2004/04/18 15:54:38 mrsam Exp $ # # OID prefix: 1.3.6.1.4.1.10018 # # Attributes: 1.3.6.1.4.1.10018.1.1 # # Depends on: nis.schema, which depends on cosine.schema attributetype ( 1.3.6.1.4.1.10018.1.1.1 NAME 'mailbox' DESC 'The absolute path to the mailbox for a mail account in a non-default location' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.10018.1.1.2 NAME 'quota' DESC 'A string that represents the quota on a mailbox' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.10018.1.1.3 NAME 'clearPassword' DESC 'A separate text that stores the mail account password in clear text' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128}) attributetype ( 1.3.6.1.4.1.10018.1.1.4 NAME 'maildrop' DESC 'RFC822 Mailbox - mail alias' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) attributetype ( 1.3.6.1.4.1.10018.1.1.5 NAME 'mailsource' DESC 'Message source' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.10018.1.1.6 NAME 'virtualdomain' DESC 'A mail domain that is mapped to a single mail account' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.10018.1.1.7 NAME 'virtualdomainuser' DESC 'Mailbox that receives mail for a mail domain' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) attributetype ( 1.3.6.1.4.1.10018.1.1.8 NAME 'defaultdelivery' DESC 'Default mail delivery instructions' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) # # Objects: 1.3.6.1.4.1.10018.1.2 # objectclass ( 1.3.6.1.4.1.10018.1.2.1 NAME 'CourierMailAccount' SUP top AUXILIARY DESC 'Mail account object as used by the Courier mail server' MUST ( mail $ homeDirectory $ uidNumber $ gidNumber ) MAY ( mailbox $ uid $ cn $ gecos $ description $ loginShell $ quota $ userPassword $ clearPassword $ defaultdelivery) ) objectclass ( 1.3.6.1.4.1.10018.1.2.2 NAME 'CourierMailAlias' SUP top AUXILIARY DESC 'Mail aliasing/forwarding entry' MUST ( mail $ maildrop ) MAY ( mailsource $ description ) ) objectclass ( 1.3.6.1.4.1.10018.1.2.3 NAME 'CourierDomainAlias' SUP top AUXILIARY DESC 'Domain mail aliasing/forwarding entry' MUST ( virtualdomain $ virtualdomainuser ) MAY ( mailsource $ description ) )
Pensez également à modifier /etc/courier/authdaemonrc pour contenir authldap dans la ligne authmodulelist.
Il vous faut ensuite rentrer les bonnes informations dans l'annuaire OpenLDAP, nous commençons donc par les acl et le tout qui va bien. Je me sers d'ACLs pour protéger le serveur et éviter les envois/réceptions mails de personnes non déclarées.
dn: ou=aclfrlinux,dc=frlinux,dc=net objectClass: organizationalUnit ou: aclfrlinux dn: cn=unix,ou=aclfrlinux,dc=frlinux,dc=net objectClass: top objectClass: groupOfNames member: uid=root,ou=people,dc=frlinux,dc=net ou: unixusers cn: unix dn: ou=mail,ou=aclfrlinux,dc=frlinux,dc=net objectClass: organizationalUnit ou: mail dn: ou=people,dc=frlinux,dc=net objectClass: organizationalUnit ou: people dn: ou=Aliases,dc=frlinux,dc=net ou: Aliases objectClass: top objectClass: organizationalUnit
Ajoutez ensuite un compte comme ceci (attention, il vous faut remplacer le mot de passe en xxxxxxx par des hashes valides en MD5) :
dn: uid=frlinux,ou=People,dc=frlinux,dc=net objectClass: inetOrgPerson objectClass: posixAccount objectClass: top objectClass: CourierMailAccount objectClass: amavisAccount objectClass: Vacation sn: Linux cn: Fr displayName: System User mail: frlinux@frlinux.net uid: frlinux uidNumber: 1000 gidNumber: 1000 homeDirectory: /home/frlinux loginShell: /bin/bash gecos: Fr Linux mailbox: frlinux.net/frlinux defaultdelivery: . vacationActive: FALSE userPassword:: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx dn: uid=frlinux@frlinux.net,ou=mail,ou=aclfrlinux,dc=frlinux,dc=net objectClass: top objectClass: alias objectClass: extensibleObject aliasedObjectName: uid=frlinux,ou=people,dc=frlinux,dc=net uid: frlinux@frlinux.net
Changez ensuite le mot de passe comme ceci : ldappasswd -S -x -D "cn=Administrator,dc=frlinux,dc=net" -W "uid=frlinux,ou=People,dc=frlinux,dc=net". Notez qu'il faut remplacer Administrator par le bon compte servant à gérer votre OpenLDAP. Il y a encore quelques informations à entrer pour faire quelque chose de bien propre :
dn: ou=domains,dc=frlinux,dc=net objectClass: organizationalUnit ou: domains dn: ou=mailscripts,dc=frlinux,dc=net objectClass: organizationalUnit ou: mailscripts dn: virtualdomain=frlinux.net,ou=domains,dc=frlinux,dc=net objectClass: top objectClass: account objectClass: CourierDomainAlias uid: frlinux.net virtualdomain: frlinux.net virtualdomainuser: frlinux.net
Pour gérer les emails et la livraison, j'utilise un petit outil exotique du nom de gnarwl. Il vous permettra de permettre à vos utilisateurs de mettre une réponse automatique si nécessaire. Il vous faut pour cela ajouter les informations suivantes dans OpenLDAP :
dn: mail=gnarwl,ou=mailscripts,dc=frlinux,dc=net objectClass: top objectClass: account objectClass: CourierMailAlias uid: gnarwl vacation script mail: gnarwl maildrop: |/usr/bin/gnarwl dn: mail=gnarwl@frlinux.net,ou=Aliases,dc=frlinux,dc=net objectClass: top objectClass: account objectClass: CourierMailAlias uid: mail to local gnarwl user to run vacation program mail: gnarwl@frlinux.net maildrop: gnarwl
J'ai du patcher gnarwl afin de gérer le dereferencing sous OpenLDAP. Voici le patch à appliquer (sauvez le sous le nom gnarwl.patch):
diff -Nuar gnarwl-3.3/doc/HISTORY gnarwl-3.4/doc/HISTORY --- gnarwl-3.3/doc/HISTORY 2003-11-29 21:49:25.000000000 +0000 +++ gnarwl-3.4/doc/HISTORY 2006-02-10 17:38:02.000000000 +0000 @@ -244,3 +244,6 @@ - Added another way to make gnarwl work with postfix to doc/INSTALL (thanx Thomas). - Rewrote the Troubleshooting section in doc/INSTALL. + +3.4 +- Minor change to add ldap dereferencing support diff -Nuar gnarwl-3.3/src/config.c gnarwl-3.4/src/config.c --- gnarwl-3.3/src/config.c 2003-01-28 10:28:45.000000000 +0000 +++ gnarwl-3.4/src/config.c 2006-02-15 16:21:02.000000000 +0000 @@ -179,6 +179,13 @@ } return; } + if (!strcasecmp(key,"deref")) { + if (!strcasecmp(val,"never")) cfg.deref=LDAP_DEREF_NEVER; + if (!strcasecmp(val,"search")) cfg.deref=LDAP_DEREF_SEARCHING; + if (!strcasecmp(val,"find")) cfg.deref=LDAP_DEREF_FINDING; + if (!strcasecmp(val,"always")) cfg.deref=LDAP_DEREF_ALWAYS; + return; + } syslog(LOG_MAIL|LOG_WARNING,"WARN/CFG Unknown config directive: %s",key); } @@ -212,6 +219,7 @@ cpyStr(&cfg.recv_header[0],"to"); cpyStr(&cfg.recv_header[1],"cc"); if (cfg.macro_attr==NULL || cfg.macro_name==NULL) oom(); + cfg.deref=LDAP_DEREF_FINDING; } void readConf(char *cfile) { diff -Nuar gnarwl-3.3/src/config.h gnarwl-3.4/src/config.h --- gnarwl-3.3/src/config.h 2003-01-28 10:28:45.000000000 +0000 +++ gnarwl-3.4/src/config.h 2006-02-10 17:34:17.000000000 +0000 @@ -29,6 +29,7 @@ int maxmail; // max number of recepients allowed int maxheader; // max number of header lines allowed in mail int umask; // file creation mask for db files + int deref; // When to follow LDAP aliases }; /** diff -Nuar gnarwl-3.3/src/dbaccess.c gnarwl-3.4/src/dbaccess.c --- gnarwl-3.3/src/dbaccess.c 2003-01-28 10:28:45.000000000 +0000 +++ gnarwl-3.4/src/dbaccess.c 2006-02-10 17:34:38.000000000 +0000 @@ -192,6 +192,7 @@ if (ldap_simple_bind_s(ldcon,cfg.uid,cfg.pwd)==LDAP_SUCCESS) return; } else ldap_set_option(ldcon,LDAP_OPT_PROTOCOL_VERSION, &cfg.protver); + ldap_set_option(ldcon,LDAP_OPT_DEREF, &cfg.deref); #endif rc=ldap_simple_bind_s(ldcon,cfg.uid,cfg.pwd);
Editez votre /etc/apt/sources.list pour ajouter ceci (ce n'est pas par erreur qu'on prends gnarwl depuis unstable, il n'existe plus dans lenny) :
# a commenter une fois que vous avez récupéré le source de gnarwl deb-src http://ftp.ie.debian.org/debian unstable main contrib non-free
Il faut ensuite patcher et compiler :
cd /usr/local/src mkdir gnarwl cd gnarwl apt-get source gnarwl apt-get install debhelper libldap-dev libgdbm-dev patch -p0 < /root/gnarwl.patch cd gnarwl-3.3 debian/rules binary cd .. dpkg -i gnarwl_3.3-8.5_amd64.deb # nous creons à présent l'utilisateur virtuel pour les mails et les répertoires groupadd -g 111 vmail useradd -d /var/mail -u 111 -g 111 vmail # Chaque domaine sera de la forme /var/mail/$domaine/$utilisateur mkdir /var/mail/frlinux.net/frlinux cd /var/mail/frlinux.net/frlinux # pour chaque utilisateur créer le répertoire de base maildirmake Maildir chown -R vmail:vmail /var/mail/frlinux.net
Voici le fichier de configuration de /etc/gnarwl.cfg
map_sender $sender map_receiver $recepient map_subject $subject map_field $begin vacationStart map_field $end vacationEnd map_field $fullname cn map_field $deputy vacationForward server 127.0.0.1 port 389 scope sub login password protocol 3 base dc=frlinux,dc=net queryfilter (&(mail=$recepient)(vacationActive=TRUE)) result vacationInfo blockfiles /var/lib/gnarwl/block/ umask 0644 blockexpire 48 mta /usr/sbin/sendmail -F $recepient -t maxreceivers 64 maxheader 512 charset ISO8859-1 badheaders /var/lib/gnarwl/badheaders.db blacklist /var/lib/gnarwl/blacklist.db forceheader /var/lib/gnarwl/header.txt forcefooter /var/lib/gnarwl/footer.txt recvheader To Cc deref 3 loglevel 1
Passons maintenant à la partie amusante : postfix. Il y a beaucoup de configuration à faire. Commençons donc par main.cf (je ne liste ici que ce qui est à ajouter, notez aussi que les uid et gid dépendent de votre installation) :
recipient_delimiter = virtual_maps = ldap:/etc/postfix/virtualmaps virtual_transport = maildrop maildrop_destination_recipient_limit = 1 virtual_mailbox_base = /var/mail/ virtual_mailbox_maps = ldap:/etc/postfix/accounts virtual_mailbox_domains = ldap:/etc/postfix/virtualdomains virtual_minimum_uid = 111 virtual_uid_maps = static:111 virtual_gid_maps = static:112
Comme vous avez pu le constater, nous avons ajoutés 4 fichiers : virtualmaps, accounts et virtualdomains. Pensez également à faire un postmap /etc/postfix/mailscripts :
$ cat /etc/postfix/virtualmaps server_host = ldap://127.0.0.1/ search_base = ou=aliases,dc=frlinux,dc=net query_filter = (&(objectClass=CourierMailAlias)(mail=%s)) result_attribute = maildrop version = 3 bind = no $ cat /etc/postfix/accounts server_host = ldap://127.0.0.1/ search_base = ou=mail,ou=aclfrlinux,dc=frlinux,dc=net query_filter = (&(objectClass=CourierMailAccount)(mail=%s)) dereference = 3 result_attribute = mailbox version = 3 bind = no $ cat /etc/postfix/virtualdomains server_host = ldap://127.0.0.1/ search_base = ou=domains,dc=frlinux,dc=net query_filter = (&(objectClass=CourierDomainAlias)(virtualdomain=%s)) result_attribute = virtualdomain version = 3 bind = no $ cat /etc/postfix/mailscripts server_host = ldap://127.0.0.1/ search_base = ou=mailscripts,dc=frlinux,dc=net query_filter = (&(objectClass=CourierMailAlias)(mail=%s)) result_attribute = maildrop version = 3 bind = no
Modifier ensuite /etc/postifx/master.cf et ajouter les lignes suivantes :
smtp-amavis unix - - n - 2 smtp -o smtp_data_done_timeout=1200 127.0.0.1:10025 inet n - n - - smtpd -o cleanup_service_name=cleanupAF -o content_filter= cleanupAF unix n - n - 0 cleanup -o always_bcc=gnarwl
Il faut ensuite modifier amavis et particulier /etc/amavis/conf.d/50-user :
$enable_ldap = 1; $default_ldap = { hostname => '127.0.0.1', port => 389, version => 3, timeout => 120, tls => 0, base => 'ou=mail,ou=aclfrlinux,dc=frlinux,dc=net', scope => 'sub', query_filter => '(&(objectClass=amavisAccount)(mail=%m))', bind_dn => undef, bind_password => undef, deref => 'always', }; #send back to postfix $forward_method = 'smtp:[127.0.0.1]:10025'; # set to undef with milter! #------------ Do not modify anything below this line ------------- 1; # insure a defined return
Nous passons à présent à la configuration de courier. Editez /etc/courier/authdaemonrc et changez la ligne authmodulelist= pour ne contenir que ceci :
authmodulelist="authldap"
Editez ensuite /etc/courier/authldaprc pour contenir ceci :
LDAP_URI ldap://localhost LDAP_PROTOCOL_VERSION 3 LDAP_BASEDN ou=mail,ou=aclfrlinux,dc=frlinux,dc=net LDAP_TIMEOUT 5 LDAP_AUTHBIND 1 LDAP_MAIL mail LDAP_FILTER (objectClass=CourierMailAccount) LDAP_DOMAIN frlinux.net LDAP_GLOB_UID vmail LDAP_GLOB_GID vmail LDAP_HOMEDIR mailbox LDAP_MAILROOT /var/mail LDAP_FULLNAME cn LDAP_CRYPTPW userPassword LDAP_DEREF always LDAP_TLS 0
Installez courier-imap-ssl : apt-get install courier-imap-ssl et editez /etc/courier/imapd.cnf pour qu'il corresponde à vos critères. Puis redémarrez le serveur imap : dpkg-reconfigure courier-imap-ssl. Pour réussir à faire marcher l'authentification, j'ai du changer le mot de passe à la main grâce à cette commande : ldappasswd -S -x -D "cn=Administrator,dc=frlinux,dc=net" -W "uid=frlinux,ou=People,dc=frlinux,dc=net". Pensez a donner la bonne permission au démon authdaemon
chown -R vmail.daemon /var/run/courier/authdaemon/
Voilà ceci conclu l'installation d'un serveur de mail géré par LDAP. Sous peu je rajouterais comment ajouter un domaine virtuel avec des alias.