[RFC] jail.conf kompatibles rc-Script

Yamagi

Possessed With Psi Powers
Teammitglied
Hallo,
da wir nun mit FreeBSD 9.1 die äußerst praktische "jail.conf" Konfigurationsdatei für das Konfigurieren von Jails haben, fehlt es an einem passenden rc-Script um solche Jails automatisch beim Systemstart starten zu können. Außerdem unterstützt FreeBSDs rc-Script für Jails keine hierarchischen Jails, es können mit ihm also keine Jails in Jails gestartet werden.Zu guter Letzt ist dann noch die fehlende ZFS-Integration zu nennen. Daher habe ich vorhin in die Tasten gehauen und ein eigenes rc-Script "jail2" geschrieben. Features sind:
- Jails werden in der /etc/jail.conf statt in der /etc/rc.conf konfiguriert
- ZFS-Datasets können Jails zugeordnet werden
- Jails können per rc-Script innerhalb von Jails gestartet werden
Den ZFS-Code habe ich mir aus Martin Matuskas "jailrc" geklaut. Es findet sich in der Ports unter sysutils/jailrc. Mein Code soll ebenfalls vorerst als Port angeboten werden.

Kurze Dokumentation der rc.conf Variablen:
- jail2_enable -> jail2 rc-Script ein- oder ausschalten
- jail2_list -> Mit Leerzeichen getrennte Liste der zu startenden Jails. Die Namen entsprechen denen aus der jail.conf
- jail2_$name_zfs -> Mit Leerzeichen getrennte Liste der ZFS-Datasets, die dem jail $name zugeordnet werden.

Um ZFS innerhalb von Jails nutzen zu können, muss das Dataset die Eigenschaft "jailed" besitzen. Zudem muss das Jail die Optionen "allow.mount", "allow.mount.zfs" und "enforce_statfs" gesetzt haben.

Meinen Port findet ihr unter https://github.com/Yamagi/jail2. Da Portmaster es nicht mag, wenn Pakete ohne zugehörige Ports installiert sind, sollte das Repo in ein dauerhaft vorhandenes Verzeichnis geklont werden. Kurze Installationsanleitung:
Code:
% git clone https://github.com/Yamagi/jail2
% cd jail2
% make install clean

Ich würde mich freuen, wenn noch einmal jemand mit mehr sh-Mojo (ich hasse den Syntax) über das Script rüberschauen kann. Patches und Pull-Request sind willkommen. Der Port selbst hingegen sollte okay sein. Nächstes Wochenende oder so reiche ich ihn dann ein.

zur jail.conf: Dort habe ich mittelfristig noch einen Patch auf meiner Liste, der die sehr spärliche Manpage aktualisiert. Zumindest eine Liste alle möglichen Optionen - und das sind viele coole Dinge - sollte dort hinein. Man kann dort wirklich alles konfigurieren, sogaren IP-Adressen beim Jailstart setzen lassen, Dateisysteme mounten und so weiter...
 
Ich finde das super, das du dich darum gekuemmert hast, aber ein zweites jail start script?

Mich hat das nicht vorhandene jail.conf start script schon lange genervt, darum habe ich eine Weiche in die /etc/rc.d/jail eingebaut, die nach der Existenz der /etc/jail.conf schaut und dann einen anderen code zweig ausfuehrt, der recht aehnlich zu deinem Code ist, aber ohne das ZFS Zeugs. ;)
Das ist zugegebenermassen nicht schoen, aber es erspart einem ein zweites Script mit dem Hinweis natuerlich, das wenn eine jail.conf existiert und diese nicht leer ist, das die halt verwendet wird und nur die Parameter jail_enable und jail_list interpretiert.
 
Du hast natürlich recht. Ein um jail.conf erweitertes rc-Script hat es schon aus POLA-Gründen deutlich einfacher es ins Basissystem zu schaffen, als mein Script. Es ist ja mit vorhandenen Konfigurationen nicht mehr kompatibel. Aber ich gebe auch gern zu, dass ich mit das vorhandene Script und auch Martin Matuskas sysutils/jailrc angeschaut habe und beide sehr widerlich fand. Es ist viel Code, teilweise mit unnötig komplexen Konstrukten und so weiter. Für mehr als einen schnellen Hack wären dort erst einmal größere Aufräumarbeiten notwendig und dafür habe ich weder Zeit noch Lust. Ganz zu schweigen von meinem eher geringen sh-Mojo. :)
 
Zuletzt bearbeitet:
Hi,

nur mal kurz zwischen gefragt. Warum wurde das überhaupt so angegangen? Es gibt doch den eigentlich perfekten Port "ezjail" dafür? Oder übersehe ich was?

Danke und Grüße,
Kai
 
Der ist aber nicht im Basissystem. ;) Vielleicht waere das aber wirklich mal eine Erwaegung wert.

Du hast natürlich recht. Ein um jail.conf erweitertes rc-Script hat es schon aus POLA-Gründen deutlich einfacher es ins Basissystem zu schaffen, als mein Script. Es ist ja mit vorhandenen Konfigurationen nicht mehr kompatibel. Aber ich gebe auch gern zu, dass ich mit das vorhandene Script und auch Martin Matuskas sysutils/jailrc angeschaut habe und beide sehr widerlich fand. Es ist viel Code, teilweise mit unnötig komplexen Konstrukten und so weiter. Für mehr als einen schnellen Hack wären dort erst einmal größere Aufräumarbeiten notwendig und dafür habe ich weder Zeit noch Lust. Ganz zu schweigen von meinem eher geringen sh-Mojo. :)
Ich kann auch nicht verstehen, warum sie die jail.conf einfuehren, aber kein ordentliches Script womit man es beim booten starten kann. Mein erster Hack war einfach das ganze mit jail -c <jail> in die /usr/local/etc/rc.d geworfen. Das war mir dann aber zu widerlich, darum habe ich das vorhandene Script einfach umgebaut. Das war nun wirklich nicht viel Arbeit, da jail(8) eigentlich ueber alles noetige verfuegt und die Syntax in der rc.conf kann erhalten bleiben.
 
Zu ezjail: Das ist halt eine philosophische Frage. ezjail ist ein wunderbares Tool, um große Mengen homogener Jails effizient managen zu können. Das möchte ich hier in diesem Einsatzkontext allerdings nicht. Ich will einfach ein paar heterogene Jails nach /usr/jails kippen und dort vergessen. Das soll mit so wenig Magie und Overhead wie möglich ablaufen, tatsächlich sind es sogar nur Minimal-Jails mit jeweils einem Prozess. Unter anderem daher dieses Script.

Ich würde mir ezjail nicht im Basissystem wünschen. Ja, es ist ein wunderbares Tool. Aber wir leben im Jahr 2012, wo ein System "out of the Box" nicht mehr Gott, die Welt und noch ein wenig mehr zufriedenstellen muss. Ich finde eher, dass man das Basissystem noch weiter verschlanken sollte und zu 10.0 einige große Brocken wir BIND und Sendmail rauswerfen und durch Minimalimplementierungen ersetzen. Wer denn das volle Paket will, kann es sich nachinstallieren. Dadurch gewinnen alle 3 Seiten: Das FreeBSD Projekt muss nicht ständig an Software rumpatchen, die nicht in den eigenen Release-Zyklus passt. Man denke nur an die ganze Menge SA zu den verschiedenen BIND-Komponenten, die daraus resultieren. Nutzer, die diese Software nutzen, haben aktuelle Versionen und können schneller aktualisieren, als die SA herausgegeben werden. Nutzer, die sie nicht nutzen, haben keinen Ärger mehr mit sinnlosen, potentiell anfälligen Komponenten. Ein ezjail im Basissystem heißt halt, dass es zwischen 9.0 und 9.1 nicht ein Update gegeben hätte. Von der POLA-Problematik bei größeren Sprüngen ganz zu schweigen.

Zu /etc/rc.d/jail und der jail.conf: Die jail.conf ist aus Notwendigkeit zustande gekommen. Zu Beginn (mit FreeSBD 4.0) waren Jails 800 Zeilen C-Code und nicht mehr als ein weiterer Eintrag in der Prozesstabelle. Nachdem es bei 5.0 und 6.0 bei kleineren Verbesserungen geblieben war, kamen dann halt irgendwann im 7.x-Zyklus die "Multi-IP jails". Damit wurden wurden mehrere IP-Adressen, IPv6 und eigene Routing-Tabellen pro Jail möglich. Mit 8.0 kamen dann die "Jail2", mit einem wesentlich besseren Rechtemanagement, hierarchischen Jails jund so weiter. Schließlich noch die Jail-Integration einiger Dateisysteme. Der ganze vnet-Krempel ist dabei noch gar nicht erwähnt. All das trieb die Komplexität deutlich in die Höhe, weshalb James Gritton das neue jail(8)-Kommando schrieb, um den Kram elegant beherrschbar zu machen. Die jail.conf ist nun daraus gewachsen, dass es sich einfach anbietet, all diese tollen Optionen in einer zentralen Datei verwalten zu können.

Das rc-Script könnte nun natürlich verschwinden und komplett durch die jail.conf ersetzt werden. Das ist schon verlockend, schließlich ist das Script schon sehr komplex (z.b. der in sh geschriebene fstab-Parser) und deckt nur einen Bruchteil der möglichen Optionen von jail(8) ab. Aber rc-Scripte sind halt so eine Sache. Man will / sollte niemanden etwas wegnehmen, weshalb man das aktuelle Script zwar modernisieren könnte, es aber halt alles vorhandene bis auf Weiteres weiterhin unterstützen muss. Dann führen rc-Scripte immer zu langen Diskussionen, bei denen es zwischen Entwicklern mit sh-Mojo und Entwicklern, die die Scripte schreiben, heftig zur Sache geht. Zuletzt ist da das Bootzeit-Argument, das uns schnell in den Bereich der mathematischen Statistik führt... Lange Rede, kurzer Sinn: James Gritton hat im Moment kaum Zeit, alle anderen aus genannten Gründen keinen Bock, weshalb es inzwischen mehrere alternative rc-Scripte für Jails in den Ports gibt, aber kein aktuelles im Basissystem. Ich hoffe / wünsche mir, dass es noch vor 10.0 damit was wird.
 
So ganz nachvollziehen kann ich das immer noch nicht. Das Script muss ja keine eierlegende Wollmilchsau werden, sondern die meisten Nutzer wollen doch einfach nur die Jails beim Systemstart starten.

Ohne Garantie, Haftung usw. aber bei mir funktioniert diese Version gegen 9.1 RC-1 und ich hab auch nicht viel "sh Mojo": ^^
Code:
--- /etc/rc.d/jail
+++ temp/jail.sh	
@@ -568,8 +568,21 @@
 	echo -n 'Starting jails:'
 	_tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \
 	    err 3 "$name: Can't create temp dir, exiting..."
-	for _jail in ${jail_list}
-	do
+	if [ -e /etc/jail.conf ]; then
+		for _jail in ${jail_list}
+		do
+			if [ -f /var/run/jail_${_jail}.id ]; then
+				echo -n " [${_jail} already running (/var/run/jail_${_jail}.id exists)]"
+				continue;
+			fi
+
+			jail -c -i -J /var/run/jail_${_jail}.id ${_jail} > /dev/null 2>&1
+
+			echo -n " ${_jail}"
+		done	
+	else
+		for _jail in ${jail_list}
+		do
 		init_variables $_jail
 		if [ -f /var/run/jail_${_jail}.id ]; then
 			echo -n " [${_hostname} already running (/var/run/jail_${_jail}.id exists)]"
@@ -679,6 +692,7 @@
 		rm -f ${_tmp_jail}
 	done
 	rmdir ${_tmp_dir}
+	fi
 	echo '.'
 }
 
@@ -687,8 +701,14 @@
 	echo -n 'Stopping jails:'
 	for _jail in ${jail_list}
 	do
-		if [ -f "/var/run/jail_${_jail}.id" ]; then
+		if [ -f "/var/run/jail_${_jail}.id" ] && [ -e /etc/jail.conf ]; then
 			_jail_id=$(cat /var/run/jail_${_jail}.id)
+
+			jail -r -q ${_jail} > /dev/null 2>&1
+			rm /var/run/jail_${_jail}.id
+
+			echo -n " ${_jail}"
+		elif [ -f "/var/run/jail_${_jail}.id" ]; then 
 			if [ ! -z "${_jail_id}" ]; then
 				init_variables $_jail

Ein Vorteil der vollstaendigen systemintegration fand ich aber immer, das die Software meist besser und stabiler lief, auch wenn sie nicht immer auf dem neusten Stand war, aber allein aufgrund der Tatsache, das es mit dem System ausgeliefert wurde, verhalf der 3rd Party Software immer zu einer groesseren Testbasis. Auch wenn das ein groesserer Aufwand fuer die Entwickler bedeutet.
Andererseits ziehe ich auch eher ein schlankes Grundsystem vor, was sich aber auch so erreichen laesst. Man kann die Welt ja auch ohne BIND und Co. bauen.
 
Es fehlt in der Startfunktion gleich zu Anfang ein
Code:
devfs_init_rulesets
um die devfs Rulesets zu laden. Ohne diesen Aufruf haben die Jails immer ein uneingeschränktes /dev.
 
Crest schrieb:
Es fehlt in der Startfunktion gleich zu Anfang ein
Code:
devfs_init_rulesets
um die devfs Rulesets zu laden. Ohne diesen Aufruf haben die Jails immer ein uneingeschränktes /dev.
So, ich habe nun endlich die Zeit gefunden, mich damit zu befassen. Dort fehlt natürlich kein Aufruf zum Initialisieren des devfs, da devfs von jail(8) konfiguriert wird. Mit einem
Code:
# Devfs
mount.devfs;

# Jail ruleset by default
devfs_ruleset=4;
wird das Ruleset "4" gesetzt und alles ist, wie es sein soll. :)
 
Welche Methode würdet ihr vorziehen um die Jails miteinander kommunizieren zu lassen?
Mit Hilfe von jail.conf versteht sich :)
 
Entweder IP Sockets oder Unix Domain Sockets. Für Unix Domain Sockets brauchst du allerdings nen Nullfs auf das beide Jails Zugriff haben und Nullfs hat unter FreeBSD keinen guten Ruf. Angeblich sollen die bekannten Probleme in FreeBSD 9.1 alle behoben sein. Ich würde dennoch in den meisten Fällen einfach nen IP Socket (mit Routing über nen Loopback Interface) verwenden. Notfalls kann man immernoch socat verwenden um zwei Unix Domain Sockets per IP zu verbinden.
 
Danke Crest,
es geht auch um FreeBSD 9.1
Konkreter, es gibt mehrere Webserver-jails und ein Datenbank-jail, worauf die Webserver zugreifen sollen. Aber nicht untereinander!
Hier muss man Sicherheit und Performance als auch Stabilität abwiegen.
Bis jetzt war immer IP Socket die Lösung, wenige Ergänzungen in der rc.conf wie zB.:
# Jails
jail_enable=”YES”
jail_list=”ssh”
jail_ssh_rootdir=”/usr/jails/ssh”
jail_ssh_hostname=”ssh.local”
jail_ssh_ip=”192.168.1.18″
jail_ssh_devfs_enable=”YES”
jail_ssh_exec_start=”/bin/sh /etc/rc”

ifconfig_re1_alias0=”inet 192.168.1.18 netmask 255.255.255.255″
und schon rennt es. Jetzt möchte ich das ganze mit Hilfe von jail.conf einrichten, denn jail.conf soll ja bekanntlich die rc.conf ablösen, was die Jailverwaltung angeht.
Mir ist nicht ganz klar, was es mit der vnet auf sich hat.
 
Zuletzt bearbeitet:
VIMAGE oder vnet ist ein experimentelles Feature in FreeBSD mit eine Jail ihren eigenen TCP/IP Stack bekommen kann. Solch eine Jail verfügt über eigene (pseudo-) NICs, eigene Routingtable(-s) und eigene Firewall etc. Noch ist das ganze allerdings etwas wacklig. Ich nutze es auf einer Kiste und es funktioniert solange man nicht zu oft VNETs zerstört. Viele wollen gerne vnet ausgereift haben, aber kaum jemand will es ausreichend testen.
 
Wärst du bitte so lieb und teilst mit mir und den ganzen Volk hier, wie du das ganze einrichtest (Schritt für Schritt)?
Ich will es noch nicht produktiv einsetzen, doch testen und üben würde ich schon gerne :)
Und welche Vorteile hat vnet den oben von dir aufgeführten Methoden gegenüber?
 
Zurück
Oben