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.