FreeBSD-Jails auf dem Raspberry Pi

© Stephen Bonk, 123RF

Himbeerknast

Das bekannteste Sicherheitsmerkmal von FreeBSD, die sogenannten Jails, bieten auch auf dem Raspberry Pi ein deutliches Plus an Sicherheit.

README

FreeBSD stellt mit zahlreichen Sicherheitsfunktionen eine Alternative zu den üblichen Linux-Distributionen dar. Jails sorgen für ein Maximum an Sicherheit bei geringem Ressourcenverbrauch und Administrationsaufwand.

Jails gehören zu den herausstechenden Sicherheitsmerkmalen von FreeBSD [1]. Bei einer Jail handelt es 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 der Struktur zugreifen, der Elternverzeichnisbaum bleibt unsichtbar. Ebenso verhindert das Prozessgefängnis, dass der Jail-Prozess auf Prozesse und Daten des Hosts einwirkt. Diese Eigenschaft erleichtert das Administrieren von Jails auf einem Raspberry erheblich.

Eines gleich vorweg: Eine Jail erhöht die Sicherheit eines "eingesperrten" Daemons selbst nicht. Weist ein Dienst eine Sicherheitslücke auf, dann tritt diese auch in der Jail-Umgebung auf. Falls ein Angreifer es aber auf diesem Weg schafft, sich Zugang zur Jail zu verschaffen, dann zeigt sich auch das Sicherheitsplus einer solchen Umgebung: 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 zentrales Element eines Heimnetzwerks an. Er kann die Rolle eines Einwähl-Routers mit eigenem Web- oder Name-Server (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.

Zur Sache!

Die Erstellung von Jails erfordert einige Zeit und Rechenleistung, da sie das Neukompilieren von Teilen des Betriebssystems voraussetzen. Möchten Sie Ihre Nerven und den Raspberry schonen, sollten Sie diese Aufgabe deshalb mittels Cross-Compiling auf einem leistungsfähigeren FreeBSD-System erledigen. Aber Achtung: Die FreeBSD-Versionen auf dem Raspberry und auf dem Hostsystem müssen identisch sein!

Zu Beginn steht die Planung der Jails: Schließlich begrenzt der Raspberry den Arbeitsspeicher auf 512 MByte, und ein Swap-File auf einer SD-Speicherkarte macht wegen deren niedriger Lese- und Schreibgeschwindigkeit keinen Spaß. Als Faustregel sollten Sie beim Setup etwa 100 MByte SD-Kartenspeicher und 4 MByte Arbeitsspeicher je Jail einplanen.

Das FreeBSD-Basissystem kompilieren und installieren Sie als Root-User auf dem Raspberry Pi, wie bereits im ersten Teil unserer FreeBSD-Reihe beschrieben [2]. Es lohnt sich, die bei der Installation angelegte Arbeitsumgebung zu behalten, da sie für das Aktualisieren und Erstellen neuer Jails immer wieder zum Einsatz kommt.

Haben Sie sie dennoch bereits gelöscht, gibt es zwei Möglichkeiten, um die FreeBSD-Installation von der SD-Karte des Raspberry zurückzuholen. Entweder kopieren Sie das Image der SD-Karte mit folgendem Befehl in ein Arbeitsverzeichnis:

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

Alternativ arbeiten Sie direkt auf der SD-Karte, die sie mittels mount /dev/da0s2a /mnt einhängen. 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 Shell-Befehle aus Listing 1 erledigen das und setzen die Umgebungsvariable fürs Cross-Kompilieren für die Zielplattform.

Listing 1

 

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

Da eine Jail einige Standardwerkzeuge nicht benötigt, wie etwa Compiler und Spiele, erstellen Sie am besten eine Datei /etc/src.conf mit den gewünschten Ausnahmen (Listing 2). Zuvor sollten Sie allerdings die existierende Instanz dieser Datei sichern: Sobald Sie das Hostsystem später neu kompilieren, benötigen Sie sie wieder im Originalzustand.

Listing 2

 

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 Sie gegebenenfalls zuvor anlegen müssen. Um die weitere Tipparbeit zu reduzieren, hinterlegen Sie die Pfadangabe zum Jail-Verzeichnis in der Shell-Variablen JAILDIR (Listing 3, Zeile 1). Anschließend starten Sie den Compilerlauf (Zeile 3). Zur Installation der in der Jail benötigten Tools übergeben Sie mit DESTDIR das Zielverzeichnis an Make (Zeile 4). Nach dem erfolgreichen Abschließen aller Schritte schreiben Sie das Image zurück auf die SD-Karte (ab Zeile 5).

Listing 3

 

# export JAILDIR=/mnt/home/jails/dns
# mkdir -p ${JAILDIR}
# make MALLOC_PRODUCTION=yes buildworld
# make DESTDIR=${JAILDIR} DB_FROM_SRC=1 installworld distribution
# 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 setzen Sie die SD-Karte wieder in den Raspberry ein, booten das System und melden sich als Root-User an. Als ersten Schritt erstellen Sie dann eine Konfigurationsdatei für die Jails und legen sie im Verzeichnis /etc unter dem Namen jail.conf ab (Listing 4).

Listing 4

 

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 darauffolgende Angabe path beschreibt das Verzeichnis, das die Jails enthält. Die Variable $name erhält dabei den Namen der Jail. Der Abschnitt dns 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 üblich erfolgt der Start der Jail über die Konsole (Listing 5).

Listing 5

 

# jail -c path=/home/jails/dns mount.devfs host.hostname=dns.example.home ip4.addr=192.168.1.9 command=/bin/sh

Danach finden alle weiteren Konfigurationsarbeiten innerhalb der Jail statt. Zunächst legen Sie mit touch /etc/fstab eine leere Fstab an. Des Weiteren generieren Sie eine einfache Konfigurationsdatei /etc/rc.conf (Listing 6). Den SSH-Daemon passt die Konfigurationsdatei /etc/ssh/sshd_config an die Jail an (Listing 7). Abschließend legen Sie einen Login-User an, hier admin, und vergeben ein Passwort an Root (Listing 8).

Listing 6

 

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

Listing 7

 

ListenAddress 192.168.1.9
Port 10053

Listing 8

 

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

Das exit-Kommando verlässt nun die Jail. Anschließend geht die Konfiguration auf dem Host-Hauptsystem weiter, indem Sie in der Systemkonfiguration /etc/rc.conf über folgende Zeile den Start von Jails zulassen:

jail_enable="YES"

Existieren die Unterverzeichnisse von /usr/local in der Jail noch nicht, holen Sie 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: Eventuelle Updates müssen nur auf dem Host stattfinden, die Anwendungen innerhalb der Jail bringen Sie damit ebenfalls auf den aktuellen Stand.

Die scheint auf den ersten Blick die Sicherheitsbarriere zwischen Jail und Host zu durchlöchern. Dem ist aber nicht so, da das Prozessmanagement des Betriebssystems für die Prozesse innerhalb der Jail das Jail-Bit setzt. Das verhindert, dass Prozesse aus der Jail ausbrechen. Auf dem Host ergänzen Sie dazu die Datei /etc/fstab um die Einträge aus Listing 9.

Listing 9

 

/usr/local/bin     /home/jails/dns/usr/local/bin     nullfs ro 0 0
/usr/local/sbin    /home/jails/dns/usr/local/sbin    nullfs ro 0 0
/usr/local/lib     /home/jails/dns/usr/local/lib     nullfs ro 0 0
/usr/local/libdata /home/jails/dns/usr/local/libdata nullfs ro 0 0
/usr/local/share   /home/jails/dns/usr/local/share   nullfs 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 legen Sie dieses Verzeichnis für die Jail manuell an (Listing 10). Es folgen der Start der Jail und die erste Anmeldung mittels ssh. Den Status der Jail verrät das Kommando service (Listing 11).

Listing 10

 

# mkdir -p /home/jails/dns/usr/local/etc/rc.d
# service jail start dns
# ssh admin@dns.example.home
# service jail status dns
 JID IP Address Hostname Path
 dns 192.168.1.9 dns... /home/jails/dns

Listing 11

 

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

Anwendungen

Abbildung 1 zeigt im linken Terminalfenster eine erfolgreiche Anmeldung am Raspberry selbst. Im rechten Fenster sehen Sie eine SSH-Verbindung zur Jail, in der der Name-Server arbeitet. Die Hostnamen und IP-Adressen entstammen dem privaten Netzwerk des Autors.

Abbildung 1: SSH-Logins auf dem Raspberry und in einer Jail.

Wie auf großen Servern bieten Jails auch auf kleinen Systemen wie dem RasPi eine Reihe von Anwendungsmöglichkeiten, beispielsweise als Webserver für die eigene Homepage, eigener Name-Server, Squid als transparenter Webproxy und vieles mehr. Das folgende Beispiel zeigt das Einrichten eines Name-Servers fürs eigene Netzwerk.

Da es noch kein vollständiges Repository für die ARM-Architektur des Raspberry Pi gibt, installieren Sie zunächst auf dem Host das Tool bind99 aus den Ports (Listing 12, Zeile 1). Hier wählen Sie die Optionen für SSL- und GSSAPI-Support ab, da Sie diese für ein kleines Heimnetz nicht benötigen (Zeile 2). Anschließend rufen Sie das Install-Skript auf (Zeile 3) und kopieren 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.

Listing 12

 

# cd /usr/ports/dns/bind99
# make config
# make install clean
# 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

Damit das Programm in der Jail reibungslos funktioniert, nehmen Sie noch die in Listing 13 aufgeführten Änderungen in der Konfigurationsdatei des DNS-Daemons bind vor. Auch die Konfigurationsdatei /etc/rc.conf der Jail ergänzen Sie um die Einträge aus Listing 14. Die weitere Konfiguration des DNS-Dienstes hängt vom Netzwerk ab, um das sich die Namensauflösung kümmert.

Listing 13

 

query-source address 192.168.1.9;
listen-on port 53 { 192.168.1.9; };
allow-query {
 192.168.1.0/24;
};

Listing 14

 

named_enable="YES"
named_chrootdir=""

Auf dem Host fällt die Angelegenheit etwas komplizierter aus. Damit Anfragen an den Name-Server und dessen Antworten ihre jeweiligen Ziele erreichen, ergänzen Sie die Paketfilterregeln. Für den von OpenBSD abstammenden Paketfilter Pf sieht eine mögliche Regel in der /etc/pf.conf etwa so 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 gilt es, den NAT-Daemon via /etc/natd.conf zu konfigurieren (Listing 15), andererseits die Regeln aus Listing 16 im Paketfilter zu ergänzen.

Listing 15

 

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

Listing 16

 

#!/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 starten Sie die DNS-Jail auf dem Host (Listing 17, erste Zeile). Einen Funktionstest nehmen Sie mit dem Kommando aus der zweiten Zeile von Listing 17 vor, das Ergebnis sollte dem im gezeigten Ausgabeprotokoll ähneln.

Listing 17

 

# service jail start dns
# 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

Raspberry Pi Geek kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

Aktuelle Ausgabe

12/2019
RasPi-Alternativen

Diese Ausgabe als PDF kaufen

Preis € 9,99
(inkl. 19% MwSt.)

Stellenmarkt

Neuigkeiten

  • Grußbotschaften

    Mit Sonic Pi zaubern Sie komplexe Sounds, die Sie bei Bedarf sogar noch während des Abspielens modifizieren.

  • Das Runde und das Eckige

    Mit dem MCP4725 ergänzen Sie einen RasPi um einem D/A-Wandler, der bei Bedarf noch weitere Funktionen erfüllt.

  • Alles unter Kontrolle

    Schon ein einfaches Mikrocontrollerboard wie das CY8CKIT-049-42xx bietet erstaunlich viele Möglichkeiten beim Ansteuern von Hardware.

  • Viele Kerne

    Das Spresense Development Board von Sony lässt sich mit der Arduino IDE programmieren und bringt auch ein eigenes Entwickler-SDK mit.

  • Exotische Früchte

    Der aus China stammende Orange Pi positioniert sich mit einem guten Preis und interessanten Features gegen die RasPi-Truppe. Kann er sich auch behaupten?

  • Flexibler Surfer

    Mit dem neuen RasPi 4 setzen Sie einen öffentlichen Webkiosk schnell und kostengünstig auf.

  • Auskunftsfreudig

    Viele Devices, so auch der E.ON-Aura-Controller, verwenden eine Schnittstelle namens REST, um Zustandsdaten zu übermitteln. Mit ein wenig Bastelei lesen Sie diese auch über Ihr Smartphone aus.

  • Doppelt gemessen

    Mit wenig Aufwand und einem Pi Zero realisieren Sie einen mobilen Zweikanal-Spannungsprüfer.

  • Elegant zusammengeführt

    Tizonia streamt Musik von Online-Quellen und lokalen Sammlungen. Die schlanke Architektur macht den Player zur guten Wahl für den Einsatz auf dem RasPi.

  • Kommunikativ

    Nicht jeder traut sich zu, sein eigenes Smartphone zu bauen. Allerdings kann jeder Linux-Nutzer den Raspberry Pi im Handumdrehen zu einem VoIP-Telefon aufrüsten.