Aus Linux-Magazin 01/2003

Virtuelle Serverkontexte in der Praxis

Mehrere Linux-Systeme nebeneinander auf einem Computer: Virtuelle Serverkontexte bieten diese Sicherheit stiftende Trennung ohne den Overhead von Emulatoren. Selbst Root kann aus seinem kleinen Königreich nicht ausbrechen.

Sicherheit durch den Sandkasten: Das mit Java bekannt gewordene Konzept funktioniert unter Linux auch für Serverprozesse. Besonders beim Hosten mehrerer Webauftritte mit aktiven Inhalten (Server-Side Scripting) möchten sicherheitsbewusste Admins ihre Klientel voneinander trennen. Auch ganz normale Server sind in einer gekapselten Umgebung so gut aufgehoben, dass ein erfolgreicher Crackangriff nur Teile des Systems in Mitleidenschaft zieht.

Virtuelle Serverkontexte (VServer,[1]) bieten genau diesen Schutz. Sie führen Programme in einer abgeschotteten Umgebung aus, die die Auswirkungen eines erfolgreichen Angriffs eingrenzt. Die Idee ist so alt wie Unix selbst: Die einfachste Variante ist, einen eigenen Benutzer für jeden Dienst einzurichten. Die Unix-Zugriffsrechte verhindern, dass ein Eindringling Dateien anderer Benutzer verändert oder auch nur liest. Einen Schritt weiter gehen Change-Root-Umgebungen (»chroot«), sie setzen das Wurzelverzeichnis für einen Prozess auf ein Unterverzeichnis. Dieser Prozess ist im Verzeichnisbaum gefangen und sieht keine Dateien außerhalb.

Bei beiden Varianten bleiben dem Angreifer die Prozesse der anderen User verborgen. Erhält er jedoch Root-Rechte, kann er aus dem »chroot«-Käfig ausbrechen, beliebige Dateien modifizieren oder sonstigen Schaden anrichten.

Diese Probleme sind bei Emulatoren nicht vorhanden. Die einfachste Variante dieser Gattung ist der User-Mode-Kernel[2]: Der zusätzliche Kernel läuft als virtuelle Maschine und verhält sich aus Sicht des echten Kernels wie eine Anwendung. Prozesse, die unter dem User-Mode-Kernel laufen, haben keinen Zugriff auf das umgebende Linux-System. Einen Schritt weiter gehen VMWare[3] oder die LGPL-lizenzierte Alternative Plex86[4], sie emulieren die komplette Peripherie eines PCs inklusive Festplatte, Netzwerk- und Grafikkarte.

Emulatoren als Alternative

Mit Emulatoren lässt sich die gleiche Installation auf unterschiedlicher Hardware einsetzen, etwa SCSI auf IDE und umgekehrt. Auf diesen virtuellen PC kann man fast beliebig Betriebssysteme und Anwendungen installieren. Da Emulatoren einen eigenen Speicherbereich sowie virtuelle Festplatten in Form von Dateien auf dem Hostsystem benötigen, ist es unmöglich, aus dem virtuellen System auszubrechen. Selbst wenn ein Angreifer einen Root-Zugang erlangt, ist das Basissystem vor ihm geschützt. Den Computer kann er nur durch CPU-, Festplatten- oder Netzwerklast stören.

Noch weiter gehen Systeme wie Bochs[5] (LGPL-Lizenz), die zusätzlich zur Peripherie auch den Prozessor emulieren. Damit fungiert beispielsweise ein Macintosh-Rechner als PC mit Athlon-Prozessor. Allerdings kostet das Emulieren viel Rechenleistung, die virtuelle Ausführungsgeschwindigkeit liegt im Bereich von wenigen MHz. Für praktische Anwendungen ist dieser Ansatz daher kaum geeignet.

Zudem belegen User-Mode-Linux und die Emulatoren sehr viel RAM, da jede virtuelle Maschine einen eigenen Kernel inklusive Puffer, Cache und freiem Speicher benötigt. Hinzu kommen noch die im Emulator laufenden Prozesse. Die Maschinen können keine dieser Ressourcen gemeinsam nutzen, sie benötigen auch jeweils den Festplattenplatz für ein komplettes Linux-System.

Listing 1: Pakete
installieren

01 #!/bin/bash
02 TARGETDIR=/vserver/suse
03 TMPDIR=/tmp/rpmdir
04 PKGLIST=/tmp/paketliste
05 SRCDIR=/media/dvd
06 ARCH=i586
07 
08 rm -rf $TMPDIR
09 mkdir -p $TMPDIR
10 cd $TMPDIR
11 for pkg in `cat $PKGLIST` ; do
12     for rpm in $SRCDIR/suse/${ARCH}/${pkg}-[0-9]*.rpm ; do
13         test -f ${rpm} && ln -s ${rpm} .
14     done
15     for rpm in $SRCDIR/suse/noarch/${pkg}-[0-9]*.rpm ; do
16         test -f ${rpm} && ln -s ${rpm} .
17     done
18 done
19 test -d $TARGETDIR || mkdir -p $TARGETDIR
20 mkdir -p $TARGETDIR/etc
21 mkdir -p $TARGETDIR/var/lib/rpm
22 cp /etc/passwd /etc/shadow /etc/group* $TARGETDIR/etc
23 rpm --root=$TARGETDIR --initdb
24 rpm --root=$TARGETDIR -hiv *.rpm

Viele Könige neben mir

Virtuelle Serverkontexte sind ein eleganter Zwischenweg. Es handelt sich dabei um Change-Root-Käfige mit wichtigen Zusätzen. Seit den 2.2er Kerneln können Root-Prozesse Teile ihrer Sonderrechte abgeben, die so genannten Capabilities. Capabilities sind zum Beispiel die Rechte, einen Port zu binden, die Uhrzeit zu ändern oder beliebige Prozesse zu beenden, weitere Beispiele zeigt Tabelle 1. Ohne die Capabilities darf ein Prozess keine dieser Aufgaben mehr ausführen. Informationen dazu finden sich in den Kernelquellen in der Datei »include/ linux/capability.h«.

Die Kombination aus reduzierten Capabilities und Change-Root-Umgebung ergibt ein recht sicheres Subsystem, in dem ein Eindringling mit (reduzierten) Root-Rechten nur wenig Unsinn anstellen kann. Der Angreifer sieht aber noch alle Prozesse auf der Maschine, auch jene, die außerhalb seiner Umgebung laufen. Das ändert VServer durch ein Kernel-Patch, das so genannte Kontexte einführt. Jeder Kontext kapselt seine eigenen Prozesse. Das verhindert, dass ein Angreifer andere Prozesse des Hostsystems stört. Trotzdem laufen alle Kontexte mit dem gleichen Kernel und benutzen das gleiche RAM, den gleichen Cache und die gleiche Festplatte.

Der Overhead dieses Verfahrens ist recht gering, ein Rechner kann bei gleicher Leistung deutlich mehr virtuelle Server ausführen, als dies mit Emulatoren möglich wäre. Für ganz Knauserige gibt es ein Skript, das die einzelnen Kontexte vergleicht und identische Dateien (bis auf Konfigurationsdateien) durch Hardlinks ersetzt. Egal wie viele Kontexte laufen, der Platz für identische Files ist nur einmal nötig.

Tabelle 1: Einige Capabilities

Tabelle 1: Einige Capabilities

Kleines Patch mit großer Wirkung

Das VServer-Konzept baut auf vorhandener Funktionalität auf, entsprechend klein ist das Kernel-Patch[6]: Gerade mal 82 KByte bringt es auf die Waage, und zwar unkomprimiert. Hinzu kommen die Verwaltungsprogramme, wahlweise als RPM oder Quellcode-Archiv (».tar.gz«). Ist der Kernel gepatcht und gestartet, kann der Admin loslegen. Für jeden Serverkontext muss er ein Unterverzeichnis unter »/vservers« anlegen und dort eine Linux-Distribution installieren (siehe Kasten “Distributionen minimieren”). Am schnellsten geht das, wenn er ein fertig installiertes Linux-System ins Unterverzeichnis kopiert.

Jeder Serverkontext benötigt eine eigene Konfigurationsdatei »/etc/vservers/ Servername.conf«. Eine Vorlage findet sich unter »/usr/lib/vserver/sample.conf«, in dieser muss der Admin mindestens die IP-Adresse des virtuellen Servers eintragen. Ein Beispiel ist in Listing 2 zu sehen, Tabelle 2 gibt einen Überblick über die Optionen. Gestartet wird der Serverkontext mit »vserver Servername start«. Da im Beispiel noch kein SSH-Daemon läuft, führt nur »vserver Servername enter« in den Kontext hinein (siehe Abbildung 1). Der Weg heraus führt wie bei jeder Shell über »exit«.

Innerhalb des Kontexts sind keine Prozesse des Gastgebers sichtbar. Um nur einen einzelnen Befehl ausführen, braucht man nicht unbedingt in den virtuellen Server zu wechseln, sondern kann dies mit »vserver Servername exec Befehl« erreichen. Beendet wird der Kontext mit »vserver Servername stop«. Informationen über alle laufenden Kontexte liefert das Kommando »vserver-stat«, siehe Abbildung 2.

Befinden sich auf einem Gastgebersystem viele ähnliche Installationen, kann man Festplattenplatz sparen: Hardlinks ersetzen mehrfach vorhandene Files durch eine einzelne Kopie. Allerdings darf kein Serverkontext in diese Dateien schreiben, da die Änderung für alle Kontexte gilt. Deshalb wird auf den Hardlinks das »immutable«-Flag gesetzt.

Listing 2:
Beispielkonfiguration

01 # /etc/vserver/meinserver.conf
02 IPROOT=192.168.0.1
03 IPROOTDEV=eth0
04 S_HOSTNAME=meinserver.domain.de
05 S_FLAGS="lock nproc"
06 ULIMIT="-H -u 1000"
07 S_CAPS="CAP_NET_RAW"
Abbildung 1: Mit dem Kommando »vserver meinserver enter« betritt der Admin den Serverkontext. Von dort aus sind nur noch die Prozesse dieses Kontexts zu sehen.

Abbildung 1: Mit dem Kommando »vserver meinserver enter« betritt der Admin den Serverkontext. Von dort aus sind nur noch die Prozesse dieses Kontexts zu sehen.

Tabelle 2: Optionen

Tabelle 2: Optionen

Abbildung 2: Einen Überblick über den Status aller aktiven VServer gibt das Kommando »vserver-stat«.

Abbildung 2: Einen Überblick über den Status aller aktiven VServer gibt das Kommando »vserver-stat«.

Nicht veränderlich?

Das Immutable-Bit verhindert, dass ein Benutzer – und in den Kontexten auch Root – die Datei verändert. Es verhindert allerdings auch, dass die Datei gelöscht wird, womit Updates unmöglich sind. Daher führt VServer das Immutable-linkage-invert-Bit ein. Ist es zusammen mit dem Immutable-Flag gesetzt, dann lässt sich die Datei (der Hardlink) löschen, aber nicht modifizieren. Freundlicherweise arbeiten alle Paketmanager so, dass sie zuerst die Datei löschen, bevor sie eine neue Version aufspielen.

Hardlinks sollte man nicht bei Konfigurationsdateien, sondern nur bei Binaries und Bibliotheken verwenden. VServer enthält ein Programm, das den Unterschied kennt und nur die Binaries beachtet: »vunify«. Es lässt sich vom Paketmanager (zurzeit nur RPM; Debian »dpkg« ist in Arbeit) die Namen aller in Frage kommenden Dateien geben und ersetzt automatisch doppelt vorhandene Dateien durch Hardlinks. Ein Kontext dient als Referenz, in den anderen werden Kopien durch Hardlinks ersetzt:

/usr/lib/vserver/vunify Referenz Server1 Server2 -- ALL

Mit dem Parameter »ALL« überprüft das Tool alle RPMs, alternativ kann man eine Liste von RPM-Namen angeben. Das Ergebnis ist erstaunlich: Eine Red-Hat-Installation schrumpft von 2 GByte auf schlanke 38 MByte. Sind neue Pakete einzuspielen, erledigt das »vrpm« in mehreren Servern gleichzeitig:

vrpm Server1 Server2 -- -hiv package.rpm

Der Servername »ALL« sorgt dafür, dass alle Server das neue Paket erhalten:

vrpm ALL -- -hiv package.rpm

Danach ist ein weiterer »vunify«-Lauf sinnvoll, da die neuen Pakete als Kopien in allen Kontexten vorhanden sind.

Die Prozesse in den einzelnen Serverkontexten können sich gegenseitig nicht sehen. Dieser erwünschte Umstand hat den Nachteil, dass auch der Admin nicht sieht, was alles auf der Maschine läuft. Aus diesem Grund hat Kontext 1 eine besondere Bedeutung: Er sieht die Prozesse aller anderen Kontexte. Mit ihm ist es möglich, eine Prozessliste aller auf der Maschine laufenden Prozesse in allen Kontexten zu erhalten.

Um alles zu vereinfachen, gibt es die Programme »vtop«, »vps«, »vpstree« und »vkill«, die das Gleiche machen wie ihre Verwandten ohne v, aber im Kontext 1 laufen. »vps« gibt zusätzlich den Namen des Kontexts aus, wobei mit »MAIN« der Gastgeberkontext 0 und mit »ALL_ PROCS« der Kontext 1 gemeint ist.

Das VServer-Patch fügt drei Syscalls in den Kernel ein, mit denen die Kontexte verwaltet werden. Der Befehl »vserver« nutzt diese Syscalls, um einen neuen Kontext zu erstellen, ihn auf eine IP-Adresse festzulegen und die Capabilities einzuschränken. Zudem ruft das Tool im Serververzeichnis »chroot« auf und startet »init«. Man kann diese Aufrufe auch einzeln nutzen: »chcontext« erzeugt neue Kontexte und wechselt in bestehende, »chbind« legt einen Prozess auf bestimmte IP-Adressen fest und »reducecap« schränkt die Root-Rechte ein. Normale Benutzer können mit »chcontext« nur neue Kontexte anlegen, Root darf auch in bestehende wechseln.

Dass die Prozesse verschiedener Kontexte einander sehen können, lässt sich mit »/usr/sbin/chcontext bash« nachvollziehen: In der neuen Shell zeigt »ps aux« nur die drei Prozesse »init«, »bash« und »ps«. Auch neue Prozesse, etwa »xterm«, sind nur in diesem Kontext sichtbar und nur von dort aus zu beenden. Die Prozesse sind jetzt zwar getrennt, Root verfügt aber immer noch über viele Rechte. »reducecap –secure bash« entzieht ihm diese Universalrechte, »reducecap –show« zeigt, welche Rechte noch vorhanden sind.

Fallstricke

Ein Serverkontext sieht zwar aus wie ein richtiger Server, es sind aber einige Besonderheiten zu beachten. Alle Kontexte laufen mit demselben Kernel und damit demselben TCP/IP-Stack. Deshalb darf sich jeder Kontext nur an die ihm zugewiesene IP-Adresse binden und insbesondere nicht an Localhost. Zugriffe auf 127.0.0.1 schlagen fehl. Bei den meisten Programmen genügt es, in »/etc/hosts« für »localhost« die IP-Adresse des Serverkontexts einzutragen.

Betreibt man virtuelle Serverkontexte auf einem Gastgebersystem mit nur einer IP-Adresse, zum Beispiel einem Dial-up-Rechner, können die Gastsysteme nicht direkt auf das Internet zugreifen. Der Grund dafür ist, dass NAT (Network Address Translation) lokal nicht funktioniert. Ausgehende Pakete erhalten die (extern ungültige) IP-Adresse des Serverkontexts, die Antworten erreichen den Kontext nicht mehr. Um dies zu umgehen, muss das Gastgebersystem entsprechende Proxies zur Verfügung stellen (Squid, Bind …) und jeder Kontext muss diese Proxies benutzen.

Dateisystem-Quotas harmonieren noch nicht mit VServer: Jeder Kontext hat zwar seine eigene »/etc/passwd« und verwaltet damit seine eigenen User-IDs. Das Dateisystem sieht aber die gleichen IDs und berechnet die Quoten über alle Kontexte hinweg. Überschneiden sich die IDs, dann zählen die Dateien aus jedem Kontext zur gleichen User-ID. Überschreitet ein Benutzer in einem Kontext die Grenze, wirkt sich dies auf alle Benutzer mit der gleichen User-ID in allen anderen Kontexten aus. Der VServer-Autor plant bereits ein Patch, das die User-IDs on the fly für jeden Kontext eindeutig umrechnet.

Virtuelle Serverkontexte bieten neue Möglichkeiten in der Serververwaltung. Der nahe liegende Einsatzbereich sind Webserver mit Root-Zugang. Wenn Kunden eigene Skripte, Datenbanken, Serverdienste oder Ähnliches installieren wollen, können sie dies in ihrem eigenen Kontext tun. Fehlkonfigurationen oder erfolgreiche Crackangriffe bleiben auf den Kontext beschränkt und gefährden nicht die anderen Server.

Mehr Sicherheit durch VServer

In einem Serverkontext ist es einfacher, Einbrüche zu entdecken. Wurde ein normales System geknackt und mit einem Root-Kit versehen, ist es sehr schwierig, das Root-Kit zu finden. Alle dafür nötigen Systemprogramme wurden eventuell durch solche ersetzt, die das Root-Kit verstecken. Bei virtuellen Serverkontexten ist das Erkennen leicht möglich, vorausgesetzt das Gastgebersystem wurde nicht ebenfalls geknackt. Alle Kontexte liegen in Unterverzeichnissen des Gastgebersystems und lassen sich von dort aus inspizieren, zum Beispiel kann Tripwire die veränderten Dateien erkennen und Alarm schlagen.

Die Datensicherung vieler Server vereinfacht sich ebenso, statt vieler Rechner muss sich das Backup nur um das Verzeichnis »/vservers« kümmern. Sollte ein Kunde sein Root-Passwort vergessen haben, kann es der Admin vom Gastgebersystem aus zurücksetzen, er ändert einfach die »passwd«-Datei im Verzeichnis des jeweiligen Servers.

In einem beschränkten Rahmen sind VServer auch zur Serverkonsolidierung geeignet. Viele einzelne Server lassen sich auf einem Server zusammenfassen, sofern alle mit Linux arbeiten. Die verwendete Distribution ist hierbei egal – ein System, auf dem nebeneinander Debian, Red Hat und SuSE laufen, ist kein Problem. Umgekehrt geht das natürlich auch: Virtuelle Serverkontexte lassen sich beliebig auf andere Maschinen verschieben, wenn veränderte Anforderungen es notwendig machen.

Fazit

Mit VServer mutiert ein realer Rechner zur virtuellen Server-Farm. Ohne den Overhead von Emulatoren à la VMWare laufen viele Linux-Installationen parallel auf einer Hardware. Wer gerne getrennte Mail-, Web- und FTP-Server hätte, damit Crackangriffe nicht alle Dienste auf einmal treffen, spart sich mit diesem Werkzeug unnötige Hardware. Auch beim Administrieren sind VServer recht praktisch: Neue Software ist schnell auf allen Servern installiert. (fjl)

Distributionen
minimieren

In einem VServer-Kontext muss in der Regel keine vollständige Linux-Distribution mit allen Gimmicks laufen. Für den Serverbetrieb genügt eine Minimalinstallation. Um eine bekannte Umgebung vorzufinden, empfiehlt es sich, eine gewohnte Distribution in abgespeckter Form zu installieren.

Debian: Mit »debootstrap« schnell am Ziel

Um Debian in ein Verzeichnis zu installieren, braucht man das Programm »debootstrap«[7]. Es ist als Debian- und RPM-Paket erhältlich. Wer den 22-MByte-Download nicht scheut, der kann mit »debootstrap woody /vserver/ Servername http://ftp.de.debian.org /debian« direkt über das Internet installieren. Sind CDs zur Hand, dann lautet das passende Kommando »debootstrap woody /vserver/ Servername file:///cdrom/debian«.

Red Hat und Mandrake

Für Red Hat 7.2, 7.3 und 8.0 sowie Mandrake Linux 8.2 enthält das VServer-Paket fertige Skripte, die bei gemounteter CD »/mnt/cdrom« alles vorbereiten. Beispielsweise installiert »/usr/lib/vserver/install-rh8.0 Servername« ein Red Hat 8.0.

Bei SuSE ist Handarbeit angesagt

Das selige Yast 1 konnte SuSE Linux noch in ein beliebiges Verzeichnis installieren. Yast 2 hat diese Fähigkeit verloren, man muss die Pakete von Hand einspielen. Als Ausgangsbasis dient die Datei »suse/setup/descrMinimal.sel« auf der ersten Installations-CD, sie enthält eine Liste der minimal notwendigen RPM-Pakete. Aus dieser Liste sind die RPMs nötig, die sich zwischen den Tags »+Ins:« und »-Ins:« befinden, dazu noch »yast2-trans-de« für Deutsch oder »yast2-trans-en_US« für Englisch.

Im nächsten Schritt installiert ein Skript (siehe Listing 1) die Pakete. Es liest die Datei »$PKGLIST«, legt eine Liste der RPMs in Form von Symlinks an und installiert dann alle Pakete auf einmal. Das ist notwendig, damit sich RPM-Abhängigkeiten zwischen den Paketen automatisch auflösen. Wer sich die Mühe machen will, kann die Pakete auch in die richtige Reihenfolge bringen und dann in einer »for«-Schleife installieren.

Infos:

[1] VServer: [http://www.solucorp.qc.ca/miscprj/s_context.hc]

[2] User-Mode-Linux: [http://user-mode-linux.sourceforge.net/]

[3] VMWare: [http://www.vmware.com]

[4] Plex86: [http://savannah.nongnu.org/projects/plex86]

[5] Bochs: [http://bochs.sourceforge.net/]

[6] VServer-Quellen: [ftp://ftp.solucorp.qc.ca/pub/vserver]

[7] Debian-Bootstrap: [http://people.debian.org/~blade/install/debootstrap/]

Der
Autor

Kurt Huwig ist Vorstand der iKu Systemhaus AG in Saarbrücken und installiert seit 1996 Linux-Server. In seiner Freizeit entwickelt er für das Open-Antivirus-Projekt einen GPL-lizenzierten Virenscanner.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben