summaryrefslogtreecommitdiff
path: root/content/Informatique/chroot.rst
blob: d126d9948ccc5f474ad918fb69d966ab9df8e8fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
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|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