Inhaltsverzeichnis

Allgemein

Eine Jail ist ein abgeschotteter Systembereich zur Erhöhung der Systemsicherheit. Hierdurch werden Programme, bzw. Dienste ein einem getrennten Systembereich ausgeführt um das eigentliche System zu schützen. Im Prinzip ist es eine Erweiterung einer chroot-Umgebung. Teilweise wird es auch als Virtualisierung bezeichnet, jedoch ist eine Jail im Funktionsumfang keineswegs mit echten Virtualisierungen zu vergleichen. Genauere Details zum Sinn und der möglichen Nutzung von Jails sollen hier nicht aufgeführt werden.

Die Jail kann entweder aus den Binärpaketen installiert werden oder komplett aus den Quellen übersetzt. Beide Varianten werden hier aufgeführt, wobei die Installation aus den Binärpaketen deutlich schneller vollzogen ist.

Manuelle Verwaltung von Jails vs ezjail

Im weiteren Verlauf dieses Artikels wird gezeigt wie man von Hand Jails erstellen und verwalten kann. Dies ist, speziell wenn man mehrere Jails verwaltet, mit wachsendem Aufwand verbunden. Alternativ hierzu gibt es verschiedene Jail-Management-Programme wie z.B. ezjail welche diese Aufgaben stark vereinfachen können. Im Artikel EIn Jailsystem mit ezjail installieren wird die Installation und Konfiguration von ezjail erläutert.

Verzeichnisse anlegen

Um dem System eine gewisse Ordnung einzuhalten werden alle Jails im Folgenden unter /usr/local/jails erstellt. Dieser Ort ist frei wählbar und könnte z.B. auch auf einem anderen Datenträger liegen. Entsprechend sind die Verzeichnisangaben dann jedoch zu ändern.

Sollte das Verzeichnis welches die Jails halten soll noch nicht vorhanden sein wird es zunächst angelegt:

# cd /usr/local
# mkdir jails

Anschließend wird das Verzeichnis für die erste zu erstellende Jail angelegt. In diesem Beispiel trägt sie den Namen testjail.

# cd /usr/local/jails
# mkdir testjail

Installation aus Binärpaketen

Zur Installation der Jail aus Binärpaketen kann bsdinstall verwendet werden, welches bereits aus der Installation des Basissystems bekannt ist. Wird bsdinstall verwendet um eine Jail zu installieren muss es wissen welche FreeBSD-Version es installieren soll. Um dies herauszufinden fragt es uname -r ab. Da die Installationsquellen für bsdinstall nur für die Veröffentlichungsversionen (z.B. 10.0-RELEASE) und nicht für darauf aufsetzende Patchversionen (z.B. 10.0-RELEASE-p7) vorhanden sind muss im Allgemeinen bsdinstall ein falscher Wert für uname -r untergeschoben werden. Hierzu kann die Umgebungsvariable UNAME_r gesetzt werden.

Um z.B. auf einem FreeBSD 10.0 System eine Jail zu installieren wird die Variable UNAME_r wie folgt gesetzt.

# sentenv UNAME_r 10.0-RELEASE

Hiermit liefert uname -r nun den gewünschten Wert.

Nun kann mittels bsdinstall die Installation begonnen werden.

# bsdinstall jail /usr/local/jails/testjail

Zunächst wird hier der Server ausgewählt von welchem die Installationsdateien heruntergeladen werden (falls nicht bereits bei einer vorherigen Installation geschehen). Anschiessend sind die zu installierenden Sets auszuwählen und der Download und deren Installation beginnt.

Nun wird noch das root-Kennwort gesetzt und ausgewählt welche Standarddienste in der Jail automatisch gestartet werden sollen (dumpdev sollte hier abgewählt werden wenn es nicht wirklich benötigt wird) und das root-Kennwort gesetzt. Abschliessend kann noch ein normaler Benutzeraccount angelegt werden und die Installation ist beendet.

Um das installierte Basisversion nun noch mit den aktuellen binären Patchlevel zu versorgen wird freebsd-update verwendet. Hierzu muss UNAME_r noch auf der Veröffentlichungsversion gesetzt bleiben.

# freebsd-update -b /usr/local/jails/testjail fetch install

Nun kann UNAME_r wieder zurückgesetzt werden, damit es in Zukunft wieder den korrekten Patchlevel liefert.

# unsetenv UNAME_r

Weiter geht es dann mit: Jail einrichten

Installation aus den Systemquellen

Die Installation aus den Systemquellen dauert länger und ist aufwändiger. Für ein normales System lohnt sich der Mehraufwand iA nicht so keine besonderen Kompileroptionen gewünscht werden.

Voraussetzungen

Es ist ein installiertes FreeBSD mit installierten Systemquellen in /usr/src notwendig.

System kompilieren

Nachdem die Quellen der Jail vorhanden sind muss das System welches installiert werden soll kompiliert werden. Hierfür werden die Standardbefehle zum übersetzen des Basissystems verwendet. Die make-Befehle müssen immer unter /usr/src ausgeführt werden.

# cd /usr/src/
# make buildworld

Hierdurch wird das gesamte Basissystem übersetzt und in /usr/obj gespeichert. Dieser Vorgang kann, abhängig vom Computer, recht lange dauern. Immerhin wird ein komplettes, modernes Unix-System übersetzt.

System installieren

Das fertig kompilierte System wird nun an seinen Zielort kopiert. Dies geschieht mit folgendem Aufruf (auch hier wieder aus /usr/src).

# make installworld DESTDIR=/usr/local/jails/testjail
# make distribution DESTDIR=/usr/local/jails/testjail

Jail einrichten

Wurde die Jail nicht per bsdinstall installiert muss noch der Nameserver in der etc/resolv.conf der Jail definiert werden. Hierzu wird die Namensauflösung des Hostsystems übernommen.

cp /etc/resolv.conf /usr/local/jails/testjail/etc/resolv.conf

Nun wird noch die adjkerntz-Zeile in der /usr/local/jails/testjail/etc/crontab deaktiviert (ein # davor gesetzt):

#1,31    0-5 *   *   *   root    adjkerntz -a

Zuletzt wird das Logging so eingestellt, dass Nachrichten in eine Datei fließen und nicht in die Console. Hierzu wird in der Datei /usr/local/jails/testjail/etc/syslogd.conf die Zeile

*.err;kern.warning;auth.notice;mail.crit        /dev/console

wie folgt geändert:

*.err;kern.warning;auth.notice;mail.crit        /var/log/messages

Die Jail ist somit prinzipiell fertig.

Um die Messages von syslog in der Jail zu halten und sämtlichen Netzwerkverkehr von syslogd zu unterbinden wird die Datei /usr/local/jails/testjail/etc/rc.conf um die Zeile ergänzt (soll die Jail per syslogd in einen Remote-Rechner loggen - z.B. der Host - darf diese Zeile nicht gesetzt werden):

syslogd_flags="-ss"

Hostnamen setzen

Der Hostname muss noch festgelegt werden. Hierzu wird die Datei /usr/local/jails/testjail/etc/hosts entsprechend angepasst.

Anpassen des Hostsystems

Spätestens seit FreeBSD 10 werden Jails in einer eigenen Konfigurationsdatei des Hostsystems, der /etc/jail.conf, verwaltet.

jail.conf

Die jail.conf besteht aus einem allgemeinen Teil, der grundlegende Einstellungen für alle Jails enthält, und einem Teil der die speziellen Einstellungen jeder einzelnen Jail definiert.

##########################################
###### Allgemeine Einstellungen     ######

# Jailstart
exec.start="/bin/sh /etc/rc";

# Jailstop
exec.stop="/bin/sh /etc/rc.shutdown";

# Aufraeumen
exec.clean;

# Devfs mounten
mount.devfs;

# Netzwerkkarte
interface="em0";

##########################################
###### Per Jail Einstellungen       ######

testjail {
  host.hostname = "testjail.example.com";
  path = /usr/local/jails/testjail;
  ip4.addr = "www.xxx.yyy.zzz";
}

Für jede weitere Jail wird ein neuer Abschnitt in den unteren Teil eingefügt.

Jail im RC-System eintragen

Um die Jail dem System bekannt zu machen und auf einfache Weise über das RC-System starten zu können wird die Datei /etc/rc.conf noch angepasst. Es kommen folgende Einträge hinzu:

# JAILS
jail_enable="YES"
jail_list="testjail"

Der Eintrag jail_enable definiert ob Jails prinzipiell gestartet werden oder nicht. Unter jail_list wird eine durch Leerzeichen getrennte Liste von Jailnamen erwartet welche beim Systemstart automatisch gestartet werden sollen.

Lauschende Ports auf Host-IP beschränken

Da die IP der Jail ein Alias des Hostsystems ist wird auf Netzwerkanfragen auf diese IP prinzipiell das Hostsystem antworten. Um dies abzustellen müssen alle lauschenden Prozesse des Hostsystems ausschliesslich auf dessen IP lauschen.

Um die lauschenden Prozesse anzuzeigen kann der folgende Aufruf verwendet werden.

# sockstat -4

Alle Prozesse welche * als IP aufführen lauschen auf allen verfügbaren IPs. Um dies abzustellen müssen die Dienste entsprechend umkonfiguriert werden. Ein prominentes Beispiel ist der sshd-Server.

Jail starten und anhalten

Die Jail kann dann mit den folgenden Befehlen gestartet und wieder beendet werden.

# jail -c testjail
# jail -r testjail

Dabei steht -c für create zum Starten der Jail und -r für remove zum Beenden der Jail.

Jails auflisten

Eine Liste aller laufender Jails findet sich mit dem Befehlt jls. Dieser zeigt auch gleich die zur Jail zugehörigen ID JID die benötigt wird um z.B. über jexec mit der Jail zu kommunizieren.

In der Jail arbeiten (Shell in der Jail)

Um in der laufenden Jail eine Shell zu öffnen um hierin zu arbeiten wird der Befehl jexec verwendet. Hierzu muss die Jail laufen.

# jexec testjail /bin/sh

Alternativ kann eine Shell in der Jail mit dem folgenden Befehl gestartet werden:

# /etc/rc.d/jail console testjail

Rootkennwort ändern und Benutzer anlegen

Wurde die Jail per bsdinstall installiert wurde das root-Kennwort bereits gesetzt. Wurde die Installation jedoch aus den Systemquellen installiert muss noch das Kennwort des Benutzers root gesetzt werden. Nach dem Login in die Jail per jexec sollte das Kennwort des root-Benutzers mittels passwd geändert werden.

Sollen noch normale Benutzer angelegt werden kann dies per adduser erfolgen. Dieser kann z.B. für einen SSH-Login verwendet werden wenn man root-Logins per ssh verbieten möchte.

X11 verbieten

Da in einer Jail i.A. keine grafischen Anwendungen laufen sollte man das einkompilieren von X11-bezogenen Teilen unterbinden. Dieser Vorgang ist unter X11 verbieten beschrieben.

Mailsystem einrichten

Das Mailsystem der Jail muss noch entsprechend angepasst werden damit Mails an einen Empfänger zugestellt werden können. Hierzu muss mindestens der Hostname eingerichtet werden. Evtl. können Weiterleitungen in der Datei /etc/mail/aliases eingetragen werden (anschließend muss newaliases ausgeführt werden).

Ggf. bietet sich hier auch die Verwendung von ssmtp an.

Zeitzone einstellen

Anschließend sollte noch die Zeitzone richtig eingestellt werden. Am einfachsten geht das per tzsetup. Ist der Host auf UTC eingestellt sollte die Jail ebenfalls auf UTC laufen.

Ports-Tree verfügbar machen

Um Programme in der Jail zu installieren ist es sinnvoll einen Port-Tree vorliegen zu haben. Da im Allgemeinen im Hostsystem bereits ein Ports-Tree vorhanden ist kann dieser verwendet werden um nicht unnötig Speicherplatz für doppelte Datenhaltung zu verschwenden. Durch einen nullfs-mount kann das Ports-Verzeichnis des Hosts in der Jail eingebunden werden. Um eine mögliche Sicherheitslücke zu vermeiden sollte der Ports-Tree schreibgeschützt in die Ports eingebunden werden.

Mounten des Port-Trees

Hierzu wird entweder per Hand der Ports-Tree read-only gemountet:

# mount_nullfs -o ro /usr/ports /usr/local/jails/testjail/usr/ports

oder automatisch beim Hochfahren über die Datei /etc/fstab des Hostsystems. Hierzu wird die /etc/fstab wie folgt erweitert:

/usr/ports   /usr/local/jails/testjail/usr/ports     nullfs  ro  0   0

Zuvor muss das ports-Verzeichnis in der Jail angelegt sein.

make.conf anpassen

Damit die Ports nun auch gebaut werden können muss dem Gastsystem noch ein alternatives Verzeichnis mit Schreibrechten zugeteilt werden. Die Datei /etc/make.conf hält diese Informationen. Um die gewünschte Änderung durchzuführen wird die Datei wie folgt ergänzt, oder nötigenfalls erzeugt:

WRKDIRPREFIX=/tmp
DISTDIR=/tmp/distfiles
PACKAGES=/tmp/packages

Nun werden die Arbeitsdaten der Ports unter /tmp des Gastsystems abgelegt und der Ports-Tree wird nicht durch die Ports geändert.

Startscript - Eigene Startbefehle festlegen

Soll die Jail beim Systemstart noch spezielle Befehle ausführen die nicht über rc.conf abgedeckt werden können, so können diese in das Startscript /etc/rc.local (innerhalb der Jail) aufgenommen werden.

Jail aktualisieren

Die Vorgehensweise um eine Jail zu aktualisieren wird im Artikel Jail aktualisieren beschrieben.