www.fabiankeil.de/blog-surrogat/2006/06/12/jail-experimente-mit-ezjail.html

Jail-Experimente mit ezjail

Vereinfacht dargestellt ist ein Jail unter FreeBSD ein chroot, das nicht nur auf Datei-System- sondern auch auf Prozess-Ebene arbeitet. Sehr praktisch um auf Servern verschiedene Benutzer von einander abzuschotten, oder einfach um die Ordnung im System etwas zu erhöhen.

Die Prozesse im Jail sehen nur die Prozesse im gleichen Jail, selbst kompromittierte Prozesse mit Root-Rechten können höchstens innerhalb der Schranken des eigenen Jails wüten, ohne den Rest des Systems zu gefährden. Jails laufen im Kernel des Host-Systems, nutzen im Normallfall aber ein eigenes Userland und Port-System.

Dadurch entstehen keine Virtualisierungs-Kosten, als Nachteil werden aber die meisten System-Variablen (schreibgeschützt) geerbt und können nicht für jedes Jail einzeln geändert werden.

Jedes Jail braucht eine eigene Netz-Adresse, da FreeBSD jedoch jeder Netzwerk-Karte mehr als eine Adresse zu ordnen kann, ist das kein Problem, sondern erlaubt im Gegenteil die weitere Abschottung: das Jail bekommt eine private Adresse, die nicht im Internet geroutet wird. Über NAT kann im Host-System die Kommunikation mit der Außenwelt erlaubt und auf die erforderlichen Ports beschränkt werden.

Ports- und Package-Test im Jail

Für die weitgehend fertig gestellten trans-proxy-tor und dns-proxy-tor-Ports wollte ich sicher stellen, keine Abhängigkeiten vergessen zu haben und dass sie sich auch auf einem jungfräulichen System installieren lassen. Eine Möglichkeit wäre FreeBSD auf einem Testsystem zu installieren, die andere Möglichkeit ein Test-Jail.

Von Zeit-Aufwand gäbe es für das erste Test-System keinen Unterschied: da ich mir erst etwas Grundlagen-Wissen zu Jails besorgen musste und auf kleinere Probleme gestoßen bin, hat sich der Test etwas verzögert. Die Einarbeitung rentiert sich aber bereits beim zweites Test-System: die Installation eines kompletten Betriebs-Systems dauert immer gleich lange, die Installation eines neuen Jails mit Routine etwas weniger:

fk@TP51 ~ $sudo ifconfig lo2 alias 192.168.6.101
fk@TP51 ~ $time sudo ezjail-admin create test 192.168.6.101
/usr/jails/test/COPYRIGHT
/usr/jails/test/basejail
[...]
/usr/jails/test/var/tmp/vi.recover
/usr/jails/test/var/yp
1905 blocks
Warning: Some services already seem to be listening on all IP, (including 192.168.6.101)
  This may cause some confusion, here they are:
root     Xorg       1021  1  tcp4   *:6000                *:*
root     ntpd       580   4  udp4   *:123                 *:*
bind     named      513   22 udp4   *:50687               *:*
root     syslogd    407   8  udp4   *:514                 *:*

real    0m2.223s
user    0m0.100s
sys     0m0.233s

Wie die Warnung zeigt, ist mein Host-System noch nicht vollständig für Jails konfiguriert und ein paar Ports auf der Jail-IP werden von Prozesse im Host-System blockiert, für meinen Ports-Test stellte das aber keine Probleme dar.

ezjail-admin ist Teil der Skriptsammlung zur Jail-Administration ezjail. ezjail baut auf FreeBSDs eigenen Jail-Programmen auf und erleichtert die Arbeit mit Jails weiter.

Um Speicherplatz zu sparen kopiert ezjail-admin bei der Einrichtung eines neuen Jails nur die Verzeichnisse und Dateien, auf die das Jail schreibend zugreifen können muss. Der Rest wird schreibgeschützt über NullFS aus einem Basis-Jail eingebunden. Der Platzbedarf eines neuen Jails ist daher vernachlässigbar, ein frisch angelegtes Jail wiegt keine zwei Mega Byte:

fk@TP51 ~ $sudo du -sh /usr/jails/test/
1.4M    /usr/jails/test/

Nach der Installation einzelner Ports kommt natürlich deutlich Gewicht dazu, mein Port-Test-Jail kommt auf etwas über 50 Mega Byte:

fk@TP51 ~ $sudo du -sh /usr/jails/porttest/
53M    /usr/jails/porttest/

Der Abhängigkeits-Test war erfolgreich, nach Eingabe von make install clean in /usr/ports/security/trans-proxy-tor (aus Sicht des Jails, in Wirklichkeit unterhalb von /usr/jails/porttest) vermeldet pkg_info folgende Programme als installiert:

dns-proxy-tor-0.0.9 Resolves DNS requests through Tor
gettext-0.14.5_2    GNU gettext package
gmake-3.80_2        GNU version of 'make' utility
libevent-1.1a_1     Provides an API to execute callback functions on certain ev
libiconv-1.9.2_2    A character set conversion library
libtool-1.5.22_2    Generic shared library support script
p5-Event-Lib-1.00_1 Makes libevent(3) accessible with Perl
perl-5.8.8          Practical Extraction and Report Language
tor-devel-0.1.1.20  An anonymizing overlay network for TCP
trans-proxy-tor-0.0.9 Transparent proxy used to redirect TCP connections into Tor
tsocks-1.8.b5_3     Allow non SOCKS aware applications to use SOCKS without mod

Beim Gang über Binär-Pakete wird die Liste noch mal deutlich schlanker, in einem zweiten Jail wurden die im ersten Jail gebauten Pakete getestet, so dass die Build-Abhängigkeiten wegfielen:

dns-proxy-tor-0.0.9 Resolves DNS requests through Tor
libevent-1.1a_1     Provides an API to execute callback functions on certain ev
p5-Event-Lib-1.00_1 Makes libevent(3) accessible with Perl
perl-5.8.8          Practical Extraction and Report Language
tor-devel-0.1.1.20  An anonymizing overlay network for TCP
trans-proxy-tor-0.0.9 Transparent proxy used to redirect TCP connections into Tor
tsocks-1.8.b5_3     Allow non SOCKS aware applications to use SOCKS without mod

Was sich auch auf den Speicherplatz auswirkt:

fk@TP51 /usr/local/etc/ezjail $sudo du -sh /usr/jails/packagetest/
 35M    /usr/jails/packagetest/

Die /etc/rc.conf in beiden Jails ist bis auf die Tor-IP-Nummern identisch. Im Port-Test-Jail:

sendmail_enable="NONE"
sshd_enable=YES
tor_enable=YES

trans_proxy_tor_enable="YES"
trans_proxy_tor_bind_addr="192.168.6.100"
trans_proxy_tor_socks_addr_and_port="192.168.6.100:9050"

dns_proxy_tor_enable="YES"
dns_proxy_tor_bind_port="53"
dns_proxy_tor_start_privileged="YES"
dns_proxy_tor_bind_addr="192.168.6.100"
dns_proxy_tor_ctrl_addr_and_port="192.168.6.100:9051"
dns_proxy_tor_socks_addr_and_port="192.168.6.100:9050"
dns_proxy_tor_socks_resolve="YES"

Im Package-Test-Jail:

sendmail_enable="NONE"
sshd_enable=YES
tor_enable=YES

trans_proxy_tor_enable="YES"
trans_proxy_tor_bind_addr="192.168.6.101"
trans_proxy_tor_socks_addr_and_port="192.168.6.101:9050"

dns_proxy_tor_enable="YES"
dns_proxy_tor_bind_port="53"                            
dns_proxy_tor_start_privileged="YES"                    
dns_proxy_tor_bind_addr="192.168.6.101"                 
dns_proxy_tor_ctrl_addr_and_port="192.168.6.101:9051"   
dns_proxy_tor_socks_addr_and_port="192.168.6.101:9050"  
dns_proxy_tor_socks_resolve="YES"

Und wie beabsichtigt werden trans-proxy-tor, dns-proxy-tor und Tor beim Jail-Start mit gestartet. Ein ps -wwaux innerhalb des Port-Test-Jails:

USER               PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
root             20177  0.0  0.2  1380   804  ??  SsJ   6:26PM   0:00.01 /usr/sbin/syslogd -s
_tor             20196  0.0  1.9 10872  9980  ??  SJ    6:26PM   0:01.86 /usr/local/bin/tor -f /usr/local/etc/tor/torrc --pidfile /var/run/tor/tor.pid --runasdaemon 1 --datadirectory /var/db/tor --user _tor --group _tor
_dns-proxy-tor   20204  0.0  0.8  4920  4268  ??  IsJ   6:26PM   0:00.00 /usr/bin/perl /usr/local/bin/dns-proxy-tor -b 192.168.6.100:53 -p /usr/local/var/run/dns-proxy-tor/dns-proxy-tor.pid -v info -l /var/log/dns-proxy-tor.log -t 192.168.6.100:9051 -s 192.168.6.100:9050 -u _dns-proxy-tor:_dns-proxy-tor
_trans-proxy-tor 20215  0.0  0.8  4708  4040  ??  SsJ   6:26PM   0:00.00 /usr/bin/perl /usr/local/bin/trans-proxy-tor -b 192.168.6.100:1112 -p /usr/local/var/run/trans-proxy-tor/trans-proxy-tor.pid -v debug -l /var/log/trans-proxy-tor.log -s 192.168.6.100:9050
root             20261  0.0  0.4  3040  2092  ??  IsJ   6:26PM   0:00.00 /usr/sbin/sshd
root             20268  0.0  0.2  1396   884  ??  SsJ   6:26PM   0:00.00 /usr/sbin/cron -s
root             20325  0.0  0.5  5836  2392  ??  IsJ   6:31PM   0:00.18 sshd: fk [priv] (sshd)
fk               20328  0.0  0.5  5812  2400  ??  SJ    6:31PM   0:00.04 sshd: fk@ttyph (sshd)
fk               20329  0.0  0.2  1784  1208  ph  SsJ   6:31PM   0:00.03 -sh (sh)
fk               20336  0.0  0.1  1432   744  ph  R+J   6:32PM   0:00.00 ps -wwaux

Und innerhalb des Package-Test-Jails:

USER               PID %CPU %MEM   VSZ   RSS  TT  STAT STARTED      TIME COMMAND
root             20000  0.0  0.2  1380   804  ??  SsJ   6:26PM   0:00.01 /usr/sbin/syslogd -s
_tor             20019  0.0  1.6  8896  8024  ??  SJ    6:26PM   0:02.24 /usr/local/bin/tor -f /usr/local/etc/tor/torrc --pidfile /var/run/tor/tor.pid --runasdaemon 1 --datadirectory /var/db/tor --user _tor --group _tor
_dns-proxy-tor   20027  0.0  0.8  4920  4320  ??  IsJ   6:26PM   0:00.00 /usr/bin/perl /usr/local/bin/dns-proxy-tor -b 192.168.6.101:53 -p /usr/local/var/run/dns-proxy-tor/dns-proxy-tor.pid -v info -l /var/log/dns-proxy-tor.log -t 192.168.6.101:9051 -s 192.168.6.101:9050 -u _dns-proxy-tor:_dns-proxy-tor
_trans-proxy-tor 20038  0.0  0.8  4708  4092  ??  SsJ   6:26PM   0:00.01 /usr/bin/perl /usr/local/bin/trans-proxy-tor -b 192.168.6.101:1112 -p /usr/local/var/run/trans-proxy-tor/trans-proxy-tor.pid -v debug -l /var/log/trans-proxy-tor.log -s 192.168.6.101:9050
root             20084  0.0  0.4  3040  2092  ??  IsJ   6:26PM   0:00.00 /usr/sbin/sshd
root             20091  0.0  0.2  1396   884  ??  SsJ   6:26PM   0:00.00 /usr/sbin/cron -s
root             20292  0.0  0.5  5836  2392  ??  IsJ   6:28PM   0:00.10 sshd: fk [priv] (sshd)
fk               20295  0.0  0.5  5812  2400  ??  SJ    6:29PM   0:00.13 sshd: fk@ttyp3 (sshd)
fk               20296  0.0  0.2  1784  1208  p3  SsJ   6:29PM   0:00.04 -sh (sh)
fk               20334  0.0  0.1  1432   744  p3  R+J   6:32PM   0:00.00 ps -wwaux

Mission erfolgreich.

Die Zahl der Prozesse könnte man sogar noch weiter verringern: cron und sshd werden für den Betrieb von dns-proxy-tor trans-proxy-tor sowie Tor nicht benötigt, und könnten auch (wieder) deaktiviert werden.

Zu überlegen bleibt noch, ob Tor wieder aus den Abhängigkeiten für dns-proxy-tor und trans-proxy-tor gestrichen werden sollte. Eigentlich reicht es aus, wenn Tors Socks- und der Control-Port erreichbar sind, prinzipiell könnten dns-proxy-tor, trans-proxy-tor und Tor auch auf drei Systeme (oder Jails) verteilt werden.

Konfiguration im Host-System

trans-proxy-tor benötigt Zugriff auf /dev/pf um zu erfahren, von welcher Adresse die von PF abgefangenen Verbindungen ursprünglich kamen. /dev/pf wird für die meisten Jails nicht benötigt und da der Zugriff auch ein Sicherheits-Risiko darstellt, ist es üblicherweise in Jails unsichtbar.

Über devfs-Regeln kann man das ändern, in der Konfigurations-Datei /etc/devfs.rules habe ich die bereits vorhandenen Jail-Regeln kopiert und um einen pf-Regelsatz erweitert:

fk@TP51 ~ $tail -n 15 /etc/devfs.rules 
# Devices usually found in a jail.
#
[devfsrules_jail=4]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login

# Devices usually found in a pf jail.
#
[devfsrules_pf_jail=5]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add path pf unhide mode 0660 group _trans-proxy-tor

In ezjails Jail-Konfigurations-Dateien in /usr/local/etc/ezjail/ musste der neue Regelsatz in der Variablen jail_JAILNAME_devfs_ruleset angegeben werden.

Damit die Jail-Adressen bereits beim Systemstart vorhanden sind, enthält die /etc/rc.conf die Zeilen:

cloned_interfaces="lo1 lo2"
ifconfig_lo2="192.168.6.100 up"
ifconfig_lo2_alias0="inet 192.168.6.101"

(lo1 im Host-System für die PF-Konfiguration benötigt und hat nichts mit den Jails zu tun)