Puffy

SSH in Chroot

Ab OpenBSD 4.3 besitzt OpenSSH die neue Funktion ChrootDirectory. Dies ist eine von vielen (auch mir) lange gewünschte Funktion, die das aufsetzen einer Chroot-Umgebung für SSH beträchtlich vereinfacht. Bislang war ein Chroot-SSH nur sehr umständlich zu konfigurieren. Wie setzt man diese neue Funktion ein?

Nur SFTP Zugriff

Möchte man für seine Benutzer nur SFTP Zugriff ist die Einrichtung sogar besonders einfach.

In der /etc/ssh/sshd_config muß der Parameter bei Subsystem sftp auf internal-sftp umgestellt werden:

Subsystem       sftp    internal-sftp

Danach kann man Benutzern oder Benutzergruppen ein Chroot-Verzeichnis zuweisen. Dies geht am besten mit der Match-Direktive von sshd:

Match Group sftpuser
        ChrootDirectory /home
	ForceCommand internal-sftp
        AllowTCPForwarding no

In diesem Fall muß natürlich erst die Gruppe sftpuser existieren. Dann wird jeder User der Gruppe sftpuser das Verzeichnis /home, als sein /-Verzeichnis sehen. Das ChrootDirectory muß übrigens immer ein Verzeichnis sein, das root gehört und nicht schreibbar für normale User ist. Das heißt das typischerweise nicht direkt das Heimatverzeichnis eines Users sein ChrootDirectory ist, sondern ein Verzeichnis darüber

Zusätzlich kann man noch, damit der Pfad zum Heimatverzeichnis aufgelöst werden kann einen symbolischen Link setzen:

cd /home
ln -s . home

Shell-User

Falls Benutzer nicht nur sftp benutzen können sollen, sondern auch direkt auf der Shell arbeiten können sollen, ist noch etwas zusätzliche Konfiguration notwendig. Das ForceCommand internal-sftp von oben muß hingegen entfernt werden, damit auch andere Befehle funktionieren.

Damit eine Shell benutzt werden kann, muß natürlich eine solche innerhalb des ChrootDirectory vorhanden sein. Außerdem werden auch noch ein paar Gerätedateien unter /dev benötigt. Daher müssen innerhalb des ChrootDirectory die Verzeichnisse dev und bin angelegt werden:

cd /home
mkdir bin dev

Nun müssen die benötigten Gerätedateien angelegt werden. Dabei darf außerdem das ChrootDirectory nicht in einem Verzeichnis liegen welches mit der Option nodev gemountet wurde. An Gerätedateien werden arandom, null, zero, stdin, stderr, stdout und tty benötigt:

Gerätedateien auf der Partition aktivieren:

mount -u -o dev /home

Diese Änderung dauerhaft machen (entfernen der nodev-Option in der /etc/fstab):

vi /etc/fstab

Weiter auf der Shell:

cd /home/dev
mknod -m 644 arandom c 45 4
mknod -m 666 null c 2 2
mknod -m 666 zero c 2 12
mknod -m 666 stderr c 22 2
mknod -m 666 stdin c 22 0
mknod -m 666 stdout c 22 1
mknod -m 666 tty c 1 0

Nun muß man noch die Shell und weitere benötigte Programme aus /bin ins ChrootDirectory kopieren. Dabei muß man unter OpenBSD keine Abhängigkeiten berücksichtigen, da alle Programme die in /bin liegen unter OpenBSD statisch kompiliert wurden:

cd /home/bin
cp -p /bin/ksh .
cp -p /bin/cp .
cp -p /bin/ls .
cp -p /bin/mkdir .
cp -p /bin/mv .
cp -p /bin/rm .
cp -p /bin/rmdir .
cp -p /bin/sleep .
cp -p /bin/test .
cp -p /bin/tar .
ln tar cpio
ln tar pax
ln ksh sh
ln ksh rksh
ln test [

Da man meistens mit dieser geringen Grundausstattung nicht auskommen wird, wird man weitere Programme aus /usr/bin benötigen. Diese können Abhängigkeiten zu Libraries aus /usr/lib haben, die man mit dem Tool ldd prüfen kann und die dann ebenfalls kopiert werden müssen. Es kann auch sein, das manche Programme weitere Verzeichnisse und/oder Dateien benötigen wie etwa in /usr/share oder Verzeichnisse unterhalb von /var oder das tmp-Verzeichnis. Dies muß dann im Einzelfall geprüft werden. Hier erst mal ein einfaches Beispiel:

cd /home
mkdir -p usr/bin
mkdir usr/lib
mkdir usr/libexec
ldd /usr/bin/env
cp -p /usr/bin/env usr/bin
cp -p /usr/lib/libc.so.43.0 usr/lib
cp -p /usr/libexec/ld.so usr/libexec
ldd /usr/bin/grep
cp -p /usr/bin/grep usr/bin
cp -p /usr/lib/libz.so.4.1 usr/lib
cd usr/bin
ln grep egrep
ln grep fgrep
ln grep zgrep
ln grep zegrep
ln grep zfgrep

Etwas komplizierter gestaltet sich der vi-Editor. Dieser benötigt noch temporäre Verzeichnisse und die Terminal Datenbank /etc/termcap:

cd /home
ldd /usr/bin/vi
cp -p /usr/bin/vi usr/bin
cp -p /usr/lib/libcurses.so.10.0 usr/lib
cd usr/bin
ln vi ex
ln vi view
cd ../..
mkdir etc var
cp -p /etc/termcap etc
mkdir -m 1777 tmp
mkdir -m 1777 var/tmp

Wer außerdem möchte das mit dem ls Befehl korrekte Usernamen und Gruppen angezeigt werden kann auch noch die beiden Dateien /etc/group und /etc/pwd.db ins ChrootDirectory kopieren. Diese enthalten keine Passwörter:

cd /home
cp -p /etc/group etc
cp -p /etc/pwd.db etc

Wenn sich die SSH-User nicht gegenseitig in Ihre Heimatverzeichnisse blicken lassen sollen, müssen noch die Rechte auf die Heimatverzeichnisse selbst korrigiert werden:

cd /home
chmod 700 username

Auf einem Webserver könnte das auch so aussehen (falls /var/www/users statt wie vorher beschrieben /home benutzt wurde):

cd /var/www/users
chgrp www username
chmod 710 username

Creative Commons Attribution 2.0 Germany License
Copyright (c) René Maroufi, 2007