Mise en avant

Auto-hébergement de la messagerie : Debian Jessie, Postfix, Dovecot, Postgrey

Auto-hébergement de la messagerie : Debian Jessie, Postfix, Dovecot, Postgrey…

Cet article répond à la question : comment installer simplement, un serveur de mail, qui soit un minimum sécurisé et capable de limiter un peu le SPAM ?

La configuration proposée permet de gérer les boites mails (BAL) des utilisateurs systèmes sur un ou plusieurs domaines. Les utilisateurs sont ceux ajoutés sur le système (/etc/passwd). Pas besoin de gérer les comptes mails avec des « Virtuals » dans une configuration basique (pour quelques personnes, cette option est amplement suffisante).

Prérequis

Avant tout, il faut que l’enregistrement MX soit configuré sur le DNS du domaine traité.

exemple.com.         3w   IN      MX  10   mail.exemple.com.

Ajouter aussi le champs Sender Policy Framework (SPF) dans la zone DNS, car certains serveurs de mails vérifient cette information pour qualifier les serveurs SPAMmeurs.

exemple.com.  IN  TXT   "v=spf1 mx -all"

Une dernière chose, pensez à mettre à jour le Reverse (enregistrement PTR dans la zone Reverse du DNS). Cette information est également vérifiée pour savoir si c’est vraiment sérieux de recevoir des mails de votre serveur.

Installation de la messagerie

Je pars du principe que le système est déjà installé et à jour (Debian Jessie). Les configurations ont été faites sur un VPS Cloud OVH, mais le serveur peut être hébergé n’importe où, il faut juste s’assurer que les ports nécessaires au fonctionnement de la messagerie ne soient pas filtrés ou bloqués (TCP 25, 993, 587).

Les paquets à installer :

$ sudo apt install postfix dovecot-imapd postgrey

Aux questions :

Configuration type, répondre : Internet Site
Nom du système de mail, répondre : exemple.com (ou levotre !)

La configuration par défaut après l’installation de Postfix

$ postconf -n

alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
append_dot_mydomain = no
biff = no
config_directory = /etc/postfix
inet_interfaces = all
mailbox_size_limit = 0
mydestination = exemple.com, localhost.localdomain, localhost
myhostname =  mx2.exemple.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
myorigin = /etc/mailname
readme_directory = no
recipient_delimiter = +
relayhost =
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_use_tls = yes

Il faut y ajouter :

## TLS smtp Opportuniste

smtpd_tls_security_level = may

## Dovecot (SASL) Simple Authentication and Security Layer
## http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
# On Debian Wheezy path must be relative and queue_directory defined
queue_directory = /var/spool/postfix
# and the common settings to enable SASL:
smtpd_sasl_auth_enable = yes

## local delivery agent (LDA) celui qui délivre le mail dans la BAL, avec la commande qui va bien

mailbox_command = /usr/lib/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"

## Format des BAL : Maildir
home_mailbox = Maildir/

## Quelques restrictions pour éviter les clandestins et les spammeurs 
## Bien évidement ces restrictions sont personnelles et sont tout à fait ajustable en fonction des besoins

smtpd_client_restrictions = permit_mynetworks,
    reject_unauth_pipelining,
    reject_rbl_client sbl-xbl.spamhaus.org,
    reject_rbl_client list.dsbl.org

smtpd_helo_required = yes

smtpd_helo_restrictions = permit_mynetworks,
    reject_invalid_hostname,
    reject_non_fqdn_hostname,
    warn_if_reject reject_unknown_hostname

smtpd_sender_restrictions = permit_mynetworks,
    reject_non_fqdn_sender,
    reject_unlisted_sender,
    reject_unknown_sender_domain

smtpd_recipient_restrictions =
    # General rules
    reject_non_fqdn_recipient,
    reject_unknown_recipient_domain,
    # Our users
    permit_mynetworks,
    permit_sasl_authenticated,
    # Spam filters
    reject_rbl_client zen.spamhaus.org,
    reject_rbl_client dnsbl.sorbs.net,
    reject_rhsbl_reverse_client dbl.spamhaus.org,
    reject_rhsbl_helo dbl.spamhaus.org,
    reject_rhsbl_sender dbl.spamhaus.org,
    # This should be next-to-last
    check_policy_service inet:127.0.0.1:10023
    reject_unauth_destination, reject_unlisted_recipient,
    permit

Authentification de l’expéditeur et chiffrement

Pour éviter que n’importe qui envoie des mails depuis notre serveur de mail, il vaut mieux s’assurer de l’identité et vérifier les habilitations de l’expéditeur.

# vi /etc/postfix/master.cf
~
submission inet n       -       -       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
~

Recharge la configuration et relance le service

service postfix restart

A ce stade

# netstat -lnpt

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:10023         0.0.0.0:*               LISTEN      4787/postgrey.pid -
tcp        0      0 0.0.0.0:587             0.0.0.0:*               LISTEN      5133/master     
tcp        0      0 0.0.0.0:143             0.0.0.0:*               LISTEN      5191/dovecot    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      539/sshd        
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      5133/master     
tcp6       0      0 :::587                  :::*                    LISTEN      5133/master     
tcp6       0      0 :::143                  :::*                    LISTEN      5191/dovecot    
tcp6       0      0 :::22                   :::*                    LISTEN      539/sshd        
tcp6       0      0 :::25                   :::*                    LISTEN      5133/master

On remarque que « postgrey » écoute sur le port 10023. Ce service va rejeter dans un premier temps, les serveurs mails qu’il ne connaît pas, puis acceptera de laisser passer le mail à la seconde tentative.

Théoriquement, avec le « Greylisted » et les quelques règles de restrictions, une bonne partie des SPAM seront rejetés.

Fini pour Postfix

Maintenant configuration de Dovecot

A modifier dans /etc/dovecot/conf.d/10-mail.conf

## Emplacement des BAL
#mail_location = mbox:~/mail:INBOX=/var/mail/%u
mail_location = maildir:~/Maildir

A modifier dans /etc/dovecot/conf.d/10-ssl.conf

## Activation du TLS
# SSL/TLS support: yes, no, required.
#ssl = no
ssl = required
ssl_cert = </etc/ssl/certs/ssl-cert-snakeoil.pem
ssl_key = </etc/ssl/private/ssl-cert-snakeoil.key

A modifier dans /etc/dovecot/conf.d/10-master.conf

# Gestion de l'authentification des utilisateurs 
# Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666 }

Relance le service

# service dovecot restart

Création d’un utilisateur

# adduser alex 

Création des alias

A modifier dans /etc/aliases

# See man 5 aliases for format
postmaster:    root
root: alex

Recharge la base des alias

# newaliases

Test

A configurer sur un client comme Thunderbird

Attention, le certificat TLS est auto signé, donc, une exception est nécessaire.

IMAP
Server Name: mx2.exemple.com
Port: 993
Connection security: SSL/TLS
Authentication method: Normal password
User Name: alex
SMTP
Server Name: mx2.exemple.com
Port: 587
Connection security: STARTTLS
Authentication method: Normal password
User Name: alex

Conclusion

Bon ben, voila ! Un serveur de mail de plus.

Cette configuration est suffisante pour passer la plus part des mécanismes de répudiation mis en place anarchiquement par certains serveurs de mail (pour lutter contre le SPAM).

CNAM – Information et communication pour l’ingénieur (ENG221)

CNAM ENG221 : retour d’expérience !

Retour d’expérience UE ENG221 CNAM : explications, étapes et déroulement

L’unité d’enseignement ENG221 se déroule sur 12 séances, un mixte de cours magistraux et de travaux pratiques.

La validation de l’examen se fait à la suite d’une soutenance de 20 minutes (+ 20 minutes de questions), sur un sujet théoriquement éloigné de la spécialité de l’auditeur.

Le document de synthèse doit contenir 30 pages max.

Le travail personnel est de 6 semaines au total (c’est cours, il ne faut pas perdre de temps).

Les étapes clés :

  • Attribution du sujet, et du président de jury, par mail (reçu le 16 novembre dans mon cas, début des cours le 28 septembre)
  • Envoyer par émail une proposition de plan détaillé au président du jury au plus tard 3 semaines après la réception du sujet (7 décembre)
  • Envoyer par émail de la « Méthodologie de Recherche d’Information » (2 pages max) au Professeur du cours, 2 semaines après (22 décembre).
  • Faire parvenir le document de synthèse en 3 exemplaires au secrétariat du président du jury et ce au plus tard 3 semaines plus tard (11 janvier).
  • Soutenance 1 à 3 semaines plus tard (27 janvier pour ma part)

La note méthodologie doit faire ressortir les éléments étudiés en cours et les appliquer au sujet proposé. La qualité et la justification des sources de la bibliographie sont des éléments importants. La diversifications des sources est conseillés. J’ai utilisé un schéma heuristique pour expliquer le cheminement de mon organisation. J’en ai dégagé le plan.

Le document de synthèse doit respecter le sujet proposé et contenir une bibliographie détaillée, équilibrée et de qualité.

La soutenance doit reprendre les points clés du document de synthèse. 25 slides est une bonne moyenne.

Le jury est composé de 3 professeurs, parfois 4, si le professeur du cours est présent.

A l’issu de la présentation (20 minutes), le jury posent des questions pointues et soutenues ! Je conseille de bien maîtriser son sujet dans les détails et ne pas laisser d’éléments flous ou sans explication. Et encore, cela ne suffit pas, c’est même le minimum, car le Jury est expérimenté et posera des questions sur ce que vous n’avez pas traité ou abordé. Donc, préparez vous bien. Ayez un avis critique sur votre sujet et répondez aux questions si et seulement si, vous maîtrisez la réponse.

Le jury délibère quelques minutes (sans vous) et vous donne votre note.

Mon sujet : la technologie NFC

Ma présentation : NFC-DOMONT

Le document de synthèse : CNAM-ENG221-DOMONT-NFC

Bonne chance à vous.

Outils d’analyse de flux réseau avec Nfdump, Nfsen (collecteur) et fprobe (sonde)

Outils d’analyse de flux réseau avec Nfdump, Nfsen (collecteur) et fprobe (sonde)

Comment le réseau est utilisé ? Comment optimiser la configuration du réseau sans visibilité temporelle ? Quels outils utiliser pour analyser les flux réseaux ?

Réponse : très simplement avec la combinaison des outils suivants :

  • nfdump : The nfdump tools collect and process netflow data on the command line
  • nfcapd : netflow capture daemon
  • NfSen : NfSen is a graphical web based front end for the nfdump netflow tools.
  • fprobe : libpcap-based tool that collect network traffic data and emit it as NetFlow flows towards the specified collector.

L’implantation de la solution sera faite sur un Debian Wheezy et Jessie

Pour schématiser, la sonde fprobe sera placée sur un pare-feu Debian Wheezy, elle enverra les flux aux collecteurs nfcapd (un autre serveur Debian Wheezy) et nfdump permettra de manipuler et restituer l’information, NfSen présentera l’information traitée sur un page Web (via des graphiques et des filtres avancés)

Installation de Nfsen sur le collecteur

La solution NFsen nécessite un serveur Web (Apache, Nginx) et quelques composants additionnels pour fonctionner (PHP, Perl.)

# apt-get install gcc flex librrd-dev make apache2 libapache2-mod-php5 php5-common rrdtool libmailtools-perl librrds-perl libio-socket-ssl-perl build-essential vim wget

Et Installation de Socket6 via CPAN :

# perl -MCPAN -e 'install Socket6'

NFDUMP

Une chose importante : il faut la version 1.6 ou ultérieur de NFDUMP et la compiler avec l’option –enable-nfprofile

nfdump-1.6.13.tar.gz (a récupérer sur le site : http://sourceforge.net/projects/nfdump/)

# wget http://downloads.sourceforge.net/project/nfdump/stable/nfdump-1.6.13/nfdump-1.6.13.tar.gz
# tar -zxvf nfdump-1.6.13.tar.gz
# cd nfdump-1.6.13/
# ./configure --enable-nfprofile
# make;make install

Pou vérifier la version :

$ nfdump -v

Remarque : NFdump peut etre utilisé en ligne de commande pour analyser les informations collectées (http://nfdump.sourceforge.net/).

nfdump -r /and/dir/nfcapd.200407110845 -c 100 'tcp and ( src ip 172.16.17.18 or dst ip 172.16.17.19 )'

NfSen

nfsen-1.3.7.tar.gz (a récupérer sur le site : http://nfsen.sourceforge.net/)

# wget http://downloads.sourceforge.net/project/nfsen/stable/nfsen-1.3.6p1
# tar -zxvf nfsen-1.3.7.tar.gz
# cd nfsen-1.3.7/
# cp etc/nfsen-dist.conf etc/nfsen.conf
# vi etc/nfsen.conf

Extrait du fichier de conf :

# user and group of the web server process 
# All netflow processing will be done with this user
$WWWUSER = "www-data";
$WWWGROUP = "www-data";
~~~
%sources = (
'upstream1' => { 'port' => '9995', 'col' => '#0000ff', 'type' => 'netflow' },
'peer1' => { 'port' => '9996', 'col' => '#ff0000' },
);

Les sources contiennent les paramètres des sondes (port d’écoute, couleur et type de flux )

Génère l’arborescence /var/www/nfsen/ > partie web + /data/nfsen/ > données collectés

# mkdir -p /data/nfsen
# ./install.pl /etc/nfsen.conf
# cd /data/nfsen/bin

A ce stade NFsen est prêt à être lancé :

#/data/nfsen/bin/nfsen start

Bonus :

Un extrait d’un VHOST avec Apache

<Directory /var/www/nfsen>
 DirectoryIndex disabled
 DirectoryIndex nfsen.php
 Options Indexes FollowSymLinks MultiViews
 AllowOverride None
 Order allow,deny
 allow from all
</Directory>

Vérifications :

  • vérifier que NFSen (nfcapd) et Apache sont bien lancés dans les processus
  • lancer http://ip.du.collecteur
  • les données collectées sont dans /data/nfsen/profiles-data/live/ (défini dans nfsen.conf)

 

exemple graphe nfsen
exemple graphe nfsen

Installation de la sonde Fprobe

J’installe ici la sonde sur un pare feu Debian (via le paquet disponible fprobe)

#aptitude install fprobe

Les configurations demandées lors de l’installation sont placées dans /etc/default/fprobe

La sonde sera lancée au démarrage du serveur (daemon fprobe)

Une sonde peut être lancée manuellement

#/usr/sbin/fprobe -i eth_interface -fip ip_collecteur:port-ecoute

Conclusion

L’alchimie de ces outils donne un bon outillage pour analyser les flux réseaux. Il est pertinent de placer les sondes aux endroits stratégiques sur le réseau afin d’avoir des données justes sur le trafic ambiant. Finalement pas besoin d’outils onéreux et compliqués pour collecter des informations sur les flux réseaux. La documentation de NfSen est assez explicite pour appréhender ses nombreuses possibilités http://nfsen.sourceforge.net/

LDAPS : OpenLDAP et GnuTLS – Debian

Introduction : LDAPS : OpenLDAP et GnuTLS – Debian Wheezy

Cet article traite l’installation, la configuration et la sécurisation de LDAP (Lightweight Directory Access Protocol) avec OpenLDAP et GnuTLS sous Debian Wheezy.

Depuis la version 2.4 de OpenLDAP la gestion de la configuration se fait par défaut via la On-Line Configuration (cn=config). OLC remplace la gestion de la configuration via le fichier slapd.conf. Elle permet une gestion dynamique de la configuration sans redémarrage systématique du service LDAP.

Debian Wheezy installe la version slapd 2.4.31-1

Le nom du serveur ici est srv.ldap.local. La base est dc=ldap,dc=local

INSTALLATION de OpenLDAP sous Debian Wheezy

# aptitude install slapd ldap-utils

Vérification

# ps aux | grep l[d]ap

openldap 3094 0.0 0.3 25408 3980 ? Ssl 15:45 0:00 /usr/sbin/slapd -h ldap:/// ldapi:/// -g openldap -u openldap -F /etc/ldap/slapd.d

CONFIGURATION

Par défaut une base nodomain est créé

# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b "cn=config" olcSuffix | grep ^olcSuffix

SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
olcSuffix: dc=nodomain

Vérification des schémas installés par défaut :

ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b "cn=config" olcSchemaConfig | grep ^cn

SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
cn: config
cn: module{0}
cn: schema
cn: {0}core
cn: {1}cosine
cn: {2}nis
cn: {3}inetorgperson

Reconfiguration de l’annuaire : création d’une seule base ldap.local

# dpkg-reconfigure -plow slapd
Voulez vous omettre la configuration d'OpenLDAP → Non

Nom de domaine : ldap.local

Nom d'entité (« organization ») : ldap.local

Mot de passe de l'administrateur : motdepasse

Module de base de données à utiliser : HDB

Faut-il supprimer la base de données à la purge du paquet ? Oui 

Faut-il déplacer l'ancienne base de données ? Oui

Faut-il autoriser le protocole LDAPv2 ? Non

Vérification après reconfiguration

# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b "cn=config" olcSuffix | grep ^olcSuffix
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
olcSuffix: dc=ldap,dc=local

La base dc=ldap,dc=local a bien été créée

PEUPLEMENT DE L’ANNUAIRE

Attention, Le mode « list » de vim ( :set list ) est privilège pour l’édition des fichiers LDIF afin d’être stricte sur la syntaxe (ne pas laisser d’espace en trop, LDIF est sensible à ça).

Ajout d’une OU people (Organizational Unit) et d’un groupe groups

Création du fichier LDIF

# cat ou.ldif 
dn: ou=people,dc=ldap,dc=local
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=ldap,dc=local
objectClass: organizationalUnit
ou: groups

Injection du fichier ou.ldif dans la configuration

# ldapadd -cxWD cn=admin,dc=ldap,dc=local -f ou.ldif
Enter LDAP Password: 
adding new entry "ou=people,dc=ldap,dc=local"

adding new entry "ou=groups,dc=ldap,dc=local"

Vérification

# ldapsearch -LLL -x -H ldap:/// -b "dc=ldap,dc=local" -D cn=admin,dc=ldap,dc=local -W
Enter LDAP Password: 
dn: dc=ldap,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: ldap.local
dc: ldap

dn: cn=admin,dc=ldap,dc=local
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9SlZRNEdkbURJNGRDNUhSUHR1a3VXbGUzQkZTYkxmdjI=

dn: ou=people,dc=ldap,dc=local
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=ldap,dc=local
objectClass: organizationalUnit
ou: groups

Ajout de quatre utilisateurs

# ldapadd -cxWD cn=admin,dc=ldap,dc=local -f users.ldif
Enter LDAP Password: 
adding new entry "uid=padme,ou=people,dc=ldap,dc=local"

adding new entry "uid=anakin,ou=people,dc=ldap,dc=local"

adding new entry "uid=leia,ou=people,dc=ldap,dc=local"

adding new entry "uid=luke,ou=people,dc=ldap,dc=local"

Vérification

slapcat 
dn: dc=ldap,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: ldap.local
dc: ldap
structuralObjectClass: organization
entryUUID: aac46d3a-f303-1033-8e5d-45d6f2932b4e
creatorsName: cn=admin,dc=ldap,dc=local
createTimestamp: 20141028153436Z
entryCSN: 20141028153436.269442Z#000000#000#000000
modifiersName: cn=admin,dc=ldap,dc=local
modifyTimestamp: 20141028153436Z

dn: cn=admin,dc=ldap,dc=local
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9SlZRNEdkbURJNGRDNUhSUHR1a3VXbGUzQkZTYkxmdjI=
structuralObjectClass: organizationalRole
entryUUID: aacb4f1a-f303-1033-8e5e-45d6f2932b4e
creatorsName: cn=admin,dc=ldap,dc=local
createTimestamp: 20141028153436Z
entryCSN: 20141028153436.314557Z#000000#000#000000
modifiersName: cn=admin,dc=ldap,dc=local
modifyTimestamp: 20141028153436Z

dn: ou=people,dc=ldap,dc=local
objectClass: organizationalUnit
ou: people
structuralObjectClass: organizationalUnit
entryUUID: bc0417de-f304-1033-8b72-8b44c99db207
creatorsName: cn=admin,dc=ldap,dc=local
createTimestamp: 20141028154214Z
entryCSN: 20141028154214.704697Z#000000#000#000000
modifiersName: cn=admin,dc=ldap,dc=local
modifyTimestamp: 20141028154214Z

dn: ou=groups,dc=ldap,dc=local
objectClass: organizationalUnit
ou: groups
structuralObjectClass: organizationalUnit
entryUUID: bc051512-f304-1033-8b73-8b44c99db207
creatorsName: cn=admin,dc=ldap,dc=local
createTimestamp: 20141028154214Z
entryCSN: 20141028154214.711179Z#000000#000#000000
modifiersName: cn=admin,dc=ldap,dc=local
modifyTimestamp: 20141028154214Z

dn: uid=padme,ou=people,dc=ldap,dc=local
objectClass: person
objectClass: shadowAccount
objectClass: inetOrgPerson
cn: Padme
sn:: UGFkbcOpIEFtaWRhbGEgU2t5d2Fsa2Vy
uid: padme
userPassword:: e1NTSEF9azdrVlBCNi9MYkM4eDM2UHl5WFQxUFV4c0M2Y2dnR3M=
mail: padme@ldap.local
structuralObjectClass: inetOrgPerson
entryUUID: 0d250ba0-f6ed-1033-98bd-db7881564dff
creatorsName: cn=admin,dc=ldap,dc=local
createTimestamp: 20141102150247Z
entryCSN: 20141102150247.545692Z#000000#000#000000
modifiersName: cn=admin,dc=ldap,dc=local
modifyTimestamp: 20141102150247Z

dn: uid=anakin,ou=people,dc=ldap,dc=local
objectClass: person
objectClass: shadowAccount
objectClass: inetOrgPerson
cn: Anakin
sn: Anakin Skywalker
uid: anakin
userPassword:: e1NTSEF9azdrVlBCNi9MYkM4eDM2UHl5WFQxUFV4c0M2Y2dnR3M=
mail: anakin@ldap.local
structuralObjectClass: inetOrgPerson
entryUUID: 0d26fb22-f6ed-1033-98be-db7881564dff
creatorsName: cn=admin,dc=ldap,dc=local
createTimestamp: 20141102150247Z
entryCSN: 20141102150247.558381Z#000000#000#000000
modifiersName: cn=admin,dc=ldap,dc=local
modifyTimestamp: 20141102150247Z

dn: uid=leia,ou=people,dc=ldap,dc=local
objectClass: person
objectClass: shadowAccount
objectClass: inetOrgPerson
cn: Leia
sn: Leia Organa
uid: leia
userPassword:: e1NTSEF9azdrVlBCNi9MYkM4eDM2UHl5WFQxUFV4c0M2Y2dnR3M=
mail: leia@ldap.local
structuralObjectClass: inetOrgPerson
entryUUID: 0d2acfcc-f6ed-1033-98bf-db7881564dff
creatorsName: cn=admin,dc=ldap,dc=local
createTimestamp: 20141102150247Z
entryCSN: 20141102150247.583494Z#000000#000#000000
modifiersName: cn=admin,dc=ldap,dc=local
modifyTimestamp: 20141102150247Z

dn: uid=luke,ou=people,dc=ldap,dc=local
objectClass: person
objectClass: shadowAccount
objectClass: inetOrgPerson
cn: Luke
sn: Luke Skywalker
uid: luke
userPassword:: e1NTSEF9azdrVlBCNi9MYkM4eDM2UHl5WFQxUFV4c0M2Y2dnR3M=
mail: luke@ldap.local
structuralObjectClass: inetOrgPerson
entryUUID: 0d2b542e-f6ed-1033-98c0-db7881564dff
creatorsName: cn=admin,dc=ldap,dc=local
createTimestamp: 20141102150247Z
entryCSN: 20141102150247.586883Z#000000#000#000000
modifiersName: cn=admin,dc=ldap,dc=local
modifyTimestamp: 20141102150247Z

Des vérifications supplémentaires peuvent être faite à distance :

# ldapsearch -x -H ldap://srv.ldap.local -b dc=ldap,dc=local -D "uid=luke,ou=people,dc=ldap,dc=local" -W
Enter LDAP Password: 
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# ldap.local
dn: dc=ldap,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: ldap.local
dc: ldap

# admin, ldap.local
dn: cn=admin,dc=ldap,dc=local
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator

# people, ldap.local
dn: ou=people,dc=ldap,dc=local
objectClass: organizationalUnit
ou: people

# groups, ldap.local
dn: ou=groups,dc=ldap,dc=local
objectClass: organizationalUnit
ou: groups

# padme, people, ldap.local
dn: uid=padme,ou=people,dc=ldap,dc=local
objectClass: person
objectClass: shadowAccount
objectClass: inetOrgPerson
cn: Padme
sn:: UGFkbcOpIEFtaWRhbGEgU2t5d2Fsa2Vy
uid: padme
mail: padme@ldap.local

# anakin, people, ldap.local
dn: uid=anakin,ou=people,dc=ldap,dc=local
objectClass: person
objectClass: shadowAccount
objectClass: inetOrgPerson
cn: Anakin
sn: Anakin Skywalker
uid: anakin
mail: anakin@ldap.local

# leia, people, ldap.local
dn: uid=leia,ou=people,dc=ldap,dc=local
objectClass: person
objectClass: shadowAccount
objectClass: inetOrgPerson
cn: Leia
sn: Leia Organa
uid: leia
mail: leia@ldap.local

# luke, people, ldap.local
dn: uid=luke,ou=people,dc=ldap,dc=local
objectClass: person
objectClass: shadowAccount
objectClass: inetOrgPerson
cn: Luke
sn: Luke Skywalker
uid: luke
userPassword:: e1NTSEF9azdrVlBCNi9MYkM4eDM2UHl5WFQxUFV4c0M2Y2dnR3M=
mail: luke@ldap.local

# search result
search: 2
result: 0 Success

# numResponses: 9
# numEntries: 8

Sécurisation de LDAP avec GnuTLS

OpenLDAP est compilé avec GnuTLS (et pas OpenSSL).

Vérification pour s’en convaincre :

# apt-rdepends slapd | grep tls
Reading package lists... Done
Building dependency tree       
Reading state information... Done
  Depends: libgnutls26 (>= 2.12.17-0)
libgnutls26
  Depends: libgnutls26 (>= 2.12.17-0)

Installation de GnuTLS

# apt-get install gnutls-bin

Les certificats seront placés dans un répertoire spécifique volontairement. Et le certificat serveur sera auto-signé par soucis de simplicité (c’est mal).

# mkdir /etc/ldap/ssl && chown openldap: /etc/ldap/ssl && cd /etc/ldap/ssl

Génération des certificats

# certtool --generate-privkey --outfile ca-key.pem
# certtool --generate-self-signed --load-privkey ca-key.pem --outfile  ca-cert.pem
Generating a self signed certificate...
Please enter the details of the certificate's distinguished name. Just press enter to ignore a field.
Country name (2 chars): FR
Organization name: ldap
Organizational unit name: ldap
Locality name: Paris
State or province name: Paris
Common name: srv.ldap.local
UID: 
This field should not be used in new certificates.
E-mail: mail@ldap.local
Enter the certificate's serial number in decimal (default: 1414942800): 


Activation/Expiration time.
The certificate will expire in (days): 1000


Extensions.
Does the certificate belong to an authority? (y/N): 
Is this a TLS web client certificate? (y/N): 
Will the certificate be used for IPsec IKE operations? (y/N): 
Is this also a TLS web server certificate? (y/N): Y
Enter a dnsName of the subject of the certificate: srv.ldap.local
Enter a dnsName of the subject of the certificate: 
Enter the IP address of the subject of the certificate: 
Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (y/N): 
Will the certificate be used for encryption (RSA ciphersuites)? (y/N): Y
Enter the URI of the CRL distribution point: 
X.509 Certificate Information:
	Version: 3
	Serial Number (hex): 54565050
	Validity:
		Not Before: Sun Nov 02 15:40:20 UTC 2014
		Not After: Sat Jul 29 15:40:24 UTC 2017
	Subject: C=FR,O=ldap,OU=ldap,L=Paris,ST=Paris,CN=srv.ldap.local,EMAIL=mail@ldap.local
	Subject Public Key Algorithm: RSA
	Certificate Security Level: Normal
		Modulus (bits 2432):
			00:bd:8b:1b:e5:66:82:21:da:42:d1:ec:4c:34:06:78
			00:9e:bc:b4:70:57:d2:35:77:55:d5:63:f0:2a:93:d0
			f8:52:f7:d3:b3:32:ce:d2:2d:dc:c5:4c:f4:a4:2d:5f
			35:68:4b:2a:af:a1:c3:4d:f7:51:50:86:68:c2:bc:47
			d1:42:4a:eb:e8:c4:7b:c5:c4:31:ad:e3:3f:15:f4:49
			9d:78:f5:54:2f:1e:36:47:2b:87:4a:17:5a:87:91:2b
			ca:fa:d0:8a:5b:a4:ad:bd:03:62:18:9a:cb:6a:2c:e1
			b5:e8:c9:dd:77:3c:ea:30:9c:fa:01:0d:92:fa:4b:49
			06:39:1a:7f:00:39:ca:e6:bf:01:ae:85:e3:d1:0a:69
			a7:6b:9d:2a:2c:9a:40:f2:a1:cd:07:1f:7a:61:4f:85
			f7:5e:1b:94:ed:56:fc:a9:39:f0:85:c7:32:38:6d:29
			0a:77:3f:f9:0e:4f:cb:5e:79:50:c6:12:3b:d4:48:6d
			45:f7:2b:b6:2b:29:5e:39:02:b0:07:3d:2e:d0:4d:c1
			57:39:60:0c:3e:c6:60:79:0d:ef:91:af:4e:c3:17:04
			3b:69:c8:9c:44:44:7e:c3:7f:ce:4b:2b:a5:cf:76:f0
			93:f7:5e:e1:ef:cc:e6:3b:4b:ce:f5:6b:fc:60:1e:fd
			5b:e2:41:40:a9:ec:1a:19:2c:0e:cb:aa:a9:2b:cf:48
			c0:71:83:c5:c1:0c:9f:bf:7b:42:7d:9e:8c:df:cc:99
			86:5f:ec:07:25:35:93:73:c1:8e:de:d7:1a:f1:82:0a
			91
		Exponent (bits 24):
			01:00:01
	Extensions:
		Basic Constraints (critical):
			Certificate Authority (CA): FALSE
		Subject Alternative Name (not critical):
			DNSname: srv.ldap.local
		Key Purpose (not critical):
			TLS WWW Server.
		Key Usage (critical):
			Key encipherment.
		Subject Key Identifier (not critical):
			4651006619055a0a69e37ddc8ffc41f47586c3ed
Other Information:
	Public Key Id:
		4651006619055a0a69e37ddc8ffc41f47586c3ed

Is the above information ok? (y/N): Y

Modification des droits sur le répertoire qui contient les certificats

# chown openldap: /etc/ldap/ssl/*
ls -lat /etc/ldap/ssl/*
-rw-r--r-- 1 openldap openldap 1566 nov.   2 16:41 /etc/ldap/ssl/ca-cert.pem
-rw------- 1 openldap openldap 1968 nov.   2 16:38 /etc/ldap/ssl/ca-key.pem

Le hostname du serveur doit est égal au CN

# hostname -f
srv.ldap.local

Ajout des configuration dans le cn=config

# cat tls.ldif
dn: cn=config
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/ssl/ca-key.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/ssl/ca-cert.pem
# ldapmodify -Y EXTERNAL -H ldapi:/// -f tls.ldif 
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"

Il faut ajouter ldaps:/// dans le /etc/default/slapd

#/etc/default/slapd
SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"

La configuration globale peut être vérifiée comme suit

# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config

ou directement

# less /etc/ldap/slapd.d/cn=config.ldif

Redémarrage du service slapd

# /etc/init.d/slapd restart
[ ok ] Stopping OpenLDAP: slapd.
[ ok ] Starting OpenLDAP: slapd.

Vérification

# ps axu | grep slapd
openldap  2472  0.0  0.3  25520  3984 ?        Ssl  17:03   0:00 /usr/sbin/slapd -h ldap:/// ldapi:/// ldaps:/// -g openldap -u openldap -F /etc/ldap/slapd.d

# netstat -tunlp | grep slapd
tcp        0      0 0.0.0.0:636             0.0.0.0:*               LISTEN      2472/slapd      
tcp        0      0 0.0.0.0:389             0.0.0.0:*               LISTEN      2472/slapd      
tcp6       0      0 :::636                  :::*                    LISTEN      2472/slapd      
tcp6       0      0 :::389                  :::*                    LISTEN      2472/slapd

Tests Local et distant

Ajustement à faire pour tenir compte du certificat auto signé

# cat /etc/ldap/ldap.conf
URI ldap:/// ldaps:///
TLS_REQCERT hard
TLS_CACERT  /etc/ldap/ssl/ca-cert.pem
# ldapsearch -h srv.ldap.local -ZZ -D "cn=admin,dc=ldap,dc=local" -W -b 'dc=ldap,dc=local' '(objectclass=*)'
# ldapsearch -x -H ldaps://srv.ldap.local -b dc=ldap,dc=local -D "uid=luke,ou=people,dc=ldap,dc=local" -W

Des tests peuvent être réalisés avec le carnet d’adresse LDAP de Thunderbird (ajouter une exception de sécurité, gestion des certificats, ajoutez : srv.ldap.local:636)

Ajustement pour rendre LDAPS obligatoire et LDAP seulement en localhost

SLAPD_SERVICES="ldap://127.0.0.1:389/ ldapi:/// ldaps:///"
# /etc/init.d/slapd restart[ ok ] Stopping OpenLDAP: slapd.
[ ok ] Starting OpenLDAP: slapd.
# ps axu | grep slapd
openldap  2568  0.0  0.3  25520  3988 ?        Ssl  17:43   0:00 /usr/sbin/slapd -h ldap://127.0.0.1:389/ ldapi:/// ldaps:/// -g openldap -u openldap -F /etc/ldap/slapd.d
# netstat -tunlp | grep slapd
tcp        0      0 0.0.0.0:636             0.0.0.0:*               LISTEN      2568/slapd      
tcp        0      0 127.0.0.1:389           0.0.0.0:*               LISTEN      2568/slapd      
tcp6       0      0 :::636                  :::*                    LISTEN      2568/slapd 

ACL

Afin d’ajuster les accès à l’annuaire, il est nécessaire de modifier les ACLs par défaut.

# ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -W -b cn=config '(olcDatabase={1}hdb)' olcAccess
Enter LDAP Password: 
dn: olcDatabase={1}hdb,cn=config
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou
 s auth by dn="cn=admin,dc=ldap,dc=local" write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,dc=ldap,dc=local" write by * 
 read

Par défaut tout le monde peut lister les entrées de l’annuaire. Nous allons limiter la lecture aux utilisateurs authentifiés

# cat acl.ldif 
dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {1}to * 
 by dn="cn=admin,dc=ldap,dc=local" write 
 by self write 
 by users read
# ldapmodify -Y EXTERNAL -H ldapi:/// -f acl.ldif 
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={1}hdb,cn=config"

Pas besoin de redémarrer le service LDAP. Les modifications sont prises en compte dynamiquement

# ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -W -b cn=config '(olcDatabase={1}hdb)' olcAccess
Enter LDAP Password: 
dn: olcDatabase={1}hdb,cn=config
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou
 s auth by dn="cn=admin,dc=ldap,dc=local" write by * none
olcAccess: {1}to * by dn="cn=admin,dc=ldap,dc=local" write by self write by us
 ers read

CONCLUSION

Cet article (un peu long) a traité principalement de l’installation, de la configuration et de la sécurisation de OpenLDAP.

Dans un prochain article, il sera question de traiter la sécurisation de l’authentification (SASL), de l’optimisation par la mise en place des index, et de la réplication.

Références

http://fr.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol

http://www.openldap.org/doc/admin24/index.html

http://wiki.acacs.org/doku.php?id=installer_openldap_slapd_en_version_2.4_en_ssl_tls_sous_debian_squeeze

https://wiki.debian.org/LDAP/OpenLDAPSetup

http://www.inetdoc.net/pdf/sysadm-net.ldap.qa.pdf