Comptes dynamique pour ProFTPd
IntroLe sujet traité par cet article, résulte del’agrandissement de ma société, suite a un rachat, nous passons de 30 postes à 70, il est temps de trouver un système d’administration plus aisé que les solutions traditionnelles pour gérer les utilisateurs et les différents services à base d’authentification. Les versions utilisésJe me sert d’un système LFS 4.0, mais les autres distributions fonctionnent de manière identique a quelques détails près, notamment au niveau de l’emplacement de fichiers de configuration. Pour Proftpd, j’utilise la version 1.2.7, compilé de la manière suivante: ./configure --prefix=/usr/local/Proftpd --with-modules=mod_ldap &&make && make install L’option –prefix signifie que tous les fichiers relatifs à Proftpd seront rangés dans le répertoire /usr/local/proftpd le fichier de configuration sera donc dans le répertoire /usr/local/proftpd/etc/proftpd.conf. si vous installez un paquetage rpm (pour redhat ou mandrake), le fichier sera probablement /etc/proftpd.conf, je ne connais pas les autres distributions. Pour le serveur LDAP, j’utilise la version 2.1.12, compilé avec les commandes suivantes: ./configure --prefix=/usr/local/openldap --enable-syslog && make && make install OpenLDAP sera intégralement installé dans le répertoire /usr/local/openldap, ces fichiers de configuration seront donc dans le répertoire /usr/local/openldap/etc/openldap, pour des distributions différentes, ils seront probablement dans /etc/openldap. L’option –enable-syslog, est active le système de log Syslog, elle n’est pas vraiment nécessaire dans le cadre de cet article, mais elle sert toujours et elle permet de centraliser ses logs. J’utilise LDAP Browser afin d’administrer et gérer la base LDAP, je n’expliquerai pas ici son fonctionnement, mais je le trouve très utile. Le fait qu’il soit écrit en java, permet de le faire tourner sur de multiples plates-formes il est disponible a cette adresse: http://www.iit.edu/~gawojar/ldap ![]() Il existe aussi GQ uniquement sous Linux http://biot.com/gq/ Les services traités:
Présentation de OpenLDAPUne base LDAP permet avant tout de gérer des utilisateurs, elle est optimisée pour un accès rapide en lecture. Elle est donc idéale pour gérer ce genre de situations. Elle comprend des droits d’accès et une structure en « arbre », elle devient donc parfaite pour cacher une partie de ses entrées à certains types de services. On pourra ainsi séparer la liste du personnel de la liste des accès ftp. Je vais tout d’abord détailler le service LDAP et son principe de fonctionnement: Un annuaire LDAP est composé d’entités classées sous forme d’arbre, ce qui veut dire que l’on peut avoir un classement qui représente la hiérarchie de sa société ou bien une organisation des machines clientes. Chaque élément de cette hiérarchie est distingué par un dn (Distinguished Name) qui est un identifiant unique. Chaque élément possède des attributs qui sont piochés dans des schémas. Ces attributs contiennent les valeurs utiles: le nom de la personne, son adresse mail, etc. L’annuaire LDAP fonctionne sur le modèle client serveur, son interrogation est donc faîte au travers de protocoles réseau basés sur TCP/IP. Cela implique que la base peut être consultée partout dans le monde via l’internet, ou rester interne à sa société, ou même être utilisée via des tunnels sécurisés entre plusieurs succursales. Stratégie d’organisation de la baseAvant de commencer à mettre en place les services, il faut procéder à une analyse du problème afin de réfléchir à une structure d’annuaire. Il faut pouvoir stocker la liste des utilisateurs afin de pouvoir affecter des propriétaires aux différents fichiers. Ces données devront pouvoir remplacer le fichier /etc/passwd il faut donc inclure les données suivantes:
Plusieurs choix sont possibles pour gérer l’accès FTP, soit on crée une liste d’utilisateurs destinés uniquement au service FTP, soit on décide que chaque utilisateur existant (la liste des utilisateurs) possède un attribut LDAP qui autorise le ftp à l’utilisateur. Dans mon cas, la deuxième solution n’a aucun intérêt. En effet l’accès au serveur est destiné à certains clients et non aux usagers du réseau local, il faut donc entrer une liste d’utilisateur ftp. Pour ces utilisateurs, il faudra les données suivantes:
Nous pouvons constater que les données sont quasiment les mêmes pour les utilisateurs et pour le service FTP. Pour organiser la base, nous créerons deux branches dans l’arbre, une que nous nommerons « People », pour les utilisateurs et « FTP » pour les comptes ftp. Mise en place de OpenLDAPMaintenant que nous connaissons la structure à mettre en place dans l’annuaire, nous pouvons choisir les schémas à utiliser. Les schémas sont les fichiers de définition des types de données stockées dans la base. Voila la liste des schémas fournis en standard avec OpenLDAP: corba.schema, core.schema, cosine.schema, inetorgperson.schema, java.schema, misc.schema, nis.schema, openldap.schema. Voila les schémas que j’ai ajoutés à ma base LAP via le mot clé « include » dans le fichier slapd.conf. include /usr/local/openldap/etc/openldap/schema/core.schema include /usr/local/openldap/etc/openldap/schema/cosine.schema include /usr/local/openldap/etc/openldap/schema/inetorgperson.schema include /usr/local/openldap/etc/openldap/schema/nis.schema Le schéma core et le schéma cosine, sont indispensables, la base refuse de démarrer sans ceux-ci et le schéma inetorgperson inclus des définitions interressantes pour l'organistaion de la base. Le schéma essentiel pour le projet, est le schéma nis, qui contient les définitions des comptes et groupes au standard posix. Voila par exemple la définition d’un compte utilisateur : objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top AUXILIARY DESC 'Abstraction of an account with POSIX attributes' MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) ) Sa syntaxe est assez intuitive, objectclass est le mot clé pour définir un nouvel objet, l’objet est défini entre parenthèses. Le premier chiffre est un identifiant unique et standardisé, il est suivi du nom de l’objet (posixAccount). SUP indique les classes dont l’objet hérite. DESC est la description de l’objet, MUST liste les élément de l’objet qui sont indispensable au fonctionement, chaque élément est séparé par un « $ », on retrouve cn (Common Name) qui est le nom de la personne, uid (User IDentifier) est le login de la personne, uidNumber, est le numéro unique qui identifie la personne sur le système compatible Posix (présent dans /etc/passwd pour le système d’utilisateurs standard), gidNumber (Group Identifier), est le numéro du groupe auquel la personne appartient et homeDirectory est le répertoire utilisateur, dans lequel sera stocké les fichiers utilisateurs et les fichiers de configuration propre à l’utilisateur. MAY liste les éléments facultatifs, le mot de passe (userPassword), le shell utilisé (loginShell), le gecos qui sert à stocker le nom complet de l’utilisateur et description contient une éventuelle description de l'entrée. Il n’est pas indispensable que vous compreniez ces syntaxes pour la suite de l’article, les fichiers schémas sont fournis par OpenLDAP et contiennent tous les éléments couramment utilisés pour la construction d’une base LDAP. Un service LDAP est fort aisé à mettre en place, après avoir compilé et installé le service, éditez le fichier slapd.conf, voila le mien : #inclusions #---------- include /usr/local/openldap/etc/openldap/schema/core.schema include /usr/local/openldap/etc/openldap/schema/cosine.schema include /usr/local/openldap/etc/openldap/schema/inetorgperson.schema include /usr/local/openldap/etc/openldap/schema/nis.schema #section generale #---------------- pidfile /var/run/slapd.pid argsfile /var/run/slapd.args loglevel -1 defaultaccess read sizelimit 1000 timelimit 60 schemacheck on #database #-------- database ldbm cachesize 1000 dbcachesize 1000000 directory /usr/local/openldap/var/lib/ldap mode 0600 index objectClass eq index cn pres,eq,sub index dc pres,eq,sub index ou pres,eq,sub index uid pres,eq,sub index loginShell pres,eq index uidNumber pres,eq index gidNumber pres,eq index homeDirectory pres,eq index givenname pres,eq,sub suffix "dc=test,dc=fr" #controle d'access #----------------- rootdn "cn=root,dc=test,dc=fr" rootpw secret La section « inclusion », liste les fichiers de définition des schémas à inclure dans la base. La section générale, liste les paramètres nécessaires au fonctionnement de la base. Pidfile défini le fichier où sera stocké le pid (Process IDendifier) du service ldap. Argsfile défini l’emplacement du fichier slapd.args. Loglevel défini les évènement à loguer, -1 permet de tout loguer, il est utile de positionner cette valeur à -1 durant l’installation du service, afin de pouvoir consulter toutes les erreurs. Defaultacces, donne des droits d’accès par défaut, defaultaccess=read, signifie que toute personne qui se logue anonymement sur la base, aura accès à toutes les données en lecture seule, laisser cette option sur read n’est pas une très bonne stratégie de confidentialité. Sizelimit, limite le nombre d’entrées de la base, une limite de 1000 pour une société de 70 personnes laisse une marge raisonable ;-). Timelimit, limite le temps d’une recherche, il est exprimé en secondes, concrètement si la recherche n’est pas satisfaite en 60 secondes, ldap renvoie une erreur indiquant un dépassement de temps. Schemacheck permet de vérifier l’intégrité des schémas au démarrage de la base, il sert à vérifier que les attributs entrées dans la base sont cohérents avec les schémas définis. La section database fournit les paramètres utilisés par la base proprement dite. Database définit le moyen de gestion et stockage de la base, ldbm est utilisé très couramment, cachesize indique la taille du cache en nombre d’entrées pour la base de données. dbcachesize indique la taille en octets du cache associée à chaque fichier d’index ouvert. Directory est le répertoire dans lequel la base sera stockée. Le mode défini les droits unix des fichiers de la base, mode=0600 indique de la base sera en lecture/ecriture uniquement pour le propriétaire (ldap). Les index, sont les champs susceptibles d’être demandés dans une recherche, le fait de les indexer accélère la recherche. Chaque nouvel index créera une nouvelle base classée par ordre d’index. Les valeurs pres, eq, sub, approx, déterminent le mode de recherche, eq optimise l’index pour une recherche basée sur l’égalité des termes, sub optimise pour les sous chaines, et approx pour l’approximation. Les personnes connaissant déjà bien LDAP, noteront peut être quelques incohérences dans les exemples, ceci est du au fait que j’ai masqué les infos propres à ma société ainsi que quelques personnalisations de la base que j’ai enlevé car elles n’entrent pas dans le cadre de cet article. Voila un « ls » des fichiers de la base: [root@mail ldap]# ls -al /var/lib/ldap total 740 drwx------ 2 ldap ldap 4096 jun 18 2002 . drwxr-xr-x 10 root root 4096 nov 7 20:05 .. -rw------- 1 ldap ldap 111656 fev 21 13:19 cn.gdbm -rw------- 1 ldap ldap 27605 fev 21 13:16 dn2id.gdbm -rw------- 1 ldap ldap 14972 fev 21 13:19 gidNumber.gdbm -rw------- 1 ldap ldap 64208 fev 21 13:19 givenName.gdbm -rw------- 1 ldap ldap 15832 fev 21 13:19 homeDirectory.gdbm -rw------- 1 ldap ldap 77755 fev 21 13:19 id2entry.gdbm -rw------- 1 ldap ldap 14692 fev 21 13:19 loginShell.gdbm -rw------- 1 ldap ldap 12296 fev 21 13:16 nextid.gdbm -rw------- 1 ldap ldap 14712 fev 21 13:19 objectClass.gdbm -rw------- 1 ldap ldap 106552 fev 21 13:19 uid.gdbm -rw------- 1 ldap ldap 16012 fev 21 13:19 uidNumber.gdbm L’option suffix donne le dn de base de la base, il est courant de le faire correspondre au suffixe dns de sa société. La dernière partie « contrôle d’access » donne aux utilisateurs des droits sur la base. Rootdn est le dn de l’utilisateur root qui à accès a tout, rootpw est le mot de passe root, il est écrit en clair dans la base, il est donc conseillé de mettre des droit d’accès assez restreint au fichier de configuration. On peut tout de même crypter le mot de passe, il suffit d’utiliser la commande suivante (il faut avoir installé perl).
#perl -e "print crypt('passwd','aa');"
aaU3oayJ5BcR6
perl ou passwd représente le mot de passe et aa une chaîne de deux caractères quelconques. Il faudra ensuite mettre cette ligne dans le fichier de configuration:
rootpw {crypt}aaU3oayJ5BcR6 #la representation du mot passwd
La valeur qui suit {crypt} est bien sur la valeur retournée par la commande précédente. La section « contrôle d’accès » permet beaucoup plus de choses que je ne détaillerai pas. Elle permet notamment de déléguer l’administration de certaines parties de la base à d’autres utilisateurs. Pour une société de 70 personnes sans succursales, un seul Admin est suffisant. Mes droits d’accès seront donc un accès en lecture seule pour tout le monde et tous les services et un accès complet pour root. Il n’y a plus qu’à lancer la base, en général /etc/rc.d/init.d/ldap start, pour les utilisateurs lfs, il faudra créer le fichier de démarrage. Si OpenLDAP ne se lance pas, reportez vous aux messages d’erreurs dans les journaux de logs. Maintenant que la base est lancée, il faut ajouter des entrées, pour cela on utilise le format ldif. Voila le format d’un fichier ldif. #création du suffixe, le dn de base dn: dc=test,dc=fr objectClass: top objectClass: posixGroup cn: test gidNumber: 1000 # Création de People dn: cn=People,dc=test,dc=fr objectClass: top objectClass: posixGroup cn: People gidNumber: 2000 # Création de FTP dn: cn=FTP,dc=test,dc=fr objectClass: top objectClass: posixGroup cn: FTP gidNumber: 3000 # entrée de utilisateur 1 dn: cn= utilisateur1,cn=People,dc=test,dc=fr objectClass: Top objectClass: posixAccount cn: utilisateur1 uid: utilisateur1 uidNumber: 2001 gidNumber: 2000 userPassword: pass1 homeDirectory: /home/utilisateur1 loginShell: /bin/false # entrée d'un access FTP dn: cn=ftp1,cn=FTP,dc=test,dc=fr objectClass: Top objectClass: posixAccount cn: ftp1 uid: ftp1 uidNumber: 3001 gidNumber: 3000 userPassword: motdepasse homeDirectory: /home/ftp1 loginShell: /bin/false Le fichier au format LDIF, permet de remplir la base. L’entrée primordiale, est la première, les deux suivantes créent deux branches de l’arbre, les autres sont les entrées utilisateurs et comptes ftp. On retrouve dans le fichier les noms définis plus haut dans les schémas. Chaque entrée du fichier est séparée par une ligne vide. Le premier champ est le dn, il doit être composé d’un attribut de l’entrée en général le cn mais cela reste libre, il doit être suivi de tout son chemin d’accès, ce qui permet de définir l’arbre: dn: dc=test,dc=fr Il faut ensuite lister les objets utilisés par l’entrée dans notre cas ils seront top, et posixGroup pour les branches de l’arbre et top et posixAccount pour les utilisateurs. Il faut ensuite renseigner les attributs choisis pour chaque entrée. Pour entrer ces données dans la base ldap, il faut que la base soit lancée, ensuite les données pourront être entrées à l’aide de la commande ldapadd avec cette syntaxe: ldapadd -x -h 127.0.0.1 -w secret -D cn=root,dc=test,dc=fr -f fichier.ldif Le paramètre « -x » est utilisée pour accéder à la base sans cryptage. Le paramètre « -h » donne l’adresse du serveur ldap à remplir. Le « -w » donne le mot de passe de la base, il est utile dans les scripts, si vous tapez les commandes sous les yeux attentifs d'une assemblée remplacez le par le paramètre « -W » (majuscule) car il propose une invite pour taper le mot de passe. Le « -D » spécifie de dn de l’utilisateur root et le « -f » indique le fichier ldif a utiliser. Mise en place des propriétaires des fichiers Maintenant que nous avons entré les utilisateurs, il nous reste à les faire reconnaître par le système. En effet si l’utilisateur ftp1 se connecte au serveur ftp et qu’il uploade quelques fichiers, le fichier aura comme propriétaire 3001:3000 au lieu de ftp1:FTP. Pour que le système reconnaisse les utilisateurs stockés dans la base ldap, nous modifierons le fichier /etc/nsswitch. Il faut faire attention en modifiant ce fichier, car une erreur de manipulation peut nuire au fonctionnement du serveur. Voila les lignes à modifier dans le fichier /etc/nsswitch.conf: passwd: files ldap group: files ldap shadow: files ldap Il suffit de rajouter ldap derrière chacune de ces lignes. Ceci indiquera au système de gestion des propriétaires qu’il faut rechercher l’utilisateur dans les fichiers (respectivement /etc/passwd, /etc/group et /etc/shadow) puis si aucun uid n’est trouvé, il doit regarder dans la base ldap. Il faut vérifier que la bibliothèque qui permet le fonctionnement de nss avec ldap est bien installée, elle est généralement présente dans /lib, elle porte le nom de libnss_ldap.xxx, si ce fichier est présent, tout va bien, s’il n’est pas la, il faut installer le package libnss_ldap, procurez vous le et installez le, avec un système rpm ou deb. Avec une lfs, récupérez l’archive, décompressez la,puis compilez la (./configure -prefix=/usr/local/nss-ldap && make && make install), il faut ensuite créer un lien symbolique de /usr/ocal/nss-ldap/lib/libnss_ldap.xxx dans /lib. Il reste juste à renseigner la bibliothèque sur l’emplacement du serveur ldap. Le fichier est en général /etc/ldap.conf, dans le cas de la lfs, il est situé dans /usr/local/nss-ldap/etc/ldap.conf, il suffit de mettre ces deux lignes à l’intérieur: host 127.0.0.1 base dc=test,dc=fr Si tout ceci a été effectué sans erreurs, vous pourrez taper les commandes suivantes pour tester le système:
touch test #création d'un fichier quelconque de test
chown ftp1:FTP test #si vous n'avez pas d'erreur, le proprietaire du fichier de
#test, est un utilisateur declar�dans la base ldap.
vous faîte un ls -ail, vous verrez : # ll total 0 -rw-r--r-- 1 ftp1 FTP 0 Mar 1 20:15 test Mise en place de la structures de repertoires:Avant d’installer Proftpd, il manque a créer les répertoires qui seront utilisés par le serveur ftp pour stocker les données à partager. Pour cela, je vous propose ce script largement commenté. Le lancement de ce script, crée les répertoires utilisés par le serveur ftp, si le répertoire existe déjà, il ne sera pas créé. Il ajuste ensuite les droits d’accès à ces répertoires:
#!/bin/sh
#cette ligne recherche toutes les entrées de la branche ftp, elle demande uniquement
#le paramètre homeDirectory, un grep filtre la réponse et ne laisse apparaître que les
#lignes commençant par «homeDirectory:», on obtiendra donc la ligne suivante:
# homeDirectory: /home/ftp1
#on entame un boucle, pour laquelle à chaque tour
#$i sera remplacé par un nouveau
#répertoire a créer
for i in `ldapsearch -x -b "cn=FTP,dc=test,dc=fr" homeDirectory | grep homeDirectory: | awk '{print $2 }'`
do
#on verify que le repertoire n’existe pas
if [ ! -e /home/$i ]; then
#on crée le répertoire
echo "Creation de $i"
mkdir $i
#on va rechercher l’uid
USER=`ldapsearch -x -b "cn=FTP,dc=test,dc=fr" homeDirectory=$i uid | grep uid | awk '{print $2 }'`
#on change l’user pour tout le repertoire
chown $USER:FTP $i
fi
done
configuration de ProftpdVoila, il ne nous reste plus qu’à configurer Proftpd, si la compilation c’est bien passée, il suffit d’éditer le fichier de configuration proftpd.conf, voila le mien: ServerName "test file server" ServerType standalone ServerAdmin admin@test.fr DeferWelcome off DefaultServer on Port 21 Umask 022 User ftp Group ftp <Directory /*> AllowOverwrite on </Directory> MaxInstances 10 UseReverseDNS off IdentLookups off TimeoutStalled 300 ScoreboardFile /var/run/Proftpd.pid TransferLog /var/log/Proftpd.xfer_log DefaultRoot ~/ MaxLoginAttempts 3 LDAPServer "127.0.0.1" LDAPDoAuth on "cn=FTP,dc=test,dc=fr" J’ai volontairement simplifié le fichier, car la configuration de Proftpd n’est pas l’objet de l’article. J’ai juste laissé ce qui est nécessaire à son fonctionnement. Les paramètres qui nous intéressent sont: LDAPServer et LDAPDoAuth. LDAPServer donne l’adresse du serveur ldap utilisé pour l’authentification. L’option suivante est bien plus intéressante, c’est celle qui choisit la liste des utilisateurs à authentifier, ainsi que d’éventuels filtres de recherche. En mettant « on "cn=FTP,dc=test,dc=fr" » le serveur effectuera des recherches uniquement dans la branche FTP de l’annuaire, c'est-à-dire que la liste des utilisateurs (dans la branche People) sera ignorée lors de la validation des accès ftp autorisés. Si l’on met « on "dc=test,dc=fr" », tous les utilisateurs pourrons se connecter au serveur au même titre que les comptes ftp. Cette commande peut inclure des filtres de recherche, ceci est utile par exemple pour accorder un accès ftp a certains utilisateurs et pas d’autres. Si l’on crée un nouvel attribut pour chaque utilisateur dans la base ldap du nom de allowFtp, on lui alloue une valeur booléenne (vrai ou faux). On met « vrai » pour tous les utilisateurs authorisés à se connecter, « faux » pour les autres. Il ne reste plus qu’à rajouter un filtre dans le paramètre « LDAPDoAuth on "dc=test,dc=fr" "(allowFtp=true)" », le serveur recherchera uniquement les personnes dont l’attribut autorise la connexion. Il ne reste plus qu’à lancer le serveur, et à le tester. Voila, l’annuaire LDAP utilisé avec Proftpd doit être fonctionnel (il fonctionne très bien chez moi). Il faut savoir que LDAP peut être utilisé avec une multitude d’autres services, il peut se coupler avec samba (très intéressant pour gérer un domaine, cette technique se rapproche du système Ms active directory), il peut aussi être utilisé avec Sendmail pour attribuer une ou plusieurs adresses mail aux usagers. Il sert également avec pam pour les authentifications en tous genres. Et pour finir, il existe des bibliothèques pour quasiment tous les langages de programmation. |