diff options
Diffstat (limited to 'content/Informatique/2010-04-08-chroot.rst')
-rw-r--r-- | content/Informatique/2010-04-08-chroot.rst | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/content/Informatique/2010-04-08-chroot.rst b/content/Informatique/2010-04-08-chroot.rst new file mode 100644 index 0000000..edec0bc --- /dev/null +++ b/content/Informatique/2010-04-08-chroot.rst @@ -0,0 +1,236 @@ +.. -*- mode: rst -*- +.. -*- coding: utf-8 -*- + +Mettre en place un environnement sftp chrooté +############################################# + +:date: 2010-04-08 +:tags: Libre, Hébergement, sftp + +*Note* : Je propose une autre approche pour mettre en place cette +solution : +`mettre-en-place-un-environnement-sftp-chroote-2/ <{filename}2011-06-07-sftp.rst>`_ + +La demande +~~~~~~~~~~ + +Ma copine m'a demandé de trouver une solution simple pour échanger des +fichiers avec sa sœur, msn posant des problèmes… J'ai pensé à mon serveur ssh +et mettre en place une connexion sftp pour ça. Sur le principe cela a été +adopté avec une petite présentation de filezilla (je ne sais pas s'il existe +des clients sftp intégrés sous windows ?), j'ai donc commencé à mettre en place +le système. De mon côté, la condition principale est de n'autoriser les +connexions que par clef publique (pas de mot de passe), ma copine a tenu à ce +que sa sœur ne puisse pas accéder aux documents présents dans son home, et du +mien à ce que l'on ne puisse pas pour autant se promener dans l'arborescence du +serveur : il va donc falloir chrooter l'environnement. Il existe pas mal de +documentation la dessus sur internet, mais je me suis souvent retrouvé face à +des exemples incorrects ou incompatible avec le fait de passer par une clef +publique, je vais donc détailler les problèmes rencontrés. + +Le compte + clef publique +~~~~~~~~~~~~~~~~~~~~~~~~~ + +La première étape est de créer le compte, cela se fait assez simplement +: + +:: + + # adduser ${user} + +|Création de la clef ssh avec puttygen| et en répondant aux questions +par défaut… Vient ensuite la clef publique : filezilla gère les clefs +privés au format ppk (putty) et je n'ai pas trouvé d'outil pour les +générer sous windows. Je suis donc passé par wine + puttygen pour créer +la clef. Une fois celle-ci crée, on enregistre la partie publique et la +partie privée de la clef. La clef publique va être enregistrée dans le +fichier ${user}/.ssh/know\_host sur le serveur pour autoriser le client +à s'y connecter. La clef privée sera enregistrée de son côté au format +ppk pour être utilisée par filezilla (il est possible à partir de ce +fichier de générer une clef privée de type openssh). + +|image1| + +Il faut ensuite intégrer la clef privée dans filezilla en passant par +les paramètres : elle sera automatiquement lue à la connexion (il faut +choisir «interactive» dans le type d'authentification). (Attention : +sous windows j'ai rencontré des problèmes avec un répertoire contenant +des accents, la clef semblait être lue, mais la connexion ne se faisait +pas pour autant.) + +Chrooter l'environnement +~~~~~~~~~~~~~~~~~~~~~~~~ + +Aujourd'hui il est possible de chrooter nativement un environnement sftp +avec openssh. Il faut pour cela mettre en place une condition sur +l'utilisateur (ou le groupe) pour faire le chroot : + +:: + + Match user ${user} + ChrootDirectory /var/chroot/ + X11Forwarding no + AllowTcpForwarding no + ForceCommand internal-sftp + +Dans cet exemple le chemin /var/chroot sera utilisé comme racine lors +des connexions sftp. Ce répertoire doit être détenu par root:root et +avoir les droits 755. Cela veut dire que si notre utilisateur à pour +répertoire home /home/${user}, il se retrouvera dans +/var/chroot/home/${user} lors des connexions sftp. Il est nécessaire de +conserver le répertoire home de l'utilisateur pour que ssh accepte une +connexion par clef. En effet, lorsque l'utilisateur va se connecter, ssh +va lire dans son répertoire personnel pour lire le fichier +.ssh/know\_host et autoriser ou non la clef qui se présente. Ce qui +signifie que si l'on modifie le répertoire personnel, il faut aussi +déplacer cette arborescence (hors de question dans ce cas de mettre / +comme racine de l'utilisateur). À noter : j'ai préféré faire le match +sur le nom de l'utilisateur plutôt que sur son groupe (le groupe sera +utilisé par ailleurs). Dans le cas où nous avons plusieurs +utilisateurs, il est possible de les mettre à la suite (séparés par des +virgules). J'ai vu de nombreux tutoriaux qui indiquent comme répertoire +de chroot « /home/%u » (le répertoire de l'utilisateur standard), et +qui demandent de changer le répertoire de login de l'utilisateur par « / +». Je pense que c'est une très mauvaise idée : d'une part parce que cela +oblige à déposer les clefs à la racine du serveur, mais aussi à cause de +la contrainte d'openssh demandant à ce que le répertoire root soit +détenu par root : cela veut dire que l'utilisateur n'a pas le droit de +déposer de fichiers ou de créer de répertoires dans son propre home ! Le +plus simple est donc de prendre un autre répertoire pour l'échange, et +laisser le home de l'utilisateur pour la configuration. (Cela permet +aussi d'être sûr que le répertoire .ssh ne sera pas effacé par erreur +par l'utilisateur…) J'ai donc mis un lien symbolique pour lier le /home +de l'utilisateur avec son répertoire d'échange : + +.. code-block:: console + + # mkdir /home/${user}/echanges + # ln -s /var/chroot/home/${user} /home/${user}/echanges + +On retrouvera ainsi la possibilité de voir les fichiers déposés en +passant par le /home de l'utilisateur (même si ce dernier ne pourra pas +y aller…) + +Isoler l'environnement +~~~~~~~~~~~~~~~~~~~~~~ + +Maintenant que nous avons empêché l'utilisateur de se balader sur +l'ordinateur, nous allons l'empêcher de se balader dans les autres +répertoires des utilisateurs : cela se fait en une ligne de commande +(pour chacun des répertoires que nous allons ouvrir en sftp :) + +.. code-block:: console + + # for fichier in /var/chroot/home/* ; do chmod o-r ${fichier}; done + +Et voilà ! Les utilisateurs peuvent voir qu'il existe d'autres comptes +que le leur, mais ne peuvent pas y accéder. + +Autoriser le partage +~~~~~~~~~~~~~~~~~~~~ + +Maintenant que nous avons fermé les droits de manière générale il nous +reste à autoriser le partage des fichiers (après tout c'était le but de +la demande !) de manière plus fine. Cela implique pour moi deux choses : + +#. permettre à un autre utilisateur d'accéder aux données présentes +#. permettre à un autre utilisateur de déposer (ou de supprimer des + données) + +Pour le premier point, c'est facile il suffit d'ajouter l'utilisateur A +au groupe de l'utilisateur B : + +.. code-block:: console + + # usermod -a -G ${user} ${un_autre_utilisateur} + +Et l'utilsateur un\_autre\_utilisateur pourra donc accéder à l'ensemble +des fichiers pour les lire (et éventuellement les rapatrier chez lui). +Pour le second point (possibilité d'écrire et modifier) c'est un peu +plus compliqué; en gros nous voulons que les fichiers déposés par sftp +dans le répertoire de l'utilisateur ait comme groupe d'appartenance +celui du propriétaire du répertoire (quel que soit l'utilisateur qui +dépose) et qu'ils soient modifiable par le groupe (g+w) du +propriétaire. Par exemple : l'utilisateur A dépose un fichier dans le +répertoire d'échange de l'utilisateur B. Il faut que les droits de ce +fichier se présentent ainsi une fois le transfert terminé : + +.. code-block:: console + + $ ls -l fichier + -rw-rw---- 1 utilisateurA utilisateurB + +(ainsi l'un et l'autre pourront supprimer le fichier). Pour cela nous +allons utiliser une « bidouille » de l'os : le sgid bit. Derrière ce nom +barbare se trouve un marqueur qui permet de fixer le droit de tous les +fichiers qui seront créés dans le répertoire (plus d'info +`ici <http://en.wikipedia.org/wiki/Setuid>`_). Pour le déterminer on +passe par chmod : + +.. code-block:: console + + # chmod g+s /var/chroot/${user} + +|image2| + +Cela détermine bien quel est le groupe qui sera propriétaire du fichier, +mais cela ne donne pas à ce groupe le droit de le modifier pour autant ! +Sous linux, c'est la commande umask qui permet de déterminer les droits +des fichiers. Le problème est qu'il s'agit d'une commande liés à +l'environnement de l'utilisateur, et non pas aux répertoires sur +lesquels nous travaillons (à moins de passer par les ACLs mais cela est +déjà assez compliqué comme ça…). Ici, nous sommes dans un environnement +sftp, sans shell de login, donc sans possibilité d'exécuter la commande +directement, il faut que ce soit le serveur sftp qui le configure. J'ai +trouvé énormément de documentations (la plupart des bidouillages) pour +contourner le problème, mais la solution la plus simple vient de la +dernière version d'OpenSSH (5.4) sortie le 8 mars dernier. + + +Une nouvelle option sur le serveur sftp permet d'indiquer quel est +l'umask qui sera appliqué (dans notre cas 002) : dans le +fichier/etc/ssh/sshd\_config nous allons configurer les paramètres par +défaut du serveur sftp : Remplacer : + +:: + + Subsystem sftp /usr/lib/openssh/sftp-server.sh + +par : + +:: + + Subsystem sftp /usr/lib/openssh/sftp-server -u 002 + +Pour définir les droits umask qui seront appliqués par défaut pour +toutes les connexions sftp par défaut. Ce paramétrage est à redéfinir +pour les paramétrages personnalisés (bloc Match) : + +:: + + ForceCommand internal-sftp -u 002 + +Conclusion +~~~~~~~~~~ + +Nous avons un environnement bien hermétique, pouvant gérer +l'augmentation du nombre de compte (il suffit de refaire les chmod dans +notre environnement chrooté à la création du compte), et hermétique. Le +paramétrage côté serveur est effectivement assez lourd au début, mais je +pense que la mise à jour ne demande pas trop de travail, et on gère les +droits de manière assez fine (en passant par les groupes ce qui me +semble être dans la mentalité unix). Pour le client, il n'y a pas grand +chose à paramétrer (récupérer la clef et l'intégrer), et il n'y a +aucun risque que celui-ci vienne casser son paramétrage. On peut même +sauvegarder sa clef privée dans son home (le vrai), au cas où il +perdrait le fichier. + +.. |Création de la clef ssh avec puttygen| image:: {filename}../images/puttygen-300x276.jpg + :class: floatleft + + +.. |image1| image:: {filename}../images/filezilla-300x140.jpg + :class: floatright + +.. |image2| image:: {filename}../images/conf-300x175.jpg + :class: floatleft |