Navigation überspringen

SSH in einer chroot Umgebung benutzen

Überblick

Dieses Dokument beschreibt das Aufsetzen eines Servers mit chroot (Change Root) Accounts, wobei es den Benutzern gestattet sein soll, per ssh, scp und sftp auf den Server zuzugreifen. Dies ist nicht ganz so trivial, wie es zunächst vielleicht erscheinen mag.

Das hier beschriebene Setup wurde mit Linux 2.2.x, 2.4.x, 2.6.x und allen OpenSSH Versionen zwischen 3.1p1 und 5.5p1 erfolgreich getestet. Ältere Versionen von OpenSSH sollten aufgrund diverser Sicherheitslöcher nicht verwendet werden.

Dieses Setup sollte ebenfalls mit AIX 4.3.3 (getestet) und 5.1 (getestet) sowie OpenSSH 3.4 oder höher funktionieren. Allerdings muß dann der für AIX angepaßte Patch verwendet werden (Dank an Akos Domjan <a_domjan@hotmail.com>).

Seit Version 4.9 bietet OpenSSH selbst chroot-Unterstützung an. Diese habe ich jedoch nie selbst ausprobiert. Weitere Hinweise finden sich auf der sshd_config Man Page.

Aufsetzen der chroot Umgebung

Zunächst sollte man ein prototypisches Home-Verzeichnis für die chroot Accounts aufsetzen. Dieses Verzeichnis muß die für die chroot Accounts notwendigen Dateien enthalten. Typischerweise ist dies ein bin Verzeichnis mit einer statisch compilierten Shell und evtl. notwendigen Tools (GNU Filetools u.ä.). Außerdem wird höchstwahrscheinlich ein lib Verzeichnis benötigt, das einige grundlegenden Libraries enthält (libc u.a.).

Hat man alles beisammen, kann man ein chroot in das Verzeichnis machen und testen, ob alles wie gewünscht funktioniert. Um herauszufinden, welche Libs von einem Programm gebraucht werden, sind ldd und strace hilfreich.

Anlegen der User Accounts

Nun kann man damit beginnen, die eigentlichen User Accounts einzurichten. Um dies zu vereinfachen, kann man sich ein entsprechendes Shell Script basteln. Folgendes muß getan werden:

  • Erstellen der notwendigen Verzeichnisse unterhalb der Home-Verzeichnisse der Benutzer, z.B.:
mkdir -m 755 $HOME/bin
mkdir -m 755 $HOME/lib
# ...
  • Erstellen des /dev Verzeichnisses und notwendiger Devices, z.B.:
mkdir -m 755 $HOME/dev
mknod $HOME/dev/null c 1 3 -m 666
# ...
  • Erstellen des /etc Verzeichnisses und Anpassung der Einträge in passwd und group, z.B.:
mkdir -m 755 $HOME/etc
echo "root:x:0:0:root:/root:*" > $HOME/etc/passwd
echo "user:x:500:500:A Chroot User:/home/user:/bin/bash" >> $HOME/etc/passwd
echo "root:x:0:root" > $HOME/etc/group
echo "usergroup::500:" >> $HOME/etc/group
chmod 444 $HOME/etc/passwd $HOME/etc/group
  • Anlegen von Hardlinks. Durch „hardlinken“ der Dateien im prototypischen Verzeichnis in die entsprechenden Home-Verzeichnisse spart man sich Plattenplatz.
ln /home/typical/bin/* $HOME/bin/
ln /home/typical/lib/* $HOME/lib/
# ...

Installation von OpenSSH (systemweit)

Bevor man OpenSSH compiliert, sollte man einen chroot Patch anwenden. chroot Patches sind im Netz mehrere zu finden, aber der folgende hat bei mir mit OpenSSH 3.1p1 - 5.5p1 funktioniert (allerdings nicht mit AIX; s.u.):

--- session.c.orig    2009-01-28 06:29:49.000000000 +0100
+++ session.c 2009-02-23 09:01:33.000000000 +0100
@@ -261,6 +261,11 @@
      }
 }
 
+/* CHROOT patch start */
+char *user_dir;
+char *new_root;
+/* CHROOT patch end */
+
 void
 do_authenticated(Authctxt *authctxt)
 {
@@ -1496,6 +1501,27 @@
 
              if (setlogin(pw->pw_name) < 0)
                      error("setlogin failed: %s", strerror(errno));
+                /* CHROOT patch start */
+                user_dir = xstrdup(pw->pw_dir);
+                new_root = user_dir + 1;
+                
+                while((new_root = strchr(new_root, '.')) != NULL) {
+                  new_root--;
+                  if(strncmp(new_root, "/./", 3) == 0) {
+                    *new_root = '\0';
+                    new_root += 2;
+                                             debug("chrooting to user directory %s", user_dir);
+                                                if(chroot(user_dir) != 0)
+                                                  fatal("Couldn't chroot to user directory %s", user_dir);
+                                                pw->pw_dir = new_root;
+                                                if (chdir("/") < 0)
+                                                  fatal("Couldn't cd to / after chroot to user directory %s: %s", 
+                                                        user_dir, strerror(errno));
+                                                break;
+                  }
+                  new_root += 2;
+                }
+                /* CHROOT patch end */
              if (setgid(pw->pw_gid) < 0) {
                      perror("setgid");
                      exit(1);

Ein entsprechendes diff File gibt es hier. (Ältere Versionen dieses Patchs mit anderen Offsets sind ebenfalls verfügbar: diff für OpenSSH 3.x, diff für OpenSSH 3.1, diff für OpenSSH 4.x.)

Hinweis: Damit der obige Patch funktioniert, darf OpenSSH nicht statisch compiliert werden. (Dank an Oliver Gorzellik für den Hinweis.)

Da dieser Patch jedoch nicht auf AIX-Systemen funktioniert (hier gibt es Rechte-Probleme beim Aufruf der chroot() Funktion), sollten Benutzer solcher Systeme den Patch für AIX verwenden, der freundlicherweise von Akos Domjan <a_domjan@hotmail.com> zur Verfügung gestellt wurde.

Nun kann OpenSSH wunschgemäß konfiguriert und mit make; make install compiliert und installiert werden.

Installation von OpenSSH (chroot Umgebung)

Um OpenSSH für die chroot Accounts verfügbar zu machen, kopiert man ssh, scp, sftp und sftp-server in das prototypische Home-Verzeichnis und erstellt die entsprechenden Hardlinks für die Benutzerverzeichnisse. Die OpenSSH Dateien müssen innerhalb der chroot Umgebung an exakt den Punkten zu finden sein, die bei der systemweiten Installation vorgegeben wurden. Wurde OpenSSH systemweit nach /usr/local installiert sollte man die entsprechenden Symlinks anlegen:

mkdir -p -m 755 $HOME/usr/local/bin
cd $HOME/usr/local/bin
ln -s ../../bin/ssh .
ln -s ../../bin/scp .
ln -s ../../bin/sftp .

mkdir -p -m 755 $HOME/usr/local/libexec
cd $HOME/usr/local/libexec
ln -s ../../bin/sftp-server .

Noch einmal: OpenSSH darf nicht statisch compiliert werden.

Damit OpenSSH ein chroot durchführt, muß ein „magic token“ in /etc/passwd gefunden werden (dies mag von anderen Servern bekannt sein). Daher muß das Home-Verzeichnis Feld in /etc/passwd für die entsprechenden Benutzer angepaßt werden:

# alt ->  :$HOME:
# neu ->  :$HOME/./:

# z.B.
# :/home/user: ->  :/home/user/./:

Nun sollte ein ssh, scp oder sftp zum Server funktionieren. ssh, scp oder sftp vom Server funktionieren, wenn innerhalb der chroot Umgebung der entsprechende Hostname aufgelöst werden kann (oder man IP-Nummern verwendet).

Schlußbemerkungen

X11-Forwarding ist mit diesem Setup (noch) nicht möglich. Eventuell sollten die Benutzer ssh mit der Option -x aufrufen. Da ich diese Funktionalität nicht brauche, habe ich mich darum nicht gekümmert.

Außerdem ist es u.U. notwendig, daß die entsprechenden Benutzer ein Update ihrer lokalen SSH-Installation machen. Schwierigkeiten gab es meiner Erfahrung nach mit OpenSSH-Versionen vor 2.5.2.

Weiterhin sollte man beachten, daß dieses Setup ein chroot nur für SSH Connects durchführt. Andere Dienste müssen also abgeschaltet oder gesondert konfiguriert werden. Auf Telnet etwa sollte gänzlich verzichtet werden. Geht dies nicht (warum?) kann man für Telnet Logins changeroot verwenden, das mit dem chroot Patch von OpenSSH gut zusammenarbeitet. FTP kann dank scp und sftp auch abgeschaltet werden. Hier bieten viele Server aber auch eine chroot Funktionalität an, die i.d.R. auch dokumentiert ist.

Soll SSH für Microsoft Windows™ Benutzer zur Verfügung gestellt werden, mag ein Blick auf http://support.zeitform.info/serverzugang/ssh.html interessant sein. Hier wird beispielhaft die Einrichtung beschrieben.

Schließlich stehe ich natürlich für Fragen, Kommentare, Anregungen oder Erfahrungen gerne zur Verfügung. Meine E-Mail Adresse findet sich am Ende der Seite.

Autor: Ulf Stegemann

Datum: 2010-04-27 16:10:11

HTML generated by org-mode 6.35trans in emacs 23

Valid XHTML 1.0 strict! Valid CSS! Org-Mode Gehostet von zeitform Internet Dienste. [FSF Associate Member]