chroot pour limiter les commandes bash d’un utilisateur ssh (jails).

Un serveur dédié c’est bien mais ça coûte cher.
La plupart du temps, je propose à mes clients de l’hébergement mutualisé avec accès FTP, en général tout le monde connait et sait utiliser un client FTP mais les mises à jour avec ce protocole sont fastidieuses.

Heureusement, certains clients utilisent parfois de bons outils : les outils de gestion de version (svn, cvs …).
Voici un petit script que j’utilise pour donner un accès ssh à un utilisateur sur un serveur mutualisé en toute sécurité.
Il pourra ainsi se logguer sur la machine, effectuer les quelques commandes que je lui ai mis à
disposition (cd, cat, chmod, chown, cp, grep, gunzip, gzip mkdir, more, mv, rm, tar, svn et vi)
Avec ces commandes il peut mettre à jour son site tout seul (site de production ou de préproduction).
Afin qu’il ne puisse absolument pas voir les fichiers des autres clients, son compte est « emprisonné » dans ce qu’on appelle un chroot. Un utilisateur chrooté est un utilisateur auquel on a redéfini la racine (/). En plaçant la racine dans le répertoire de l’utilisateur, il ne peut pas voir les fichiers qui se trouvent au dessus.

Voici une image (horrible) mais qui symbolise très bien le fonctionnement:

(image provenant de sun.com)

Dans le nouveau répertoire racine, on recrée l’arborescence (soit à la main, soit avec un bootstrap par exemple le package debootstrap).

Notez que la création d’un chroot avec debootstrap permet d’avoir une distrib complète en quelques secondes. Ce qui est intéressant également avec cette méthode c’est qu’on peut installer des distributions complètement différentes de celle installée initialement.
Encore mieux que le debootstrap, les serveurs virtuels permettent une meilleur gestion de la partie matérielle.

Revenons à notre simple chroot, voici le script inspiré d’autres trouvés sur le net à droite à gauche datant de quelques années mais qui ne fonctionnaient pas, notamment la gestion des bibliothèques dynamique et des commandes à autoriser.

#!/bin/bash
if [ "$#" != 1 ];
then
  echo "Usage : $0 "
  exit 255;
fi

# list of available commands
cmd="/bin/bash /bin/cat /bin/chmod /bin/chown /bin/cp /bin/grep \
        /bin/gunzip /bin/gzip /bin/ls /bin/mkdir /bin/more /bin/mv /bin/rm /bin/tar \
        /usr/bin/svn /usr/bin/vi"

USER=$1
GROUP=chroot
groupadd "${GROUP}" > /dev/null 2>&1
useradd -c "JailsUser" -d "/home/chroot/${USER}/" -g "${GROUP}" -s "/bin/chroot" "${USER}"

echo "#!/bin/bash\nexec -c /usr/sbin/chroot /home/chroot/\$USER /bin/bash" > /bin/chroot
chmod 555 /bin/chroot

echo "User Password"
passwd "${USER}" > /dev/null

mkdir -p /home/chroot/${USER}/bin/ /home/chroot/${USER}/lib/ /home/chroot/${USER}/dev/
cd /home/chroot/
chmod -R 700 ${USER}

for i in $cmd
  do
    cp -R $i /home/chroot/${USER}/bin/
    # TODO : improve with a simple sed
    sudo ldd $i  | grep '/' | cut -d ">" -f2 \
      | cut -d "(" -f1  \
      | sed -e "s/[\t ]//g" \
      | sed -e "s/^/sudo cp /" \
      | sed -e "s/$/ \/home\/chroot\/${USER}\/lib\//" | bash
  done;
# for using /dev/null
mknod /home/chroot/${USER}/dev/null c 1 3 -m 666
chown -R "${USER}:${GROUP}" /home/chroot/${USER}
chmod u+s /usr/sbin/chroot
echo "User \"${USER}\" created and in jails !"