FreeBSD Jails mit Raspberry

handmadepictures, 123RF

Himbeerknast

FreeBSD und Raspberry Pi bilden ein starkes Team. Das bekannteste Sicherheitsmerkmal von FreeBSD sind Jails. Sie bieten auch auf der Raspberry-Plattform ein Plus an Sicherheit.
Das Titelthema im ADMIN 04/14 "Vernetzt speichern" sind Netzwerkdateisysteme, etwa Samba 4, verteilter Storage mit Ceph & GlusterFS und der Unix-Klassiker ... (mehr)

Jails gehören zu den herausstechenden Sicherheitsmerkmalen von FreeBSD [1] . Bei einer Jail handelt sich um eine erweiterte Chroot-Umgebung, wie sie auch Linux und andere Unix-Systeme kennen. Allerdings bietet eine Jail-Umgebung absoluten Schutz vor der Manipulation von Prozessen, die außerhalb derselben laufen. Da eine Jail in einem eigenen Verzeichnisbaum arbeitet, kann ein Prozess innerhalb der Jail nicht auf Verzeichnisse und Dateien außerhalb dieser Struktur zugreifen, der Elternverzeichnisbaum wird unsichtbar. Einem Jail-Prozess ist es unmöglich, auf Prozesse und Daten des Hosts einzuwirken. Diese Eigenschaft erleichtert die Administration von Jails auf einem Raspberry Pi erheblich.

Eines gleich vorweg: Eine Jail erhöht die Sicherheit eines Daemons selbst nicht. Weist ein Dienst eine Sicherheitslücke auf, dann tritt diese auch in der Jail auf. Doch wenn es einem Angreifer damit gelingt, sich Zugang zur Jail zu verschaffen, zeigt sich das Sicherheitsplus von Jails: Er findet sich in der Jail eingesperrt wieder, der Zugang zum Hostsystem bleibt ihm verwehrt.

Mit diesen Sicherheitseigenschaften bietet sich auch ein Raspberry Pi mit FreeBSD als zentralem Element eines Heimnetzwerks an. Er kann die Rolle eines Einwähl-Routers mit eigenem Web- oder Nameserver (DNS) übernehmen, jeweils in eigenen Jails gesichert. Im Falle einer Sicherheitslücke in den Daemons gelangt der Angreifer nicht an andere wichtige Daten des Hostsystems.

Die Erstellung von Jails erfordert einige Zeit und Rechenleistung, da sie die Neukompilierung von Teilen des Betriebssystems voraussetzen. Wer seine Nerven und den Raspberry schonen möchte, sollte diese Aufgabe deshalb mittels Cross-Compiling von einem leistungsfähigeren FreeBSD-System erledigen lassen. Aber Achtung: Die FreeBSD-Versionen auf dem Raspberry und auf dem Hostsystem müssen identisch sein!

Kopfrechnen

Zu Beginn steht die Planung der Jails, denn der Raspberry begrenzt den Arbeitsspeicher auf 512 MByte und ein Swapfile auf einer SD-Karte macht wegen der langsamen Lese- und Schreibgeschwindigkeiten keinen Spaß. Als Faustregel sollte man etwa 100 MByte SD-Kartenspeicher und vier MByte Arbeitsspeicher je Jail einplanen.

Das FreeBSD-Basissystem wird wie in [2] beschrieben als Root-User kompiliert und auf dem Raspberry Pi installiert. Es lohnt sich, die bei der Installation angelegte Arbeitsumgebung zu behalten, da sie für die Aktualisierung und die Erstellung neuer Jails immer wieder zum Einsatz kommt. Ist sie dennoch bereits gelöscht, gibt es zwei Möglichkeiten, um die FreeBSD-Installation von der SD-Karte des Raspberry Pi zurückzuholen. Entweder man kopiert das Image der SD-Karte in ein Arbeitsverzeichnis…

# dd if=/dev/da0 of=/home/raspberry/rpi.img bs=1m

…oder man arbeitet direkt auf der SD-Karte. Der folgende Befehl mountet sie:

# mount /dev/da0s2a /mnt

Dieser Artikel setzt im weiteren Verlauf auf die erste Methode und arbeitet mit einem Image.

Es folgt das Einhängen des FreeBSD-Slice mit dem Raspberry-Image. Die folgenden Shell-Befehle erledigen das und setzen die Umgebungsvariable fürs Cross-Kompilieren:

# cd /home/raspberry
# mdconfig -a -t vnode -f ./rpi.img md0
# mount /dev/md0s2a /mnt
# sh
# export TARGET_ARCH=armv6

Da eine Jail einige Standard-Tools wie Compiler und Spiele nicht benötigt, erstellt man eine Datei »/etc/src.conf« mit den gewünschten Ausnahmen. Es empfiehlt sich aber, zuvor die existierende »/etc/src.conf« -Datei zu sichern; wenn man das Hostsystem später neu kompiliert, benötigt man sie wieder in ihrem Originalzustand.

WITHOUT_CDDL="YES"
WITHOUT_CLANG="YES"
WITHOUT_CPP="YES"
WITHOUT_MAN="YES"
WITHOUT_CROSS_COMPILER="YES"
WITHOUT_GAMES="YES"
WITHOUT_ZFS="YES"
WITHOUT_GCC="YES"

Die FreeBSD-Jail soll im Verzeichnis »/mnt/home/jails/dns« landen, das man nötigenfalls zuvor anlegt. Um die weitere Tipparbeit zu reduzieren, wird die Pfadangabe zum Jail-Verzeichnis hier in der Shell-Variablen »JAILDIR« hinterlegt:

# export JAILDIR=/mnt/home/jails/dns
# mkdir -p ${JAILDIR}

Anschließend startet der Compiler-Lauf:

# make MALLOC_PRODUCTION=yes buildworld

Zur Installation der in der Jail benötigten Tools übergibt man das Zielverzeichnis mit »DESTDIR« an Make:

# make DESTDIR=${JAILDIR} DB_FROM_SRC=1installworld distribution

Sind alle Schritte erfolgreich abgeschlossen, schreibt man das Image zurück auf die SD-Karte:

# umount /mnt
# mdconfig -d -u md0
# dd if=/home/raspberry/rpi.img of=/dev/da0 bs=1m

Die weiteren Konfigurationsarbeiten finden direkt auf dem Raspberry Pi statt. Dafür setzt man die SD-Karte wieder in den Raspberry ein, bootet das System und meldet sich als Root-User an. Als ersten Schritt erstellt man dann eine Konfigurationsdatei für die Jails und legt sie im Verzeichnis »/etc« unter dem Namen »jail.conf« ab. Sie enthält die folgenden Einträge:

exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
path = "/home/jails/$name";
dns {
 host.hostname = "dns.example.home";
 ip4.addr = 192.168.1.9;
 interface = fxp0;
 mount.devfs;
}

Die ersten drei Zeilen bezeichnen die Kommandos zum Starten und Beenden der Jail. Die »path« -Angabe beschreibt das Verzeichnis, das die Jails enthält. Die Variable »$name« enthält den Namen der Jail. Der »dns« -Abschnitt beschreibt die Jail-Einstellungen mit dem gewünschten Hostnamen, der IP-Adresse und dem Netzwerk-Interface. Weiterhin legt »mount.devfs« fest, dass der Device-Driver-Manager von FreeBSD die Gerätetreiber auch in der Jail zur Verfügung stellt.

Wie auf jedem anderen FreeBSD-System erfolgt der Start der Jail über die Konsole:

jail -c path=/home/jails/dns mount.devfshost.hostname=dns.example.homeip4.addr=192.168.1.9 command=/bin/sh

Danach finden alle weiteren Konfigurationsarbeiten innerhalb der Jail statt. Zunächst legt man eine leere »/etc/fstab« -Datei an:

# touch /etc/fstab

Eine einfache Konfigurationsdatei »/etc/rc.conf« wird mit dem folgenden Inhalt generiert:

sendmail_enable="NO"
inetd_flags="-wW -a 192.168.1.9"
rpcbind_enable="NO"
defaultrouter="192.168.1.1"

Die Konfigurationsdatei »/etc/ssh/sshd_config« passt den SSH-Daemon an die Jail an:

ListenAddress 192.168.1.9
Port 10053

Abschließend legt man einen Login-User an, hier »admin« , und vergibt ein Passwort an Root:

# pw user add admin -g wheel
# passwd admin
# passwd root

Das »exit« -Kommando verlässt die Jail. Nun geht die Konfiguration auf dem Host-Hauptsystem weiter, indem man in der Systemkonfiguration »/etc/rc.conf« den Start von Jails zulässt:

jail_enable="YES"

Existieren die Unterverzeichnisse von »/usr/local« in der Jail noch nicht, holt man dies mit einem kleinen Trick nach. Dabei kommt der Dateisystemtreiber »nullfs« zum Einsatz, um Verzeichnisse vom Host in die Jail zu mounten. Der Vorteil dieser Methode liegt darin, dass eventuelle Updates nur auf dem Host stattfinden müssen und die Anwendungen innerhalb der Jail zugleich auf den aktuellen Stand bringen. Dieses Vorgehen scheint auf den ersten Blick die Sicherheitsbarriere zwischen Jail und Host zu durchlöchern. Doch das Prozess-Management des Betriebssystems verpasst den Prozessen innerhalb der Jail das Jail-Bit und verhindert damit, dass Prozesse aus der Jail ausbrechen.

Auf dem Host ergänzt man die Datei »/etc/fstab« um folgende Einträge:

/usr/local/bin /home/jails/dns/usr/local/binnullfs ro 0 0
/usr/local/sbin /home/jails/dns/usr/local/sbinnullfs ro 0 0
/usr/local/lib /home/jails/dns/usr/local/libnullfs ro 0 0
/usr/local/libdata /home/jails/dns/usr/local/libdatanullfs ro 0 0
/usr/local/share /home/jails/dns/usr/local/sharenullfs ro 0 0

Das Verzeichnis »/usr/local/etc« und seine Unterverzeichnisse dürfen hingegen nicht in der Jail landen, da sie teilweise Konfigurationsdateien mit Einträgen enthalten, die verborgen bleiben müssen. Gleiches gilt für »/usr/local/etc/rc.d« . Daher legt man dieses Verzeichnis für die Jail manuell an:

mkdir -p /home/jails/dns/usr/local/etc/rc.d

Es folgen der Start der Jail…

# service jail start dns

…und der erste Login:

# ssh admin@dns.example.home

Den Status der Jail verrät das folgende Kommando:

# service jail status dns
 JID IP Address Hostname Path
 dns 192.168.1.9 dns... /home/jails/dns

Abbildung 1 zeigt im linken Terminal-Fenster eine erfolgreiche Anmeldung am Raspberry selbst. Das rechte Fenster zeigt eine SSH-Verbindung zur Jail, in der der Nameserver läuft. Die Host-Namen und IP-Adressen entstammen dem privaten Netzwerk des Autors.

Abbildung 1: SSH-Logins auf dem Raspberry Pi mit FreeBSD und in einer Jail auf demselben Host.

Anwendungen

Wie auf großen Servern bieten Jails auch auf kleinen Systemen wie dem Raspberry eine Reihe von Anwendungsmöglichkeiten, beispielsweise als Webserver für die eigene Homepage, als eigener Nameserver, Squid als transparenter Webproxy und viele mehr. Das folgende Beispiel zeigt die Einrichtung eines Nameservers fürs eigene Netzwerk.

Da es noch kein vollständiges Repository für die ARM-Architektur des Raspberry Pi gibt, installiert man zunächst auf dem Host das Tool »bind99« aus den Ports:

# cd /usr/ports/dns/bind99
# make config

Hier sind die Optionen für SSL- und GSSAPI-Support abzuwählen, weil sie für ein kleines Heimnetz unnötig sind. Anschließend führt man

# make install clean

aus. Danach kopiert man die Konfigurationsdateien aus »/usr/local/etc/namedb« nach »/home/jails/dns/usr/local/etc« und das Startskript aus »/usr/local/etc/rc.d« nach »/home/jails/dns/usr/local/etc/rc.d« :

# mkdir -p /home/jails/dns/usr/local/etc/namedb
cp -R /usr/local/etc/namedb /home/jails/dns/usr/local/etc/namedb
cp -R /usr/local/etc/rc.d/named /home/jails/dns/usr/local/etc/rc.d/named

Es folgen wichtige Anpassungen einiger Parameter in der Konfigurationsdatei des DNS-Daemon »bind« , damit das Programm in der Jail reibungslos funktioniert:

# cat /home/jails/dns/usr/local/etc/namedb/named.conf
[...]
query-source address 192.168.1.9;
listen-on port 53 { 192.168.1.9; };
allow-query {
 192.168.1.0/24;
};
[...]

Die Konfigurationsdatei »/etc/rc.conf« der Jail ergänzt man um die folgenden Zeilen:

named_enable="YES"
named_chrootdir=""

Die weitere Konfiguration des DNS-Dienstes hängt vom Netzwerk ab, um das sich die Namensauflösung kümmert.

Auf dem Host ist die Angelegenheit etwas komplizierter. Damit Anfragen an den Nameserver und dessen Antworten ihre Ziele erreichen, ergänzt man die Paketfilterregeln. Für den von OpenBSD abstammenden Paketfilter PF sieht ein mögliche Regel wie folgt aus:

rdr on $if_int inet proto tcp from $if_int:network to any port dns ->192.168.1.9 port dns

Für den FreeBSD-Paketfilter IPFW fällt die Konfiguration etwas umfangreicher aus. Einerseits wird der NAT-Daemon mit »/etc/natd.conf« konfiguriert:

redirect_port tcp 192.168.1.9:53 53
redirect_port udp 192.168.1.9:53 53

Andererseits sind diese Regeln zu ergänzen:

#!/bin/sh
fwcmd="/sbin/ipfw -f"
[...]
${fwcmd} add divert natd all from any to any via ${if_ext}
${fwcmd} add allow udp from any to any 53 out via ${if_ext}iptos reliability keep-state
${fwcmd} add allow tcp from any to any 53 out via ${if_ext}setup iptos reliability keep-state
[...]

Aber Achtung: die oben genannten Regeln zeigen zwar das Prinzip, öffnen aber auch den DNS-Port 53 für alle Anfragen. In der Praxis sollten die Ports nur den in der DNS-Konfiguration angegebenen externen DNS-Servern offenstehen.

Abschließend startet man die DNS-Jail auf dem Host mit:

# service jail start dns

Ein Funktionstest erfolgt mit:

# nslookup www.bsdforen.de

Das Ergebnis sollte dem folgenden Ausgabeprotokoll ähneln:

$ nslookup www.bsdforen.de
Server: 192.168.1.9
Address: 192.168.1.9#53
Non-authoritative answer:
Name:   www.bsdforen.de
Address: 82.193.243.81

FreeBSD stellt mit seinen Jails auch auf dem Raspberry Pi eine ideale Lösung dar. Jails bieten auch auf dieser Plattform ein Maximum an Sicherheit bei geringem Ressourcenverbrauch und Administrationsaufwand.

Infos

  1. ADMIN-Magazin 01/2013, Jürgen Dankoweit, "Sicher hinter Gittern": http://www.admin-magazin.de/Das-Heft/2013/01/Wie-man-Jails-in-FreeBSD-konfiguriert-und-benutzt/
  2. ADMIN-Magazin 03/2014, Jürgen Dankoweit, "Himbeere mit Sahne": http://www.admin-magazin.de/Das-Heft/2014/03/Raspberry-Pi

Ähnliche Artikel

comments powered by Disqus
Mehr zum Thema

Wie man Jails in FreeBSD konfiguriert und benutzt

Heute, wo IT-Sicherheit eine immer größere Rolle spielt, findet ein Feature von FreeBSD besondere Beachtung: die Jails. Worin das Sicherheitsplus besteht, das sie versprechen, beleuchtet dieser Artikel.
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023