<divclass="col-main cell cell--auto"><!-- start custom main top snippet --><divid="results-container"class="search-result js-search-result"></div><!-- end custom main top snippet -->
<articleitemscopeitemtype="http://schema.org/Article"><divclass="article__header"><header><h1style="color:Tomato;">OpenLDAP installation et configuration annuaire xoyize.xyz</h1></header></div><metaitemprop="headline"content="OpenLDAP installation et configuration annuaire xoyize.xyz"><divclass="article__info clearfix"><ulclass="left-col menu"><li>
<li><ahref="https://www.vennedey.net/resources/0-Getting-started-with-OpenLDAP-on-Debian-8">Getting started with OpenLDAP on Debian </a></li>
<li><ahref="https://www.vennedey.net/resources/2-LDAP-managed-mail-server-with-Postfix-and-Dovecot-for-multiple-domains">LDAP managed mail server with Postfix and Dovecot for multiple domains</a></li>
<li><ahref="https://wiki.gandi.net/fr/hosting/using-linux/tutorials/debian/mail-server-ldap">Installation d’un serveur mail avec backend OpenLDAP</a></li>
<li><ahref="https://computingforgeeks.com/how-to-install-and-configure-openldap-server-on-debian/">How To Install and Configure OpenLDAP Server on Debian 10 (Buster)</a></li>
<li>
<p><ahref="http://idum.fr/spip.php?article326">Mise en place de OpenLDAP</a> (<em>Le but de cet article est de vous faire découvrir OpenLDAP. En commençant par vous expliquer comment il fonctionne. Puis comment l’installer. Et enfin comment l’administrer.<br/>
Pour nous aider dans cette dernière partie, j’utiliserai l’interface web phpldapadmin.</em>)<br/>
<ahref="/files/Mise en place de OpenLDAP.pdf">Mise en place de OpenLDAP</a> (Document au format PDF)</p>
</li>
<li><ahref="https://blog.debugo.fr/openldap-serie/">OpenLDAP : La série de Tutos</a></li>
<li><ahref="https://blog.debugo.fr/serveur-messagerie-complet-postfix-dovecot-ldap-rspamd/">Serveur Messagerie complet : La série de Tutos</a></li>
</ul>
<h2id="openldap-serveur">OpenLDAP Serveur</h2>
<p><em>Les tests sont effectués sur le serveur xoyize.xyz</em></p>
<p>Avant de commencer l’installation, configurez le nom d’hôte FQDN de votre serveur et ajoutez un enregistrement au fichier <strong>/etc/hosts</strong><br/>
Relever l’adresse ip de votre serveur <codeclass="language-plaintext highlighter-rouge">ip a</code> (ici notre adresse ip 192.168.0.45)</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>echo "192.168.0.45 ldap.xoyize.xyz" | sudo tee -a /etc/hosts
<h3id="installation-et-configuration">Installation et configuration</h3>
<blockquote>
<p>en mode su ou sudo</p>
</blockquote>
<p>L’installation d’OpenLDAP sur Debian est faite à l’aide de la gestion des paquets APT.<br/>
Le premier élément précise que l’installation du paquet <strong>slapd</strong> se fait en mode non interactif et <codeclass="language-plaintext highlighter-rouge">-yq</code> ajoute l’installation en mode silencieux.</p>
<p>Vous voyez plusieurs entrées sous la branche cn=schema. En l’occurrence, core, cosine, nis et inetorgperson.</p>
<p>Ce sont en quelque sorte les modèles qu’utiliseront vos futurs enregistrement (quel attribut, de quel type, etc..). Ceux déjà intégrés sont les plus couramment utilisés, mais il en existe d’autres, soit déjà disponibles dans /etc/ldap/schema :</p>
<p>Il est aussi tout à fait possible de créer vos propres schémas, afin que votre annuaire réponde précisément à vos besoins.</p>
<h4id="les-commandes">Les commandes</h4>
<p>Pour modifier la configuration du serveur nous utiliserons principalement les commandes ldapadd, ldapmodify, ldapdelete (installées avec le paquet ldap-utils) Ces dernières prennent en option un fichier (option -f) de format ldif (Ldap Data Interchange Format).</p>
<p>Nous allons rapidement voir de quoi il s’agit.</p>
<p>Pour effectuer des requêtes, nous utiliserons la commande ldapsearch.</p>
<p>Celle ci peut interroger le serveur LDAP de plusieurs façons.</p>
<p>Sur le socket réseau, nous indiquons les options :</p>
<p>-x : authentification simple.</p>
<p>-H indique l’hôte (en l’occurrence, localhost).</p>
<p>-D est le compte qui va se connecter.</p>
<p>-W sert à demander le mot de passe.</p>
<p>-b ou basedn est l’endroit ou nous voulons faire notre recherche.</p>
<p>La commande fonctionne mais ne retourne rien. Le compte admin n’a pas accès à la configuration en passant par le socket réseau (nous allons y remédier après).</p>
<p>Au passage, pourquoi donc s’embêter alors qu’on ne pourrait qu’utiliser le socket interne ?</p>
<p>L’intérêt du socket réseau est qu’on peut lancer les commandes à distance (dans ce cas remplacer localhost par le nom de la machine distante).
<p>Dans la commande précédente, j’utilise un filtre. Pour les utiliser, il suffit de les indiquer après l’option -b et avant ce que l’on demande par ex :</p>
<p>Petite explication sur l’utilisation des filtres. Ceux ci utilisent un principe qui rappelle la notation polonaise inversée, l’opérateur étant ici devant.</p>
<p>Exemple :</p>
<p>Si je veux A et B :</p>
<p>( & (A) (B) )</p>
<p>Si je veux A ou B</p>
<table>
<tbody>
<tr>
<td>(</td>
<td>(A) (B) )</td>
</tr>
</tbody>
</table>
<p>Si je veux A et B ou A et C :</p>
<table>
<tbody>
<tr>
<td>(</td>
<td>( & (A) (B) ) ( & (A) (C) ) )</td>
</tr>
</tbody>
</table>
<p>ou, en simplifiant :</p>
<table>
<tbody>
<tr>
<td>( & (A) (</td>
<td>(B) (C) ))</td>
</tr>
</tbody>
</table>
<p>On peut aussi inverser avec le !.</p>
<p>Si l’on veut par ex ce qui est A et ce qui n’est pas B :</p>
<p>( & (A) (! B) )</p>
<p>Au niveau des filtres, nous pouvons utiliser les opérateurs suivants :</p>
<ul>
<li>< : plus petit que</li>
<li><= : plus petit ou égal</li>
<li>= : égal</li>
<li>
<blockquote>
<p>: plus grand</p>
</blockquote>
</li>
<li>
<blockquote>
<p>= : plus grand ou égal</p>
</blockquote>
</li>
<li>=* : présence de (retourne les entrées ou l’attribut est présent)</li>
<li>~= : approximation ( par ex, ~=Nocolas pourra retourner Nicolas)</li>
</ul>
<p>On peut utiliser un joker, par ex, = <em>toto</em> sortira tout ce qui contient toto comme sous chaîne.</p>
<p>Il existe également la notion de filtres étendus, utilisé ainsi : attribut:dn:=valeur.</p>
<p>ne me sortira que les entrées ou l’attribut title est égal à Admin (et non pas admin, ADMIN, etc…). Par défaut, l’opération n’est pas sensible à la casse.</p>
<p>Pour connaitre l’ensemble des matchingRules disponibles :</p>
<p>Afin d’éviter d’avoir à toujours retaper le mot de passe admin (mot de passe que nous avons créé lors de la configuration du paquet) lors des commandes, nous allons l’enregistrer dans un fichier.</p>
<p>On va créer un fichier /root/pwdldap et mettre le mot de passe dedans :</p>
<li>accesslog : Enregistrement des accès. Attention, réduit drastiquement les performances.</li>
<li><strong>auditlog</strong> : Enregistrement des modifications.</li>
<li>chain : Liaison de plusieurs serveurs LDAP au niveau des recherches.</li>
<li>collect : Implémentation de la RFC 3671. Les attributs collectifs partagent des valeurs communes entre l’ensemble des membres héritant d’une entrée commune.</li>
<li>constraint : Permet de forcer des contraintes sur des attributs.</li>
<li><strong>memberof</strong> : Permet de connaître les groupes auxquels appartient un utilisateur</li>
<li><strong>ppolicy</strong> : Password Policy. Permet la mise en place de contrôles sur les mots de passe (longueur, durée de validité, etc…).</li>
<li><strong>refint</strong> :Referential Integrity. Permet de s’assurer de la cohérence de l’annuaire lors de suppression d’entrées.</li>
<li>syncprov :Syncrepl Provider. Permet la réplication syncrepl, incluant la fonctionnalité de recherche persistante. On l’installera plus tard.</li>
<li>translucent : Translucent Proxy. Cet overlay peut être utilisé avec un backend local pour créer un proxy transparent. Le contenu des entrées récupérées à partir d’un serveur LDAP distant peut être en partie réécrit/modifé/completé par la base locale.</li>
<li><strong>unique</strong> : permet de s’assurer de l’unicité d’attributs.</li>
<li>valsort : Permet de forcer l’ordre pour les valeurs d’attributs lorsqu’ils sont retournées suite à une recherche.</li>
</ul>
<blockquote>
<p>En gras, ceux dont nous nous servirons.</p>
</blockquote>
<h4id="memberof">MemberOf</h4>
<p>L’overlay memberof permet de savoir dans quels groupes se trouve un utilisateur en une seule requête au lieu de deux.<br/>
Créez un fichier memberof_act.ldif et insérez le contenu suivant :</p>
<p>Cet overlay permet de supprimer un utilisateur d’un groupe quand on supprime l’utilisateur. Au passage, si un groupe se retrouve vide, l’admin sera automatiquement ajouté (un groupe vide créé une erreur dans OpenLdap)</p>
<p>Créez un fichier refint_act.ldif et insérez le contenu suivant :</p>
<p>Cet overlay sert à auditer chaque modification au sein de l’annuaire. Dans notre cas, cela sera inscrit dans le fichier : /var/log/openldap/audit.ldif</p>
<p>Créez le fichier auditlog_act.ldif pour y insérer :</p>
<p>Nous demandons ici à ce que les attributs ui, mail et uidNumber dans l’ou people soient uniques. Et que l’attribut cn dans l’ou groups soit lui aussi unique.</p>
<p>olcPPolicyDefault : Indique le DN de configuration utilisé par défaut (nous le définirons apres).</p>
<p>olcPPolicyHashCleartext : Indique si les mots de passe doivent être cryptés.</p>
<p>olcPPolicyUseLockout : Si TRUE, le message d’erreur retourné en cas de connexion à un compte vérouillé indiquera qu’il s’agit d’un compte vérouillé. Si FALSE, ce sera un message d’échec stantard.</p>
<p>On pourra aussi spécifier cet attribut à la création de l’utilisateur.</p>
<h3id="peuplement-de-lannuaire">Peuplement de l’annuaire</h3>
<h4id="les-ous">Les OUs</h4>
<p>Nous avions créé un répertoire /root/ldap/conf pour y mettre la configuration. Créons un répertoire pour y mettre les fichiers ldif contenant les données.</p>
<p>Pour rappel, les OUs sont des conteneurs qui permettent de ranger les données dans l’annuaire, de les hiérarchiser. Il ne faut pas les confondre avec les Groupes.</p>
<p>Créez un fichier OU.ldif et remplissez le de la sorte :</p>
<p>En cherchant dedans, on va trouver nos objectclasses person et organizationalPerson :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>olcObjectClasses: {4}( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top
STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ telephoneNumber $ seeAlso $
description ) )
olcObjectClasses: {5}( 2.5.6.7 NAME 'organizationalPerson' DESC 'RFC2256: an o
rganizational person' SUP person STRUCTURAL MAY ( title $ x121Address $ regis
<p>On trouve le nom de l’attribut, une description et son type (SYNTAX suivi d’un OID, je reviendrais sur ce point dans le chapitre consacré à la création d’un schéma).</p>
<p>L’objet que l’on créé hérite des attributs des classes person, organizationalPerson et inetOrgPerson.</p>
<p>Voila donc pour les explications sur les ObjectClasses et les AttributeTypes:</p>
<p>Au passage, on va vérifier quelques points.</p>
<p>Regardons comment est stocké le mdp dans la base :</p>
<p>Et si vous tapez le bon mot de passe, cela vous affiche votre propre fiche.</p>
<h4id="les-groupes">Les groupes</h4>
<p>A noter, il existe deux types de groupes : les posixgroup et les groupofnames.
Les posixgroup sont similaires au groupes Unix, et les groupofnames ressemblent plus à des groupes AD.
Pour faire simple, l’avantage des groupofnames est qu’avec un filtre sur un utilisateur, on peut connaitre ses groupes (avec l’overlay memberof). Chose impossible avec les posixgroups.
Par contre, il est impératif d’avoir au moins un utilisateur dans un groupe de type groupofnames. Vous pouvez être tenté de vous mettre par défaut, mais le jour ou vous aller modifier votre schéma, vous allez devoir supprimer les utilisateurs, et un groupe sans utilisateur garde l’uid du dernier membre à l’avoir quitté et si vous refaite un compte avec le même uid, impossible de vous remettre dedans sans supprimer le groupe. Bref, perso, je met l’admin par défaut, comme ça pas de risques. De plus notre overlay refint configuré au préalable est raccord avec cela.</p>
<p>On voit ce que l’accès anonyme nous affiche…</p>
<p>On va devoir filtrer un peu.</p>
<p>Tout d’abord, nous allons créer deux compte systèmes. Un viewer (qui aura des droits de lecture uniquement, utilisé par les applications pour se connecter à l’annuaire et vérifier des droits, au lieu de passe par le bind anonyme) et un Writer (qui lui aura des droits d’écriture…)</p>
olcAccess: to attrs=userPassword by self write by anonymous auth by dn="cn=writer,ou=system,dc=xoyize,dc=xyz" write by dn="cn=viewer,ou=system,dc=xoyize,dc=xyz" read by dn="cn=admin,dc=xoyize,dc=xyz" write by * none
olcAccess: to dn.base="dc=xoyize,dc=xyz" by users read
olcAccess: to * by self write by dn="cn=admin,dc=xoyize,dc=xyz" write by * read by anonymous none
EOF
</code></pre></div></div>
<p>J’expliquerais plus précisément le fonctionnement des ACLs dans un autre article. Nous modifions la deuxieme ACL qui par défaut donne accès en lecture à tout le monde. La, nous réduisons la lecture aux utilisateurs authentifiés.</p>
<p>Je vais profiter de cette partie sur les OU pour expliquer les trois commandes à notre disposition pour modifier les données de l’annuaire : ldapadd, ldapmodify et ldapdelete.</p>
<p>ldapadd est un alias de ldapmodify -a, le commutateur -a indiquant un ajout. Ce commutateur peut être remplacé par la ligne changetype: add dans le fichier ldif.</p>
<p>Ainsi, pour ajouter une OU par ex avec le fichier addou.ldif :</p>
<p>Ces trois façons de faire donnent le même résultat.</p>
<p>L’avantage de tout faire par ex avec ldapmodify est que l’on peut effectuer plusieurs opérations en un fichier, le tout étant de laisser une ligne avec – entre chaque opération.</p>
<p>Dans ce fichier, nous ajoutons une OU puis nous supprimons un utilisateur. Il n’y a pas de limite d’opérations que l’on peut effectuer en une fois.</p>
<h4id="modification-dune-ou">Modification d’une OU</h4>
<p>Nous renommons l’OU test en newtest avec le fichier chgou.ldif :</p>
<h4id="déplacement-dune-ou">Déplacement d’une OU</h4>
<p>Nous déplaçons l’OU newtest de la branche ou=people,dc=xoyize,dc=xyz vers la branche ou=workgroup,ou=group,dc=xoyize,dc=xyz avec le fichier mvou.ldif :</p>
<p>Ceci ne change que le nom de l’entrée dn: uid=tata,ou=client,ou=people,dc=xoyize,dc=xyz. Les autres attributs (cn, sn, etc..) s’ils doivent être renommés seront modifiés par une autre opération (voir plus bas).</p>
<h4id="renommer-un-groupe">Renommer un groupe</h4>
<p>Renommons le groupe test en newtest avec le fichier renamegrp.ldif :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>olcObjectClasses: {7}( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of n
ames (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $
seeAlso $ owner $ ou $ o $ description ) )
</code></pre></div></div>
<p>Pour un groupe, ce qui est le plus fréquent d’ajouter comme attribut, c’est un utilisateur (ajout d’un membre dans un groupe…)</p>
<p>Bref, ajoutons donc notre utilisateur test dans le groupe test avec un fichier addusertogroup.ldif :</p>
<h4id="modifier-un-attribut-utilisateur">Modifier un attribut utilisateur</h4>
<p>Un attribut qui peut etre modifié fréquement sur un utilisateur, c’est le mot de passe. Modifions donc le mot de passe de toto avec un fichier chgpwd.ldif :</p>
<p>-W pour la demande de l’ancien mot de passe.</p>
<p>-S pour la demande d’un nouveau mot de passe (sinon, le nouveau mot de passe est généré aléatoirement)</p>
<p>Cette commande peut également servir à changer le mot de passe d’un autre utilisateur, par exemple, le compte admin demande à changer le mot de passe de l’utilisateur yannick :</p>
<h4id="supprimer-un-attribut-à-un-groupe">Supprimer un attribut à un groupe</h4>
<p>Pour un groupe, vous vous en doutez, un attribut qui peut etre amené à etre supprimé, c’est un membre. Supprimons donc toto du groupe test avec un ficher</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>lsearch -b "dc=xoyize,dc=xyz" "(&(objectclass=groupOfNames)(cn=test))" member
</code></pre></div></div>
<h2id="phpldapadmin">PhpLdapAdmin</h2>
<h3id="pré-requis">Pré-requis</h3>
<p>Pour pouvoir utiliser phpLDAPadmin, vous aurez besoin des éléments suivants :</p>
<ul>
<li>Un serveur LDAP en cours d’exécution de votre choix, quelque part dans votre réseau.
phpLDAPadmin a été développé pour gérer un serveur OpenLDAP, mais il devrait également fonctionner avec d’autres serveurs LDAP. Si vous rencontrez des problèmes avec PLA et votre serveur LDAP, contactez les développeurs et ils se feront un plaisir d’apporter les modifications nécessaires pour que cela fonctionne.</li>
</ul>
<p>Votre serveur LDAP doit également fournir l’accès au schéma en utilisant un lien anonyme. Veuillez vous assurer que vous pouvez voir votre schéma sans avoir à vous lier au serveur LDAP. Un moyen de tester cela pourrait être aussi simple que :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>ldapsearch -xh HOST -b ''' -s base subschemaSubentry
</code></pre></div></div>
<ul>
<li>Un serveur web (Nginx, Apache, IIS, etc.).</li>
<li>Votre serveur web configuré pour utiliser PHP v5 ou + . PHP doit être configuré avec :
<ul>
<li>Support PCRE</li>
<li>Prise en charge des SESSION</li>
<li>Support GETTEXT</li>
<li>Support LDAP</li>
<li>Support XML</li>
</ul>
</li>
</ul>
<h3id="installation">Installation</h3>
<ol>
<li>Installez et configurez votre serveur LDAP favori quelque part sur votre réseau. (Ou, obtenez vos détails LDAP auprès de votre administrateur LDAP.)</li>
<li>Assurez-vous d’avoir toutes les conditions préalables requises</li>
<li>git phpldapadmin version 1.25</li>
<li>Décompressez l’archive à un endroit pratique.</li>
<li>Placez le répertoire’phpldapadmin’ résultant quelque part dans votre webroot.</li>
<li>Copiez’config.php.example’ dans’config.php’ et éditez selon votre goût. <br/>
<h1id="xoyizexyz---serveur-messagerie-complet-ldap">xoyize.xyz - Serveur Messagerie complet (LDAP)</h1>
<ul>
<li>Gestion des adresses mails.</li>
<li>Gestion de plusieurs domaines.</li>
<li>Gestion des mails</li>
<li>Traitement Spam.</li>
<li>Utilisation du référentiel utilisateur du serveur LDAP.</li>
<li>Filtrage Sieve (sur le serveur directement).</li>
</ul>
<p>Les briques qui vont constituer l’architecture</p>
<ul>
<li>Postfix : Le point central de l’architecture, il assure la réception des mails des serveurs smtps extérieurs, l’envoi de mails vers eux et la soumission de message depuis les clients connectés.</li>
<li>Dovecot :
<ul>
<li>Première fonction : range les mails reçus depuis Postfix via lmtp dans les bals physiques des utilisateurs. Peut les trier dans des sous-répertoires en fonction de règles Sieve.</li>
<li>Deuxième fonction : permet aux utilisateurs de consulter leur boites aux lettres en IMAP à l’aide du client de leur choix (ou d’un webmail). Ici, je ne gère pas le pop car c’est le mal (plus sérieusement, tellement d’avantages avec l’Imap que je ne vois pas l’utilité de proposer du pop.</li>
<li>Troisième fonction : fournit le support AUTH à Postfix (pour l’envoi de message).</li>
</ul>
</li>
<li>Rspamd : Autre changement par rapport à ce que j’utilisais jusque la (Spamassassin). Ce dernier s’assure donc de traiter le spam pour les mails venant de l’extérieur, et de la signature DKIM pour les mails sortants.</li>
<li>Le serveur Openldap</li>
</ul>
<p>Pas de traitement antivirus, c’est lourd en terme de ressource, à voir ?</p>
<h3id="explication-de-lorganisation-ldap">Explication de l’organisation LDAP</h3>
<p>Jusque la, je stocke mes comptes utilisateur. Ceci dit, il me manque des attributs, que je rajouterais via un schéma personnel.</p>
<p>Au niveau domaine, j’en ai deux : xoyize.fr, ouestline.net et je gère deux compte mails toto@xoyize.fr et tata@xoyize.fr. Toutes les autres adresses de xoyize et ouestline (par ex ccc@xoyize.fr, aaa@ouestline.net, bbb@ouestline.net, etc.. seront renvoyés soit vers toto@xoyize.fr soit vers tata@xoyize.fr</p>
<p>Pour la gestion domaines et alias, j’ai donc choisi de faire de la sorte :</p>
<p>Chaque domaine sera une OU dans une nouvelle OU créée pour l’occasion.</p>
<p>Et dans chaque OU, je crée des entrées correspondants aux alias, la aussi avec l’aide de schéma supplémentaire</p>
<p>Mes domaines auraient très bien pu être non pas des OU mais des entrées, au niveau de l’OU mail et les alias définies par des attributs soit dans ces entrées soit dans les entrées des users. Je vous le disais, on peut vraiment faire comme on veut.</p>
<h3id="mise-en-place">Mise en place</h3>
<h4id="le-schéma">Le Schéma</h4>
<p>On va créer un fichier <strong>schema.ldif</strong> :</p>
olcObjectClasses: ( 1.3.6.1.4.1.99999.2.1.20 NAME 'mailaccountxoyize' SUP TOP AUXILIARY MUST ( mailaccountquota $ mailaccountactif))
olcObjectClasses: ( 1.3.6.1.4.1.99999.2.1.40 NAME 'mailaliasxoyize' SUP TOP STRUCTURAL MUST ( cn $ mailaliasfrom $ mailaliasto $ mailaliasactif))
olcObjectClasses: ( 1.3.6.1.4.1.99999.2.1.60 NAME 'maildomainxoyize' SUP TOP AUXILIARY MUST ( maildomain $ maildomainactif))
</code></pre></div></div>
<p>Vous voyez trois séries de chiffres dans le fichier.<br/>
L’OID 1.3.6.1.4.1.99999.2.2.x correspond à la hiérarchie de mes attributs (la branche 1.3.6.1.4.1 est la branche dédiée aux OID privés : voir ici).<br/>
Le 99999 devrait être dans l’idéal remplacé par le PEN que vous pouvez obtenir sur cette page. Si vous ne destinez pas votre schéma a être public, ça n’a pas trop d’importance, mais attention à ne pas prendre un numéro déjà existant si un jour vous importez un schéma avec ce numéro, bref, vous voyez le topo. J’ai fais la demande, j’ai eu mon PEN en 72h je crois…<br/>
L’OID 1.3.6.1.4.1.99999.2.1.x est sur le même modèle mais définit un objet.<br/>
L’OID 1.3.6.1.4.1.1466.115.121.1.15 correspond à la définition d’une directory string (chaîne de caractère), je fais simple et prend ce type de donnée pour mes nouveau attributs.</p>
<p>Ce schéma est au final assez simple, je rajoute trois nouvelles classe d’objets : mailaccountxoyize, maildomainxoyize et mailaliasxoyize (qui à la particularité d’être structural, c’est à dire que ce pourra être une entrée sans ajout d’autre classe (par ex, inetogperson, etc…).<br/>
Chaque classe possède des attributs obligatoire (MUST).</p>
<p>L’attribut mailaliasto est le seule à ne pas avoir SINGLE-VALUE, en effet, un alias peut renvoyer vers plusieurs bals.</p>
<p>Voila qui termine la partie LDAP pour l’utilisation avec un serveur de messagerie.</p>
<h3id="postfix">Postfix</h3>
<h4id="reverse-dns">Reverse DNS</h4>
<p>Il est nécessaire que son reverse dns soit correctement configuré : si on demande l’adresse de mail.domaine1.fr et qu’on a XXX.XXX.XXX.XXX, il faut qu’en demandant le reverse de XXX.XXX.XX.XXX on obtienne mail.domaine1.fr</p>
<p>La commande installcert met également en place une tache cron pour le renouvellement automatique de votre certificat qui du coup, renouvelle, copie ou il faut et relance, parfait !</p>
<p>Les certificatts sous xoyize.xyz</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code> ls /etc/ssl/private/
<p>ajoute le domaine au mail locaux qui sont envoyés (si un mail local est envoyé depuis un service sur le serveur, genre cron, etc… il sera de la forme root@xoyize.xyz au lieu de root@mail).</p>
<p>Centralisant tous mes mails, éventuellement d’autres serveur, c’est une info dont j’ai besoin (on peut aussi réécrire l’expéditeur, etc..).</p>
<p>Le nom de votre serveur de mail. Peut être différent, mais dans mon cas, vu ma config Dns, de l’extérieur ou de l’interieur, ca reste le meme nom.
Ensuite, les destinations qu’il accepte. On ne liste ici aucun domaine qu’on gère, ceux ci sont déclarés dans les alias virtuels.</p>
<p>Pour la partie SSL/TLS/SALS on remarque deux groupes d’options : smtp_* et smtpd_*</p>
<p>Smtp concerne la patie client de postfix, c’est à dire celle qui envoie les mails aux autres serveurs SMTP (aussi appelés MX).
Smtpd concerne la partie serveur, celle qui recoit les mails, soit des clients, soit des autres MX.</p>
<p>smtp_tls_security_level = may</p>
<p>indique que le client SMTP de postfix, quand il se connecte à un autre MX, supporte le TLS.</p>
<p>smtpd_tls_security_level = may</p>
<p>indique que le serveur SMTP de Postfix, quand il reçoit une connexion d’un client (mx ou soumis), supporte le TLS.</p>
<p>On le laisse à may pour indiquer que c’est possible sans être obligatoire. On le surchargera dans le fichier master.cf</p>
<p>Ne pas confondre aussi <em>sasl</em> et <em>tls</em> ! <em>sasl</em> concerne l’authentification de nos utilisateusr (via Dovecot) et <em>tls</em> le chiffrement des communications.</p>
<p>smtpd_tls_auth_only = yes</p>
<p>indique que si l’authentification est utilisé, on doit forcement être en SSL (ou TLS, ca revient au meme.)</p>
<p>On va ensuite modifier le fichier <strong>/etc/postfix/master.cf</strong> au début</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>submission inet n - y - - smtpd
-o smtpd_tls_security_level=encrypt
</code></pre></div></div>
<p>On active submission, et on surchage (-o le parametre smtpd_tls_security_level à encrypt pour forcer le tls.</p>
<p>Un peu plus bas, on va activer le smtps :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>smtps inet n - y - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_tls_wrappermode=yes
</code></pre></div></div>
<p>Le reste ne change pas.</p>
<p>Pourquoi Postfix utilise deux fichiers de configuration ?</p>
<p>Le fichier main.cf définit les options générales de Postfix. Le fichier master.cf, lui sert à gérer les sous process de Postfix et permet de modifier certains paramètres du fichier main.cf en les surchargeant (option -o).</p>
<h3id="postfix---ldap">Postfix - Ldap</h3>
<p>On va créer nos fichiers chargé de faire la liaison avec le serveur ldap et les ranger :</p>
<p>Postfix est opérationnel. Vous voyez, ce n’est pas si terrible ! On ne fait qu’effleurer la configuration, la documentation de Postfix est très complète et on peut configurer plein de scénarios…</p>
<p>Maintenant pour le tester, comme nous n’avons pas encore Dovecot derriere, on va se contenter de juste tester la communication d’un MX vers le nôtre :</p>
<p>Le site https://www.checktls.com/TestReceiver permet de faire cette vérification, et l’on voit de suite si le TLS est bon. On peut aussi classiquement en telnet, mais c’est… long…</p>
<p>Le site https://mxtoolbox.com/ est très pratique également.</p>
<p>Ha oui, au passage, le fichier clé pour debug, c’est bien évidement le fidèle :</p>
<p>/var/log/mail.log</p>
<h2id="dovecot">Dovecot</h2>
<h3id="dovecot---la-base">Dovecot - La base</h3>
<h4id="utilisateur-vmail">Utilisateur Vmail</h4>
<p>Nous allons créer l’utilisateur virtuel vmail ainsi que le répertoire qui stockera les mails :</p>
# %$ - Delivery status message (e.g. "saved to INBOX")
# %m - Message-ID
# %s - Subject
# %f - From address
# %p - Physical size
# %w - Virtual size
#deliver_log_format = msgid=%m: %$
EOF
</code></pre></div></div>
<p>Ici, auth_verbose et auth_debug sont bien pratiques en cas de soucis avec les connexions au LDAP, mail_debug pour les filtres Sieves (et autres, quota, etc…).</p>
<p>Dans ce fichier, on déclare nos services : imap-login, imap, lmtp (utilisé pour le transfert de mails entre Postfix et Dovecot) et le service auth, qui service à Postfix pour authentifier les utilisateurs en SMTPS.</p>
<p>La, on définit l’architecture de base de nos boites aux lettres. Création des répertoires spéciaux et auto souscription pour que l’utilisateur les voit de suite.</p>
<h3id="fichiers-de-mapping-ldap">Fichiers de mapping Ldap</h3>
<p>A – Selon la Doc de Dovecot</p>
<p>Avant de faire nos fichiers pour le Ldap, on va regarder à quoi devrait ressembler un dovecot-ldap.conf.ext qu’on peut rencontrer sur le grand internet, un exemple souvent cité (bon, les filtres sont les miens, mais c’est l’idée) :</p>
<p>C’est la que le <codeclass="language-plaintext highlighter-rouge">auth_debug</code> et <codeclass="language-plaintext highlighter-rouge">mail_debug</code> sont utiles</p>
<p>B – Passdb et Userdb</p>
<p>Dovecot utilise deux bases : passdb et userdb, déclarées dans cond.f/10-auth.conf ou j’utilise une petite astuce, le prefetch, pour éviter les doubles requêtes…</p>
<ul>
<li>Lorsqu’un utilisateur se connecte en IMAP, passdb est utilisé pour vérifier l’utilisateur (login et mdp), puis userdb est appelé pour connaitre des infos supplémentaires sur l’user (d’où le prefetch).</li>
<li>Lorsqu’un mail arrive de Postfix à Dovecot via le protocole LMTP, c’est userdb qui est appelé pour connaitre l’utilisateur à qui remettre le mail d’où le second userdb car le premier, prefetch, ne contient rien pour le coup.</li>
</ul>
<p>Il faut aussi savoir que Dovecot utilise des variables. Celles qui nous intéressent sont :</p>
<ul>
<li>%u qui est le nom utilisateur complet fourni. Par exemple ym@xoyize.xyz via un appel en Imtp (mail entrant) ou ym via l’Imap (client qui se connecte)</li>
<li>%n qui correspond à la partie utilisateur, ici : ym</li>
<li>%d qui correspond au domaine, ici : xoyize.xyz</li>
<p>indique que le champ mail de mon ldap correspond à l’utilisateur, du coup j’ai la bonne association.</p>
<p>C – Bind Ldap</p>
<p>Ensuite, au niveau du bind avec Ldap (la connexion avec Ldap), celui ci peut se faire de deux façons.</p>
<p>1 – auth_bind = yes</p>
<p>Cela permet de faire en sorte que le test du mot de passe se fasse directement avec le compte de l’utilisateur. Dovecot dans ce cas n’a pas besoin de lire le pass avec le compte viewer.</p>
<p>En contre partie, c’est plus lent, Dovecot attendant que la connexion avec le Ldap soit terminée avant de passer à la suivante.</p>
<p>2 – auth_bind = no</p>
<p>La, il y a besoin que le compte viewer puisse lire le mot de passe (d’où les acls mises en place dans la partie LDAP). Ayant de toute façon besoin de ce compte pour d’autres applications, ça ne me dérange pas.</p>
<p>De plus, c’est asynchrone, Dovecot peut lancer plusieurs requêtes concomitantes sans attendre apres.</p>
<p>Bref, on part sur le second choix.</p>
<p>D – Paf</p>
<p>Cependant, cette config me pose encore un problème… Lorsque l’on se connecte en IMAP on se présente donc avec un simple ym par contre, lors du LMTP, le %u présenté par Postfix est le mail complet, ym@xoyize.xyz et la, bah ça foire au niveau du filtre ldap, qui est pour mémoire :</p>
<td>Ha, les filtres LDAP et leur notation préfixée. Si vous avez eu une calculette Sharp dans les 90’s, vous devez connaître (et être vieux 😉 ). Bon, elles utilisaient la notaion polonaise inverse où l’opérateur est à la fin, mais c’est la même idée… Si vous avez fait de l’algèbre booléenne ou bien joué avec les AND, OR, XOR, et NAND (du genre, comment faire un OR avec que des NAND, tables de vérités, etc..), et bien le + (ou) est remplacé par</td>
<td>et le . (et) par &.</td>
</tr>
</tbody>
</table>
<p>On peut résumer :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>(&(Bloc1)(Bloc2)(Bloc3)) -> On veut Bloc1 ET Bloc2 ET Bloc3
Bloc1=(|(A)(B)) -> A OU B
</code></pre></div></div>
<p>C’est beau hein ! Bah c’est balo car on en va pas l’utiliser. En effet, cela amène un effet de bord : je peux désormais me connecter à ma bal avec comme login mon mail….
Après, on aime ou on n’aime pas. Perso, je ne préfère pas laisser cette possibilité, pour éviter les vilains qui tenteraient de se connecter en connaissant déjà le login…</p>
<p>Apres tout, j’aurais pu en rester la et me dire tant pis, mais au final c’était ne pas vraiment comprendre Dovecot…</p>
<p>E – Solution</p>
<p>Il faut faire en sorte que les appels userdb et passdb soient distincts…</p>
<p>Pour la configuration, on aura donc deux fichiers :</p>
<p>La, on demande aussi au passage un attribut quota avec userdb <codeclass="language-plaintext highlighter-rouge">userdb_quota_rule=*:bytes=%$</code> et qui sera utilisé dans le prefetch pour éviter de refaire une requête LDAP.</p>
<p>Je serais même tenté de dire que la première fois, c’est mieux de laisser Dovecot le faire, en regardant les logs et avec l’option mail_debug = yes on voit très rapidement où se trouve le problème s’il y en a un (et généralement, ça chouine pour des histoires de permissions). Pour les filtres utilisateurs, c’est la même tambouille, Dovecot les compilant au moment ou il les charge, s’il n’existent pas ou sont obsolètes.</p>
<p>Pour modifier les filtres d’un utilisateur, on peut utiliser un webmail préalablement configuré. Pour le moment, je ne couvre pas cette partie (ce sera pour plus tard), donc pour le moment, on va plutôt passer par un client tel que Thunderbird.</p>
<p>Par défaut, Thunderbird ne les gère pas, mais il suffit de rajouter ce module complémentaire.
Ensuite menu Outils/Paramètres Sieve et activez la gestion de Sieve. Les paramètres sont identiques à l’IMAP, mais sur le port 4190.</p>
<p>Et ensuite dans le menu Outils/Filtres Sieve (M). Faites nouveau pour créer un nouveau fichier de règles.</p>
if header :contains "subject" "Postfix SMTP server" {
fileinto "Serveur";
}
</code></pre></div></div>
<p>En cas de fautes, le plugin vous le signale. Il ne reste qu’a enregistrer. A noter : Sieve permet d’avoir plusieurs fichiers de filtrage, mais un seul peut être actif à la fois.</p>
<p>Bien sur, Sieve permet de faire beaucoup de choses, avec gestion de conditions, variables, etc… Ce sera l’occasion de faire un article complet (ou presque) sur Sieve un peu plus tard.</p>
<h4id="tests-1">Tests</h4>
<p>Comme je l’ai dis, l’option <codeclass="language-plaintext highlighter-rouge">mail_debug = yes</code> permet de voir de suite dans le fichier de log /var/log/mail.log c e qui ne va pas.</p>
<h3id="quota">Quota</h3>
<h4id="configuration-1">Configuration</h4>
<p>Pour rajouter la gestion du quota, il suffit de quelques manipulations. Pour rappel, si le champ dans le ldap est égal à zéro, cela veut dire pas de quota. Notez également que le champ est exprimé en bytes.</p>
<p>Dans le fichier /etc/dovecot/conf.d/10-mail.conf on va modifier :</p>
<p>L’œil attentif remarquera que l’on fait appel à dovecot-lda pour ce mail. J’ai tenté avec le lmtp, où pourtant -d a la même utilité, mais je me mange une erreur. Tant pis, au final, lda est toujours dispo, et n’est invoqué qu’au besoin. Autant dire que ça ne va pas beaucoup tourner</p>
<p>On édite le fichier /etc/dovecot/conf.d/15-lda.conf pour tout remplacer par :</p>
<p>Et pour tester en conditions réelles, attention, il faut savoir que le mail n’est envoyé qu’une seule fois, au moment où le quota est dépassé.</p>
<p>Par exemple, si vous activez le quota avec une bal deja hors quota vous n’aurez jamais le mail. Du coup, pour tester, c’est pas évident… faut jouer avec une toute petite bal. Mais si les deux commandes au préalable fonctionnent sans problemes, ca doit marcher en production.</p>
<p>Pour voir le quota avec Thunderbird, je conseille <ahref="https://addons.thunderbird.net/fr/thunderbird/addon/display-quota/">Display Quota</a>.</p>
<h4id="conclusion">Conclusion</h4>
<p>Voila pour cette troisième partie où nous avons fait connaissance avec Dovecot. Je pourrais vous parler en profondeur de la commande doveadm qui permet de faire pas mal de choses mais ce sera pour un tuto annexe… En attendant, rien ne vous empêche de vous documenter.</p>
<p>Vous voulez la bonne nouvelle ? Notre serveur de messagerie est opérationnel.</p>
<p>Pour tester, rien de tel qu’un client lourd. Thunderbird pour Windows, Evolution ou autres pour Linux.</p>
<p>Vous devez pouvoir recevoir et envoyer des mails.</p>
<p>Attention cependant, aucune protection contre le spam n’est encore en place à ce niveau. De la meme façon, vos mails envoyés vers certains domaines (gmail, hotmail) risquent fort de se retrouver classés comme spams (DKIM, SPF et DMARC pas encore en place).</p>
<p>Et oui, j’ai dis opérationnel, pas terminé ! Mais ne ne perdez pas espoir, on a fait le plus dur.</p>
<h2id="optimisation-de-postfix">Optimisation de Postfix</h2>
<h3id="sécurisation-smtps-et-submission">Sécurisation SMTPS et Submission</h3>
<p>La partie consacrée à Postfix laisse dans notre configuration une potentielle future faille.</p>
<p>Vous le savez, un SMTP externe communiquera avec le votre via le port 25, mais imaginons qu’un instant, un serveur se connecte à vos ports 465 ou bien 587…
Et bien, il ne sera pas embêté. Au final, pour le moment, ce n’est pas bien méchant car il suivra les restrictions qu’il aurait rencontré via le port 25, mais si nous mettons en place des restrictions différentes selon les services (et c’est ce que nous ferons plus tard), et bien, on risque d’avoir des surprises.</p>
<p>Autant y remédier de suite en bloquant la possibilité à un serveur SMTP de se connecter la ou il ne doit pas.</p>
<p>On édite le fichier /etc/postfix/master.cf :</p>
<p>Pour ces deux services, la directive <codeclass="language-plaintext highlighter-rouge">smtpd_client_restriction</code> du <strong>main.cf</strong> est remplacée :<br/>
on permet les utilisateurs connectés et on rejette le reste.</p>
<h3id="antiforge">Antiforge</h3>
<h4id="explication">Explication</h4>
<p>Derrière ce terme, se cache quelque de tout simple : le fait de pouvoir modifier (forger) sans vergogne l’adresse de l’expéditeur. Je m’explique :</p>
<ul>
<li>Depuis votre logiciel de messagerie, si vous modifiez l’adresse d’expéditeur par nimportequoi@xoyize.xyz, le mail est expédié sans aucun soucis.</li>
<li>De la même façon, un MX distant peut tout à fait présenter un mail auprès de notre serveur avec un FROM TO : ym@xoyize.xyz , sans que cela ne gène le moins du monde.</li>
</ul>
<p>On va donc rajouter une restriction au moment de la vérification du sender afin de limiter tout cela.</p>
<p>On édite le fichier <strong>/etc/postfix/main.cf</strong> et on ajoute dans la directive <codeclass="language-plaintext highlighter-rouge">smtpd_sender_resctriction</code> :</p>
<p>Cette nouvelle directive s’appuie sur une <codeclass="language-plaintext highlighter-rouge">sender_login_maps</code>, qu’on va déclarer plus bas :</p>
Imaginons que dans notre schéma LDAP, nous ayons un attribut mailaliassend qui stipule si un alias a le droit ou non d’envoyer des mails. Après tout, pourquoi pas…</p>
<p>Notre fichier /etc/postfix/ldap/virtual_senders.cf pourrait ressembler à cela :</p>
<p>Dans sa grande générosité au niveau de ses possibilités, Postfix permet également d’effectuer des vérifications d’accès à l’aide de quatre contrôles :</p>
<ul>
<li>check_client_access</li>
<li>check_helo_access</li>
<li>check_sender_access</li>
<li>check_recipient_access</li>
</ul>
<p>Dans le cadre du renforcement de notre serveur Postfix, seul check_sender_access sera vraiment obligatoire, les autres, c’est au cas pas cas.</p>
<p>Ces vérification s’appuient sur des données formatées de la sorte :</p>
<p>Pour filtrer des lourds (spammeurs, bots, etc…), ce n’est pas forcement la meilleure solution. D’une, il faut que la la liste d’accès soit maintenue à jour, et c’est alors un travail quotidien, ou presque…</p>
<p>Seconde « limitation », même en cas de Reject, la session SMTP ira jusqu’au RCPT ou bien sur, elle sera terminée, mais on a gaspillé de la ressource à aller si loin.</p>
<p>On peut demander à Postfix d’arrêter la communication dès qu’une restriction s’applique (en mettant l’option smtpd_delay_reject = no) mais pour trouver un éventuel soucis par la suite, ce peut être gênant. Autre problématique, certains clients gèrent mal une connexion coupée de la sorte…</p>
<p>Je conseille donc de laisser comme c’est par défaut.</p>
<p>Et donc pour bloquer des IPS spécifiques, je passe soit par mon firewall, soit par Postscreen (qu’on verra plus tard).</p>
<h4id="check_helo_access">check_helo_access</h4>
<p>Ici est effectué un contrôle sur le helo. Comme pour le client, c’est vite compliqué de maintenir quelque chose à jour.</p>
<p>Cependant, on peut quand même effectuer un petit contrôle de routine pour éviter le helo qui serait le notre, ça ne mange pas de pain…</p>
<p>Pour bloquer les mails à destination de cette adresse. L’intérêt la aussi, dans notre cas de figure, est faible, mais ça existe et ça peut servir.</p>
<p>Ici, on va effectuer un contrôle au niveau de l’expéditeur et on va revenir sur l’antiforge dont je parlais avant pour s’intéresser à un cas que je n’ai pas traité :</p>
<p>Imaginons un serveur SMTP qui nous envoie un mail avec comme FROM TO un mail du genre userbidon@xoyize.xyz, la bal n’appartenant à personne, le <codeclass="language-plaintext highlighter-rouge">reject_sender_login_mismatch</code> qu’on a vu plus haut ne bloquera rien, le mail passera.</p>
<p>On va donc y remédier. L’idée étant d’autoriser en FROM TO nos mails qui existent et de rejeter le reste.</p>
<p>Dans le bloc smtpd_sender_resctrictions, nos usagers sont déjà autorisés via permit_sasl_authenticated, on va donc ajouter juste après la restriction pour nos domaines.</p>
<p>On aurait alors besoin d’un fichier ressemblant à ça :</p>
<p>L’ordre est important. Si le check_sender_access est positionné avant le permit_sasl_authenticated, nos propres utilisateurs ne pourraient pas envoyer de mails.</p>
<p>A partir de maintenant, on va pouvoir inspecter, via des REGEX, ce qu’il y a dans les mails.</p>
<p>La syntaxe est la suivante :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>/^Subject:.*viagra*/ REJECT Pas besoin, merci
/^From: *ym*/ REJECT On connait la blague
</code></pre></div></div>
<p>De mon avis et expérience, pour filtrer le spam, ce n’est plus vraiment la meilleure solution sauf cas particulier. Compliqué de maintenir un truc à jour, risque d’un regex un peu foireux qui pourrait être trop restrictif…</p>
<p>Pour information, il est possible de tester vos regex de la sorte :</p>
<p>Ici, un header perso X-xoyize: WARN est ajouté si le mail contient un fichier avec les extensions bat, exe, com, etc… Celui ci pourra me servir à effectuer un filtre avec Sieve.</p>
<p>Au niveau des actions, on retrouve peu ou prou ce qu’on avait pour les contrôles d’accès. On peut donc aussi utiliser REJECT pour le rejeter, REDIRECT xxx@xoyize.xyz , etc…</p>
<p>Voila pour les contrôles en entrée.</p>
<h4id="supprimer-les-informations-sensibles">Supprimer les informations sensibles</h4>
<p>L’autre utilité est de pouvoir masquer certaines informations de vos mails sortants, tel que votre IP d’envoi, votre client mail… Par défaut, les headers ajoutés par votre client de messagerie sont un peu trop causant…</p>
<p>Si on regarde ces fameux headers d’un mail qui partirait de chez vous vers un destinataire externe, le premier Received ressemblerait à cela :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>Received: from [monip] (monreverse[monip])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by mail.xoyize.xyz (Postfix) with ESMTPSA id 3AB4D22938
for <destinataire@destination.com>; Mon, 21 Jul 1969 02:56:20 +0000 (UTC)
</code></pre></div></div>
<p>Au passage, pour lire les headers d’un mail, il faut commencer par le bas. Le premier Received que l’on voit en haut est en fait le dernier SMTP rencontré, celui du destinataire.</p>
<p>Et donc notre destinataire, s’il est un peu curieux, peut connaitre notre IP. Puis s’il descend un peu, il en apprendra davantage sur votre OS, etc…</p>
<p>Hum, ce n’est pas terrible…</p>
<p>Allez, nettoyons tout cela !</p>
<p>Dans un fichier <strong>/etc/postfix/check/header_checks_out</strong> :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>/^\s*Received: from \S+ \(\S+ \[\S+\]\)(.*)/ REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1])$1
/^X-Originating-IP:/ IGNORE
/^X-Mailer:/ IGNORE
/^Mime-Version:/ IGNORE
/^User-Agent:/ IGNORE
</code></pre></div></div>
<p>Au passage, on rencontre souvent sur internet ce regex :</p>
<p>En lieu et place de celui que je vous ai indiqué. Celui ci est un peu trop violent à mon gout, vu qu’il supprime complétement le Received from vous concernant. Il peut toujours être utile d’indiquer que vous étiez en tls, le serveur qui a reçu le mail, etc… Je préfère donc juste masquer l’ip d’origine.</p>
<h4id="oui-mais">Oui mais…</h4>
<p>Si on indique ces checks dans le main.cf avec :</p>
<p>Ils vont se faire sur les mails qui entrent et qui sortent. Et on ne veut pas effacer les headers des mails qui nous arrivent… ni ajouter un éventuel header au mail que l’on envoie.</p>
<p>Que faire…</p>
<p>La solution élégante est de faire appel au process cleanup et d’en faire deux « sous process ». Chacun en charge d’un traitement, et affecté comme il faut.</p>
<p>Pour se faire, c’est assez simple :</p>
<p>On édite le fichier <strong>/etc/postfix/master.cf</strong> pour y ajouter pour chaque service un nouveau service cleanup :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>smtp pass - - y - - smtpd
<p>Précisez bien <strong>header_checks</strong> et <strong>mime_header_checks</strong> : les headers pouvant être dans le format MIME ou ASCII, il est important de bien traiter les deux cas.</p>
<p>Je vous invite bien évidement à consulter la <ahref="http://www.postfix.org/documentation.html">doc officielle</a> qui vous permettra de trouver réponses à vos cas particuliers.</p>
<h2id="policyd-spf">Policyd SPF</h2>
<p>SPF (Sender Policy Framework) est un mécanisme simple qui permet de savoir si un SMTP à l’origine d’un mail est bien légitime .</p>
<p>Cela s’appuie sur un enregistrement TXT dans le DNS qui ressemble à ça :</p>
<p>“v=spf1 ip4:ip.legitime mx -all”</p>
<p>Cet enregistrement stipule quel MX est autorisé à envoyer depuis le domaine.</p>
<p>Ici, on va mettre en place la vérification pour les mails entrants, la création dans notre DNS de notre propre SPF se fera dans la partie VII.</p>
<p>On commence en installant le module SPF python (il existe aussi une version perl, mais celle en python est mieux maintenue et nécessite moins de dépendances, puis le python, c’est la vie !)</p>
<p>Les mails qui ne respectent pas les SPF seront rejetés. Par contre, s’il n’y a pas de SPF définis, on accepte (les refuser ici est une mauvaise idée, nombre de domaines légitimes n’ont pas de SPF en place…)</p>
<p>Ensuite, dans le fichier <strong>/etc/postfix/master.cf</strong> on va ajouter en bas :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>policyd-spf unix - n n - - spawn
user=nobody argv=/usr/bin/policyd-spf
</code></pre></div></div>
<p>Et dans le <strong>/etc/postfix/main.cf</strong>, on ajoute tout d’abord une ligne :</p>
<p>Voila pour le contrôle SPF qui va permettre d’écrémer un peu plus.</p>
<h2id="postcreen-a-voir">Postcreen (A voir)</h2>
<p>On arrive à la chose la plus efficace pour lutter contre le spam bête et méchant. S’il ne devait en rester qu’un, ce serait lui je pense. Pourtant il ne réinvente rien et utilise des principes déjà connus, mais il le fait bien et simplement.</p>
<p>Il est le bouclier contre les zombies/bots, etc… que je résume en « les lourds »…</p>
<p>Il est… Postscreen !</p>
<h3id="activation">Activation</h3>
<p>Postscreen étant intégré dans Postfix, rien à installer, il suffit de l’activer.</p>
<p>Dans le fichier /etc/postfix/master.cf, commentez la ligne :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>smtp inet n - y - - smtpd
</code></pre></div></div>
<p>et décommentez juste en dessous :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>smtp inet n - y - 1 postscreen
smtpd pass - - y - - smtpd
dnsblog unix - - y - 0 dnsblog
tlsproxy unix - - y - 0 tlsproxy
</code></pre></div></div>
<p>Le reste de la configuration se passera dans le fichier /etc/postfix/main.cf</p>
<h3id="configuration-2">Configuration</h3>
<p>Postcreen peut faire deux types de contrôles :</p>
<ul>
<li>des contrôles simples</li>
<li>des contrôles profonds</li>
</ul>
<p>Les contrôles simples se fond avant de passer la main à Postfix. Si tout est Ok, le mail suit son chemin.</p>
<p>Au contraire, les contrôles profonds prennent la main sur l’ensemble du dialogue et introduisent de par ce fait, un greylisting. J’y reviens plus bas.</p>
<p>Pour chaque contrôle, on peut définir une action :</p>
<ul>
<li>ignore : on ne fait rien. Peut servir en cas de debug.</li>
<li>enforced : le blocage est actif, mais la coupure se fera au moment du RCPT TO: avec une réponse 550 5.3.2 Service currently unavailable</li>
<li>drop : efficace, on coupe court avec une réponse 521 5.3.2 Service currently unavailable</li>
</ul>
<p>Un serveur qui sera accepté sera mis en liste blanche pour les prochaines fois afin de ne pas mobiliser de la ressource pour rien.</p>
<h4id="contrôles-simples">Contrôles simples</h4>
<p>Simples ne veut pas dire inefficaces. Personnellement, je n’utilise qu’eux, n’aimant pas le principe du greylisting.</p>
<p>a – Access list</p>
<p>Simplissime, ce contrôle va permettre de bloquer des IPs et contrairement au blocage dans Postfix, ici avec l’action sur drop, c’est immédiat. Ciao !</p>
<p>Pour l’activer, ajoutez ces lignes dans le fichier /etc/postfix/main.cf :</p>
<p>Ce contrôle joue sur une subtilité du protocole SMTP. En effet, si le serveur répond avec « 250-On attend un pneu…« , le tiret après le 250 indique qu’il y a plusieurs lignes.</p>
<p>Et il attend le temps indiqué avant d’envoyer le « 250 mail.xoyize.xyz ESMTP mail (Debian/GNU)« .</p>
<p>Du coup, un zombie trop rapide se fera avoir, et hop, dehors !</p>
<p>Pour l’activer, ajoutez ces lignes dans le fichier /etc/postfix/main.cf :</p>
<p>Le temps d’attente sert également à Postscreen pour consulter les Dnsbl qu’on voit juste en dessous.</p>
<p>c – Dnsbl</p>
<p>Ici, on va interroger des RBL.</p>
<p>Le principe est simple. On passe par une interrogation DNS pour savoir si un MX distant est légitime ou non.</p>
<p>Une réponse du genre 127.0.0.X indique qu’il ne faut pas accepter le mail (le type de réponse dépend de la liste dans la quelle se trouve l’IP). On peut éventuellement ne prendre que certaines réponses.</p>
<p>Pour l’activer, ajoutez ces lignes dans le fichier /etc/postfix/main.cf :</p>
<p>J’utilise trois listes. En mettre de trop n’est pas forcement une bonne idée, temps d’interrogation plus long, trouver comment bien pondérer chacune…</p>
<p>Sachez cependant qu’il en existe plein. Vous en trouverez ici par exemple : https://www.dnsbl.info/dnsbl-list.php</p>
<p>Pour faire une interrogation à la main, si votre IP est AAA.BBB.CCC.DDD :</p>
<p>On passe par un PTR record, ce qui fait qu’on peut connaitre « l’état » d’une IP en interrogeant n’importe quel DNS, ce dernier ira faire la requête au bon endroit.</p>
<p>Si pas de retour, l’IP n’est pas blacklisté, si retour, IP blacklisté donc.</p>
<h4id="contrôle-profond">Contrôle profond</h4>
<p>Très efficace contre les « lourds » qui ne respecte pas le protocole SMTP, ces vérifications ont cependant un inconvénient comme je l’expliquais :</p>
<p>Ils introduisent un Greylisting. Pour effectuer ces vérifications, Postscreen prend en charge tout la communication SMTP, mais le bougre à la fin n’est pas capable de repasser la main à Postfix.</p>
<p>Postscreen règle le problème très « simplement » en répondant à la fin : 450 4.3.2 Service currently unavailable et en mettant au passage le serveur en liste blanche.</p>
<p>Le voila le Greylisting … Un serveur SMTP bien configuré se doit de retenter l’envoi et comme il sera reconnu par Postscreen, ce dernier passera la main à Postfix.</p>
<p>Ça, c’est la théorie… Les trucs configurés avec les pieds, on en voit partout et il est tout a fait possible que le SMTP distant, bien que légitime, ne retente jamais. C’est pourquoi je n’aime pas le principe du Greylisting.</p>
<p>A vous de voir comme vous le sentez …</p>
<p>a – Pipelining</p>
<p>Postscreen ne gérant pas le pipelining (du full duplex en quelque sorte), il l’indique durant la communication. Un client « correct » le prendra alors en compte. Un « lourd », certainement que non, et bam !</p>
<p>Sixième partie de ma série d’articles sur la mise en place d’un serveur mail complet. Courage, on arrive au bout ! Nous allons installer et configurer le digne remplaçant du vénérable Spamassassin, j’ai nommé Rspamd.</p>
<h3id="installation-1">Installation</h3>
<p>Le paquet Rspamd disponible dans les dépôts de Debian n’étant plus maintenu, on va passer par les dépôts de Rspamd</p>
Controller password is not set, do you want to set one?[Y/n]: -> Yes (et vous le renseignez)
Do you wish to set Redis servers?[Y/n]: -> Yes
Input read only servers separated by <codeclass="language-plaintext highlighter-rouge">,</code> [default: localhost]: (si server Redis sur un autre serveur, vous indiquez son ip.)
Input write only servers separated by <codeclass="language-plaintext highlighter-rouge">,</code> [default: localhost]: (idem)
Do you have any password set for your Redis?[y/N]: si y’a un pass, vous l’indiquez
Do you have any specific database for your Redis?[y/N]: s’il faut spécifier une base (dans le cas d’un redis central), vous la spécifiez aussi
Do you want to setup dkim signing feature?[y/N]: -> No (on le fera après)
Expire time for new tokens [100d]: on laisse par défaut.
Reset previous data?[y/N]: -> No, vu qu’il n’y en a pas
Do you wish to convert them to Redis?[Y/n]: -> Yes</p>
<p>Au niveau de la configuration, tout se passe dans /etc/rspamd/, cependant, modifier ces fichiers n’est pas une bonne idée car comme indiqué dedans, ils se retrouveraient écrasés en cas d’update. On va donc utiliser le répertoire <strong>/etc/rspamd/local.d</strong> pour y indiquer nos modifications.</p>
<p>1 – classifier-bayes.conf</p>
<p>Ce fichier est créé par l’assistant, il suffit de rajouter la première ligne</p>
<p>Fichier également créé par l’assistant. Ici, on rajoute les deux lignes pour les sockets. Le socket sur le port 11334 sera pour l’interface Web (c’est pour cela qu’on le bind sur l’ip interne de la machine et non sur localhost). Le second socket servira pour l’apprentissage des spams.</p>
<p>A vous de bien régler ces paramètres. Ici, le reject est volontairement haut, dans un but de test et pour pouvoir le baisser au fur et à mesure.</p>
<p>4 – milter_headers.conf</p>
<p>Ce fichier est à créer. Il indique d’ajouter des entêtes dans les mails. Grace à eux, vous pourrez voir directement dans votre logiciel ce qui a provoqué ou non le marquage en spam. Mettez simplement :</p>
<p>Et voila pour la configuration de Rspamd. Il existe d’autres modules, mais nous en parlerons dans un futur article ou nous approfondirons le sujet sur Rspamd.</p>
<h3id="liaison-avec-postfix">Liaison avec Postfix</h3>
<p>Pour dire à Postfix de passer le mail à Rspamd, c’est le protocole milter que l’on va utiliser en indiquant en bas de notre fichier <strong>/etc/postfix/main.cf</strong> :</p>
<p>Pour l’utilisation de Rspamd au quotidien, pas grand chose à faire. C’est automatique, même pour les mises à jour. Cependant, si vous avez déjà un corpus de spam et de ham à lui apprendre, ce n’est pas une mauvaise chose de commencer par la, le filtre bayésien ne fonctionnant pas à moins de 200 mails appris par catégorie. Pour se faire, j’ai toujours deux dossiers récents de spams et de hams que je garde sous le coude. Je les déplace dans ma bal dans deux répertoires. Puis pour le spam :</p>
<p>Pour regarder ensuite les statistiques et voir à combien on en est :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>rspamc -h /var/run/rspamd/rspamd.sock stat
</code></pre></div></div>
<p>Pour un bon apprentissage, il faut lui apprendre des spams certes, mais également des hams, c’est important.</p>
<h3id="apprentissage-par-déplacement">Apprentissage par déplacement.</h3>
<p>Couplé avec Dovecot, Rspamd nous propose de pouvoir apprendre également en fonction des actions des utilisateurs. Si un mail est déplacé vers le répertoire spam, il sera appris comme tel et au contraire, s’il est sorti du répertoire Spam vers autre chose que la corbeille, il sera appris comme Ham. Dans le fichier <strong>/etc/dovecot/conf.d/90-sieve-extprograms.conf</strong>, mettez cela :</p>
<p>Quand un mail sera déplacé dans le répertoire Junk (Spam), le filtre report-spam.sieve sera appelé. Quand un mail sera déplacé depuis le répertoire Junk vers un autre répertoire (autre que la Corbeille), le filtre report-ham.sieve sera appelé. On va créer les filtre sieves. On créer un répertoire :</p>
<h3id="signature-dun-domaine">Signature d’un domaine</h3>
<p>Pour signer un nouveau domaine :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>rspamadm dkim_keygen -b 2048 -s dkim -d xoyize.xyz -k /var/lib/rspamd/dkim/dkim.xoyize.xyz.key | tee -a /var/lib/rspamd/dkim/dkim.xoyize.xyz.pub
</code></pre></div></div>
<ul>
<li>-b indique que l’on veut une clé de 2048 bits.</li>
<li>-s est le sélecteur.</li>
<li>-d indique le domaine.</li>
<li>-k pour dire ou l’on veut stocker la clé privée.</li>
<li>et pour terminer, on enregistre la clé publique, qui par défaut est simplement affichée, dans un fichier.</li>
</ul>
<p>Gardez la clé publique sous le coude, on la rajoutera dans le DNS.</p>
<p>Pour info, il est tout a fait possible d’avoir des sélecteurs différents, soit en fonction des domaines, soit pour versionner, etc… Dans ce cas, il faudrait renseigner le fichier /etc/rspamd/local.d/dkim_signing.conf de la sorte :</p>
<p>Rspamd propose une interface Web. Avant de la tester, je pensais que c’était un gadget, mais après avoir vu la chose, force est de constater qu’elle est plutôt bien fichue et permet de voir l’historique des messages, ce qui a provoqué ou non leur tag, rejet… On peut aussi y modifier les valeurs de metrics, les symboles (ce qui sert à détecter un spam par rapport à un critère donné). Bref, très pratique, je vous conseille de vous en servir. C’est déjà en écoute sur le port 11334, mais on ne va pas faire le goret et ouvrir cela sur le routeur. Servez vous d’un reverse proxy (Nginx est juste parfait) et indiquez dans la configuration de votre serveur.</p>
Voila, Rspamd est installé et opérationnel. La configuration reste simple, mais comme déjà dit, il existe d’autres modules que l’on peut utiliser. Ce sera pour un autre article, hors de la série sur le serveur de messagerie. La configuration présentée ici est bien suffisante dans un premier temps. En attendant, si vous voulez en savoir plus, la documentation officielle est ici : https://rspamd.com/doc/ On va passer à la finalisation de notre architecture mail avec, dans la partie VII, la mise en place des enregistrements SPF, DKIM et DMARC dans notre DNS.</p>
<h2id="dkim-spf-et-dmarc">DKIM, SPF et DMARC</h2>
<p>Dans cette avant dernière partie de ma série d’articles sur la mise en place d’un serveur mail, (la dernière sera la conclusion), nous allons mettre le coup final à notre configuration en mettant à jour nos enregistrements DNS.</p>
<p>Dans l’idéal, vous gérez vous même votre DNS, sinon, faites les modifications indiquées dans l’interface de votre registar.</p>
<p>Ces trois enregistrements s’appuient sur de simples champss TXT, afin que tous les resolvers les comprennent.</p>
<p>Il fut un temps ou on trouvait un champ SPF mais celui ci a été abandonné car pas vraiment de RFC pour cela. Il est conseillé maintenant de ne faire qu’un enregistrement TXT.</p>
<p>Bref, c’est tout simple, mais c’est vital, du moins, pour votre système de messagerie !</p>
<h3id="spf">SPF</h3>
<p>Cet enregistrement va stipuler une ou plusieurs IP(s) que l’ont autorise à envoyer des mails en notre nom.</p>
<p>Dans votre fichier de zone, indiquez :</p>
<p>xoyize.xyz. IN TXT “v=spf1 a mx ip4:78.235.240.223 ip6:2a01:e34:eebf:df3::1 -all”</p>
<p>On indique d’accepter les mails venant de notre IP et de refuser strictement les autres.</p>
<h3id="dkim">DKIM</h3>
<p>Cet enregistrement indique la clé publique correspondant à la clé privée utilisée par Rspamd pour signer les mails.</p>
<p>Un serveur distant pourra alors vérifier l’authenticité du mail en vérifiant si la clé privée utilisée pour la signature correspond à la clé publique publiée dans le DNS.</p>
<p>Reprenez la clé publique que vous aviez gardé sous le coude dans la partie VI :</p>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>dkim._domainkey IN TXT ( "v=DKIM1;k=rsa;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwCY7hcaoWyU0i7ydFiJFjnOG+Hk8UWMA+7y+RTL1BicoHm5KLwNhqO72VHW5wirk0WqEoTcNjnAIhvI1Ur07VfWh/CdACavzt2+DGKB3eiXPAbLhqI5Y72DiW1gaYUMVR2xmPtDA6aptrA/vCX5LGpyDPNP+YpTqch9eLBv/Gn9ciO3L+kgKLsDV6VyV5O" "6e5+n3PTsrXvjKJgHEDYp3QD1clLS9X9tw9Tb+BPV+qxc286niKcz5qgBhihN8GIKXSIQmf4SuBlffgAfX4Mgu9MaXbmyxryF4BGKP1ktLKuJOynla6QrkATNJmMy78ECUrUTZ8i0PVVgyeTQCkPmhAwIDAQAB;" )
</code></pre></div></div>
<p>Insérez tout cela dans votre fichier de zone, tout simplement.</p>
<h3id="dmarc">DMARC</h3>
<p>Ce n’est pas à proprement parlé un système de protection, mais plus une façon de dire ce qu’il faut faire avec des mails qui ne passe pas votre politique SPF et/ou DKIM.<br/>
Une consigne pour le SMTP qui reçoit en quelque sorte. A ne pas négliger, car l’absence de ce champ peut compromettre la livraison de vos mails.</p>
<p>Insérez une ligne semblable à la suivante :</p>
<p>_dmarc.xoyize.xyz. IN TXT “v=DMARC1; p=none; rua=mailto:postmaster@xoyize.xyz;ruf=mailto:postmaster@xoyize.xyz”</p>
<p>le p indique la politique à appliquer chez le SMTP si un mail reçu en votre nom (de domaine) ne passe ni SPF, ni DKIM.</p>
<p>Il est possible de spécifier :</p>
<ul>
<li>none, ne rien faire, mais juste le consigner dans les rapports envoyés à postmaster@xoyize.xyz</li>
<li>quarantine : mettre le mail en spam.</li>
<li>reject : le rejeter</li>
<li>rua indique à quelle adresse recevoir les reports agrégés</li>
<li>ruf indique où recevoir les reports détaillés (envoyés à chaque fois qu’un mail en votre nom est refusé)</li>
</ul>
<p>Pour plus d’informations : https://dmarc.org/wiki</p>
<p>Au début, disons le premier mois, utilisez un p=none et une fois qu’on voit que tout est OK (les mails refusés le sont à juste titre et non pas du à une boulette de votre côté), vous pouvez passer sur p=quarantine, ou p=reject.</p>
<h2id="tests-avec-dig">Tests avec dig</h2>
<p>Pour tester, on va utiliser dig et au passage, l’interrogation se fera auprès du DNS de Google pour être sur que la propagation DNS est bonne.</p>
<p>Si vous vous retrouvez listé, chaque liste gérant la chose à sa façon, à vous d’aller voir sur leur site pour vous faire délister.</p>
<h2id="liens-1">Liens</h2>
<p>Voila quelques liens pour tester un peu votre serveur :</p>
<p>https://www.mail-tester.com : très pratique, permet de voir si vous n’auriez pas louper une étape en vous donnant une note.</p>
<p>https://www.emailsecuritycheck.net : teste la protection de votre système en envoyant 7 mails douteux. Le 3 ne doit même pas arriver, les autres doivent se retrouver en spam.</p>
<p>Plus généralement, le site https://mxtoolbox.com est très complet car il couvre de nombreuses vérifications (et pas qu’au sujet de la messagerie).</p>
<h2id="erreurs">ERREURS</h2>
<divclass="language-plaintext highlighter-rouge"><divclass="highlight"><preclass="highlight"><code>Oct 22 10:55:10 xoyize postfix/lmtp[15186]: E7AFA63841: to=<ym@xoyize.fr>, orig_to=<root@xoyize.xyz>, relay=none, delay=583, delays=583/0.03/0/0, dsn=4.4.1, status=deferred (connect to xoyize.xyz[private/dovecot-lmtp]: No such file or directory)
<divclass="article__section-navigator clearfix"><divclass="previous"><span>PRÉCÉDENT</span><ahref="/2019/10/17/Linux-gestion-des-utilisateurs-et-permissions-serveur-web.html">Linux, gestion des utilisateurs ,permissions des fichiers et répertoires d’un serveur web</a></div><divclass="next"><span>SUIVANT</span><ahref="/2019/12/11/Trousseau-de-Cles-Gnome-Keyring.html">XFCE/GNOME Porte-clés ou trousseau (gnome-keyring)</a></div></div></div>
</div>
<script>(function(){
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
$(function() {
var $this ,$scroll;
var $articleContent = $('.js-article-content');
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var scroll = hasSidebar ? '.js-page-main' : 'html, body';