WebSiteChrootedStaticSftp

Histoire d'isoler un peu nos webmasteurices, on a décidé d'utiliser le patch chrootssh pour openssh. Ca a l'avantage de nous permettre de fournir un accés en sftp (only) aux users et de les isoler completement (cf Frangipane) et d'une facon plus joli et un peu plus secure que avec scponly.

Comme ca demande quand meme un boulot un peu spécifique (maintient d'un paquet debian openssh patché, compilation d'un sftp-server binaire statique, creation des users un peu spécifique,...), autant noter tout ca quelque part.

Généralités

Le patch se trouve sur la page du projet. Et y'a une documentation

C'est un patch tout bête mais qui ne sera pas intégré a openssh qui détecte si le home d'un user contient un "." et dans ce cas le met dans un chroot avant de lui laisser la main. Selon le shell qu'on lui donne (/bin/bash ou /usr/lib/openssh/sftp-server) on peut soit lui donner un accés ssh, soit un accés en sftp.

Maintient du paquet openssh patché

Ben c'est simple comme faire un paquet debian a partir de ses sources. Avec une ou deux petites nuances, notamment qu'il faut adapter debian/rules pour qu'il utilise dpatch.

  • On recupère les sources du paquet:

    apt-get source openssh-server

  • On recupère la version a peu pres correspondante du patch chrootssh ici

  • C'est un .diff, histoire de respecter un peu le debian way, on en fait un dpatch pour qu'il soit appliqué/desappliqué automatiquement a la construction du paquet. Les patchs debian se mettent dans le repertoire debian/patches du paquet source Ca se fait en quelques lignes de commande:

    mkdir openssh-$version/debian/patches dpatch patch-template -p "10_chrootssh" \ "Ici on met le descriptif du patch" \ < le_fichier.diff \ > openssh-$version/debian/patches/10_chrootssh.dpatch echo 10_chrootssh.dpatch >> openssh-$version/debian/patches/00list

  • Pas hesiter a editer 10_chrootssh.dpatch pour verifier que tout est bon (email de l'auteur du dpatch, blabla)

  • Le paquet debian de openssh a pas de patch (en tout cas pas a l'heure de la redaction de cette pasge). Pour que dpatch soit utilise a la compilation, faut modifier un peu debian/rules comme on peut le voire sur ce diff:

    --- tmpssh/openssh-4.3p2/debian/rules 2007-03-01 14:20:20.000000000 +0100 +++ chrootssh/openssh-4.3p2/debian/rules 2007-03-01 14:19:11.468303296 +0100 @@ -6,6 +6,8 @@ # This has to be exported to make some magic below work. export DH_OPTIONS

    +include /usr/share/dpatch/dpatch.make + ifeq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) OPTFLAGS := -O2 else @@ -59,8 +61,7 @@

    build: build-deb build-udeb

    -build-deb: build-deb-stamp -build-deb-stamp: +build-deb: patch-stamp dh_testdir mkdir -p build-deb cd build-deb && $(FORCE_LIBS) ../configure --prefix=/usr --sysconfdir=/etc/ssh --libexecdir=/usr/lib/openssh --mandir=/usr/share/man --with-tcp-wrappers --with-xauth=/usr/bin/X11/xauth --with-default-path=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11 --with-pam --with-4in6 --with-privsep-path=/var/run/sshd --without-rand-helper --with-libedit --with-kerberos5=/usr $(SELINUX) @@ -80,10 +81,7 @@ $(MAKE) -C contrib gnome-ssh-askpass1 CC='gcc $(OPTFLAGS) -g -Wall'; \ fi

    - touch build-deb-stamp

    -build-udeb: build-udeb-stamp -build-udeb-stamp: +build-udeb: patch-stamp dh_testdir mkdir -p build-udeb cd build-udeb && $(FORCE_LIBS) ../configure --prefix=/usr --sysconfdir=/etc/ssh --libexecdi r=/usr/lib/openssh --without-xauth --with-default-path=/usr/local/bin:/usr/bin:/bin --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin --with-4in6 --with-privsep-path=/var/run/sshd --without-rand-helper @@ -93,11 +91,9 @@ perl -pi -e 's/ +-lnsl//' build-udeb/config.status cd build-udeb && ./config.status $(MAKE) -C build-udeb -j 2 ASKPASS_PROGRAM='/usr/bin/ssh-askpass' CFLAGS='-Os -g -Wall -Wpo inter-arith -Wuninitialized -Wsign-compare -Wno-pointer-sign -std=gnu99 -DSSH_EXTRAVERSION="\" $(SSH_EXTRAVERSION)\""' ssh scp sftp sshd ssh-keygen - touch build-udeb-stamp

    -clean: +clean: unpatch dh_testdir

    •   rm -f build-deb-stamp build-udeb-stamp
        rm -rf build-deb build-udeb
        -$(MAKE) -C contrib clean
        rm -f config.log
      
  • Editer debian/changelog pour ajouter son entrée et décrire ce qu'on a fait. Bien renseigner la version en ajoutant "+chrootssh". C'est a partir de ça que dpkg-dev crée la version du paquet. Bien faire attention a conserver le même formatage, sinon il y aura des erreurs a la création du paquet (2 espaces devant chaque *, 2 espaces entre l'email de l'auteur et la date, generée a partir de "date -R",...). Exemple:

    openssh (1:4.3p2-8+chrootssh) unstable; urgency=medium

    * NMU
    * Added chrootssh patch (debian/patches/10_chrootssh)
    * Corrected debian/rules to use dpatch
    

    -- bertagaz bertagaz@ptitcanardnoir.org Mon, 26 Feb 2007 22:22:53 +0100

  • Ben voila, c'est ptret pour la compilation. Se mettre dans la racine de la source du paquet et lancer un petit "dpkg-buildpackage -rfakeroot -us -uc" et attendre la fin :]

sftp-server

Histoire de pas avoir a ajouter 30 fichiers et bibliothèques dans la chroot et les mettre a jour a chaque fois, on s'est dit qu'avoir un sftp-server compilé de manière statique ce serait plus sympa. Comme ca le code des bibliothèque dont il a besoin, il l'ajoute dans son binaire et a pas besoin d'aller le chercher dans un autre fichier a chaque fois. Moins de fichiers, moins de prise de tête.

Tout ça c'est bien joli, mais un binaire statique, ça peut être gros pour le coup, s'il doit inclure tout un tas de trucs de différentes bibliothèques. Notamment parce que par exemple la libc6, son code c'est pas un exemple de concision.

En général on utilise une autre libc pour faire ce genre de manip, des plus petites comme la dietlibc ou la uclibc qui sont utilisées pour les systêmes embarqués notamment. La différence est assez flagrante, un sftp-server compilé sur la libc6 fait a peu près 775ko, sur la uclibc, 193Ko...

Uclibc et buildroot/rootfs

Pour pouvoir compile un binaire a partir de la uclibc, on utilise buildroot, qui crée une image d'un système de fichier contenant un linux, ses toolchains et autres bibliotheques basées sur la uclibc. Pour faire ça, y'a toutes les infos dispos dans la doc de buildroot.

A la configuration (make menuconfig), il faut ajouter quelques packages au choix par defaut, notamment grep, make, patch, openssl et zlib... Sur le système ou vous construisez l'image, vous avez besoin des paquets autoconf et texinfo ou vous aurez des erreurs.

Une fois le fichier rootfs construit, il vous faudra sans doute augmenter un peu la taille de son système de fichier pour pouvoir y mettre les sources de openssh (avec resize2fs). Il suffit ensuite de le monter (mount -o loop rootfs.i686.ext2 rootfs), monter /tmp dedans (mount -o bind /tmp rootfs/tmp) et eventuellement /proc de la même façon.

Compilation du sftp-server

Autant utiliser les mêmes sources que pour le pasuet openssh qu'on a fait plus haut.

  • Entrez dans le système de fichier que vous venez de monter, et téléchargez les sources d'openssh:

    mkdir rootfs/home/default/openssh cd rootfs/home/default/openssh apt-get source openssh-server

  • Placez vous dans le systeme de fichier façon chroot afin d'avoir l'environnement de la uclibc:

    chroot rootfs/ /bin/su -

  • Allez dans les sources d'openssh et lancez la configuration et la compilation avec ces options:

    ./configure --with-ldflags="-static" \ --prefix=/usr \ --sysconfdir=/etc/ssh \ --libexecdir=/usr/lib/openssh \ --mandir=/usr/share/man \ --without-tcp-wrappers \ --without-x \ --without-xauth \ --with-default-path=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games \ --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11 \ --without-pam \ --with-4in6 \ --with-privsep-path=/var/run/sshd \ --without-rand-helper \ --without-libedit \ --without-kerberos5 \ --without-selinux

    make -j 2 CFLAGS="-O2 -Os" \ -g -Wall -Wpointer-arith \ -Wuninitialized \ -Wsign-compare \ -Wno-pointer-sign \ -std=gnu99 \ -DLOGIN_PROGRAM=\"/bin/login\" \ -DLOGIN_NO_ENDOPT \ -DSSHD_PAM_SERVICE=\"ssh\" \ sftp-server

Vous devriez avoir obtenu un binaire sftp-server statique ("ldd sftp-server" pour vérifier) et pas trop gros

Mise en place de la chroot

Avec ce sftp-server statique, la chroot est plutot minimale et nécessite peu de fichiers. Mais malgrès tout, ssh utilise nss et pam, on a donc besoin de quelques fichiers dans le repertoire /etc de la chroot, qu'on peut juste copier du système de base. En tout la chroot contient:

/chroot:
dev/ etc/ home/ usr/

/chroot/dev:
zero null random urandom ...

/chroot/etc:
default/  environment  nsswitch.conf  pam.d/  passwd  security/

/chroot/etc/default:
locale

/chroot/etc/pam.d:
common-account  common-auth  common-session  ssh

/chroot/etc/security:
limits.conf  pam_env.conf

/chroot/home:
user1/ user2/ user3 ...

/chroot/usr:
lib/

/chroot/usr/lib:
openssh/

/chroot/usr/lib/openssh:
sftp-server

Pour que sftp-server fonctionne, il faut un minimum de de choses dans dev; notamment /dev/zero, /dev/null, /dev/random On obtient le necessaire facilement avec MAKEDEV, en lançant

cd dev/
MAKEDEV zero
MAKEDEV null
MAKEDEV pty

Gestion des users

Lors de l'ajout d'utilsateurices qui devront être placéEs dans la chroot, il faut faire attention à deux choses: que leur shell soit /usr/lib/openssh/sftp-server pour qu'illes ne puissent se connecter qu'en sftp, et que leur home contienne un "." pour que openssh sache qu'il doit les chrooter. Ca donne une ligne dans /etc/passwd dans le genre, si la chroot est dans /chroot:

test:x:10000:10000::/chroot/./home/test/:/usr/lib/openssh/sftp-server

Ca se fait facile en passant les options "--shell /ur/lib/openssh/sftp-server" et "--homedir /chroot/./home/$user" à adduser lors de la création du compte.

Il faut recopier la ligne correspondante a l'utilisateurice dans le etc/passwd de la chroot.