creative commons
Garder son phacochère familier dans un enclos
icone administration-systeme
Signature :
GNU/Linux Magazine
Sommaire de l'article :
Ton phacochère [1] familier, bien que très sympathique, continue de faire quelques bêtises dans ta maison, bouffer les meubles, vider sa gamelle un peu partout, voire embêter tes autres colocataires. Ne voulant pas te résoudre à l’enfermer dans une niche (chroot) trop étroite, tu décides de lui construire un enclos qui lui sera dédié et dans lequel il pourra faire ce que bon lui semble sans nuire à son entourage (continue to be root).

Pré-requis

  • un terrain propice (avoir un FreeBSD sous la main, être root dessus) ;
  • un peu d’espace disque, car on va dupliquer tout le userland dans l’enclos ;
  • avoir les sources dans /usr/src.
Avant d'envisager la construction Avant de pouvoir configurer son enclos (jail), il faut déjà préparer le terrain tout autour (configurer le serveur qui va accueillir les jails pour que les daemons n’écoutent plus sur toutes les IP). Donc, tout autour de l’emplacement de son futur enclos, on fixe les branches qui dépassent, on ramasse les feuilles mortes, on passe un coup de râteau et on laisse un emplacement le plus nickel possible.
  • sshd Utilisez sshd_flags=”-oListenAddress=Public_IP” dans votre fichier /etc/rc.conf ou modifiez /etc/ssh/sshd_config (et redémarrez le daemon sshd par /etc/rc.d/sshd restart)
  • sendmail
Ajoutez DAEMON_OPTIONS(`Addr=Public_IP’) à votre fichier de macro sendmail (fichier mc)
  • inetd
Si vous utilisez inetd, il faut ajouter inetd_flags=”-a Public_IP” à votre /etc/rc.conf (attention à bien reprendre les flags existants).
  • named
Utilisez la directive listen-on { Public_IP; }; dans votre fichier de configuration named.conf.
  • apache
Utilisez la directive Listen Public_IP:80 dans votre /usr/local/etc/httpd.conf
  • etc.
Idem pour les autres daemons écoutant sur toutes les IP.

Un enclos en kit

Tu as acheté ton enclos au même endroit que ton abri de jardin et, bien aimablement, le fabricant a fourni une aide minimale au montage des différents éléments ; pourtant, tout n’est pas aussi simple que chez Ikea. Tu n’auras pas de notice imprimée recto-verso t’expliquant ce qu’est une vis, mais cela ne signifie pas qu’il n’y a pas de documentation ! Extrait de la page de man de jail [2]
EXAMPLES
Setting up a Jail Directory Tree
To set up a jail directory tree containing an entire FreeBSD
distribution, the following sh(1) command script can be used:
D=/here/is/the/jail
cd /usr/src
mkdir -p $D
make world DESTDIR=$D
make distribution DESTDIR=$D
mount_devfs devfs $D/dev
Si tu as compilé ton système récemment, tu peux remplacer make world DESTDIR=$D par make installworld DESTDIR=$D ce qui te fera économiser tout le temps de la compilation. Une méthode plus Gruik consiste à monter une image ISO de FreeBSD et à extraire l’environnement de base comme s’il s’agissait d’une installation d’un système :
# ggatel create 6.2-RELEASE-i386-disc1.iso
ggate0
# mount -t cd9660 /dev/ggate0 /mnt
# cd /mnt/6.2-RELEASE/base
# mkdir -p /home/jails/gcujail
# cat base.?? | tar --unlink -vxpzf - -C /home/jails/gcujail
On va créer manuellement le /dev/* du jail et y "entrer" :
# mount_devfs devfs /home/jails/gcujail/dev
# jail -l -U root /home/jails/gcujail gcujail 127.0.0.1 /bin/csh
On regarde un peu dans quel environnement on se retrouve :
gcujail# uname -a
FreeBSD gcujail 7.0-CURRENT FreeBSD 7.0-CURRENT #33: Sat Mar 17 19:35:45 CET 2007 root@stealth.domain.tld:/usr/obj/usr/src/sys/STEALTH i386
gcujail# ls -al
-rw-r--r-- 2 root wheel 801 Jan 12 07:42 .cshrc
-rw-r--r-- 2 root wheel 251 Jan 12 07:42 .profile
-r--r--r-- 1 root wheel 6196 Jan 12 07:42 COPYRIGHT
drwxr-xr-x 2 root wheel 1024 Jan 12 07:41 bin
drwxr-xr-x 5 root wheel 512 Jan 12 07:42 boot
[snip]
gcujail# mount
/dev/ad0s1f on / (ufs, local, soft-updates)
On s’aperçoit que le système dans le jail hérite de la version du kernel du serveur hôte malgré le userland "décalé" et que la sortie de la commande mount ne montre que la partition accueillant le jail. De même, depuis le jail, la commande uptime montre le résultat du serveur hôte et pas du jail en lui-même. Pour vous en convaincre, créez le fichier /etc/rc.local contenant
echo `date` >> /root/boot.log
dans le jail ; amusez-vous à faire plusieurs reboot et regarder le fichier de log et l’uptime. Pour le moment, le user root du jail voit tout /dev à l’identique de ce qu’il se trouve sur le serveur hôte, ce qui peut être très dangereux si vous n’avez pas confiance dans le root du jail, car il a accès à tous les disques et partitions, à la configuration de vos règles de firewall...

Et la barrière électrique ?

Dans un jail correctement configuré comme plus loin dans l’article, le root du jail ne peut pas configurer son propre firewall et, par conséquent, il ne peut pas choisir et setter ses rules.
# pfctl -s rules
pfctl: /dev/pf: No such file or directory
Toute la configuration firewall se fait "au-dessus" du jail, sur le serveur hôte. Configuration par défaut Le système FreeBSD comporte une configuration par défaut et des exemples pour configurer votre/(vos) jail(s). Ces informations se trouvent dans /etc/defaults/rc.conf qui est lu par les scripts de démarrage ; toutes les modifications doivent se faire dans /etc/rc.conf. Voici les paramètres communs à tous les jails :
##############################################################
### Jail Configuration #######################################
##############################################################
jail_enable="NO" # Set to NO to disable starting of any jails
jail_list="" # Space separated list of names of jails
jail_set_hostname_allow="YES" # Allow root user in a jail to change its hostname
jail_socket_unixiproute_only="YES" # Route only TCP/IP within a jail
jail_sysvipc_allow="NO" # Allow SystemV IPC use from within a jail
Et voici la liste des paramètres spécifiques à un jail qui peuvent être repris pour la configuration de vos jails : Voir Figure 1,

Configurons notre enclos

Voici ce que j’ai mis dans le /etc/rc.conf du serveur hôte ; l’utilisation de chaque variable sera détaillée plus loin.
# jail
jail_enable="YES"
jail_list="gcujail"
# Emplacement du jail et son hostname
jail_gcujail_rootdir="/home/jails/gcujail"
jail_gcujail_hostname="gcujail.gcu.info"
# ip du jail et interface qui portera l'alias
jail_gcujail_ip="192.168.0.10"
jail_gcujail_interface="bge0"
# on veut un /dev restreint dans le jail
jail_gcujail_devfs_enable="YES"
jail_gcujail_devfs_ruleset="devfsrules_jail"
# l'option -J permettra d'avoir des informations sur le jail
jail_gcujail_flags="-l -U root -s 1 -J /var/run/jail_gcujail.jid"
Dans le rc.conf du jail, on lui indique de démarrer sshd comme d’habitude :
sshd_enable="YES"
sendmail_enable="NONE"
Apparemment, il n’est plus indispensable de commenter adjkerntz -a dans /etc/crontab du système jailé. Démarrons ce jail et regardons ce qui est vu du serveur hôte.
# /etc/rc.d/jail start gcujail
Configuring jails:.
Starting jails: gcujail.gcu.info.
# ifconfig bge0
bge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=98<VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
[snip]
inet 192.168.0.10 netmask 0xffffffff broadcast 192.168.0.10
# mount
[snip]
devfs on /home/jails/gcujail/dev (devfs, local)
Ce qu’il s’est produit :
  • l’alias IP 192.168.0.10 est automatiquement ajouté sur l’interface précisée par jail_gcujail_ip ;
  • devfs s’occupe de monter le /dev du jail au démarrage de celui-ci ;
  • les devices visibles dans le /dev du jail ont réduit comme peau de chagrin et ne permettent plus d’outrepasser les devices sur le serveur hôte (faites un ls pour vérifier).
Voir Figure 2 Vous aurez remarqué que le jail est démarré en securelevel [3] à 1 grâce à -s 1 de la variable jail_gcujail_flags.

Les logs

Activons les logs de la console dans le jail (fichier /home/jails/gcujail/etc/syslog.conf) :
console.info;*.err;kern.warning;auth.notice /var/log/console.log
Créons le fichier en question et redémarrons le jail :
# touch /home/jails/gcujail/var/log/console.log
# /etc/rc.d/jail restart
Ce qui aura pour effet de créer un fichier /var/log/jail_gcujail_console.log sur le serveur hôte reprenant les logs de la console.

Remplir l'enclos

Afin d’économiser un peu d’espace disque, il vous semble évident que vous allez limiter au strict minimum les informations dupliquées sur le serveur hôte ainsi que dans votre (vos) jail(s). Typiquement, on partage /usr/src et /usr/ports :
# mount -t nullfs -o ro /usr/src /home/jails/gcujail/usr/src
# mount -t nullfs -o ro /usr/ports /home/jails/gcujail/usr/ports
# mount | grep nullfs
/usr/src on /home/jails/gcujail/usr/src (nullfs, local, read-only)
/usr/ports on /home/jails/gcujail/usr/ports (nullfs, local, read-only)
Il est possible d’ajouter ces points de montage dans le /etc/fstab du serveur hôte afin que le jail y ait accès de manière permanente, mais attention, ces répertoires peuvent être supprimés depuis le jail ! Pour plus de sécurité, il est recommandé de monter /usr/src et /usr/ports/ en read-only dans le jail et de modifier la manière dont sont compilés les ports à partir du jail (pour pouvoir utiliser un /usr/ports en RO). Si vous devez gérer plusieurs enclos, il est préférable de mettre en place un export NFS en read-only de ces répertoires vers les jails, ce qui évitera les points de montage en nullfs :
# mkdir -p /usr/obj/portsbuild /usr/obj/distfiles
Et on édite le /etc/make.conf du jail pour y ajouter les lignes suivantes :
WRKDIR=/usr/obj/portsbuild
DISTDIR=/usr/obj/distfiles
Il suffit d’ajouter les ports dans le jail comme d’habitude. Ceci aura pour inconvénient d’ignorer le contenu de /usr/ports/distfiles ; n’hésitez pas à en recopier les fichiers s’ils existent, ce qui évitera de perdre de la bande passante et du temps. Pensez à faire régulièrement le ménage dans /usr/obj/distfiles du jail sans quoi de l’espace disque sera perdu pour rien.

Sécuri-clos

Au cours de l’installation du jail, tu as constaté qu’il tenait sur une seule partition, ce qui est assez gênant quand tu veux avoir des points de montage avec des droits différents. Par exemple, j’ai pris pour habitude d’utiliser un /tmp de taille fixe, monté en RAM, avec des droits noexec et nosuid. Habituellement, je déclare dans /etc/rc.conf les lignes suivantes :
tmpmfs="YES"
tmpsize="512m"
tmpmfs_flags="-S -o noexec,nosuid"
qui ont pour résultat :
# mount | grep tmp
/dev/md0 on /tmp (ufs, local, noexec, nosuid)
Mais cela ne fonctionne pas dans gcujail tout simplement parce que les commandes mdconfig n’ont pas accès aux devices /dev/md* depuis le jail ! Les ajouter serait une fausse bonne idée, puisque cela donnerait accès aux devices md* appartenant au serveur hôte depuis l’intérieur du jail. Oh, tu peux essayer de bricoler le /etc/fstab du jail, si tu arrives à quelque chose de concluant tu es prié d’écrire à Pinpin (ou à l’auteur). La solution, peu gracieuse, trouvée pour l’instant, est la suivante :
  • sur le serveur hôte, on crée un fichier vide d’une taille fixe :
# dd if=/dev/zero of=/home/jails/gcujail.tmp bs=1m count=512
512+0 records in
512+0 records out
536870912 bytes transferred
Edition du fichier /etc/fstab.gcujail (qui sera pris par défaut par le script jail) : Voir Figure 3 et on ajoute la gestion du mount dans le fichier /etc/rc.conf du serveur hôte pour ce jail :
jail_gcujail_mount_enable="YES"
Par défaut, le fichier fstab du jail pris en compte par la variable jail_gcujail_fstab sera /etc/fstab.gcujail. On redémarre le jail :
# /etc/rc.d/jail restart
# mount | grep md
/dev/md1 on /home/jails/gcujail/tmp (ufs, local, noexec, nosuid)
Le /tmp de notre jail est bien d’une taille limitée et monté avec des droits moins permissifs. Note Un inconvénient de cette méthode est que bien qu’un /etc/rc.d/jail stop démonte le /tmp du jail, cela ne libère pas le device md qui y était associé et il faut le faire à la mimine depuis le serveur hôte !

Quota-clos

Jusqu’à présent, ton phacochère est tout seul dans son enclos. Il peut le décorer comme il lui plaît et ajouter ce dont il a besoin, mais, surtout, il peut continuer à prendre tout l’espace disponible dans son enclos. Il y a au moins deux solutions pour résoudre ce problème :
  • mettre les répertoires accueillant les jails dans des partitions physiques et donc de taille fixe ;
  • utiliser l’astuce d’un filesystem sur un fichier comme ce qu’on a fait avec /home/jails/gcujail.tmp, ce système de fichiers étant monté depuis le système hôte avant le démarrage du jail.

Manager plusieurs enclos

Divers programmes sont disponibles dans les ports afin de manager plusieurs jails plus facilement, liste évidemment non exhaustive :
# make search name=jail | grep -E "^Port|^Path|^Info"
Port: jailaudit-1.2
Path: /usr/ports/security/jailaudit
Info: Script to generate portaudit reports for jails
Port: ezjail-2.0.1
Path: /usr/ports/sysutils/ezjail
Info: A framework to easily create, manipulate and run FreeBSD jails
Port: jailadmin-1.8_2
Path: /usr/ports/sysutils/jailadmin
Info: A system for managing a set of named jails
Port: jailctl-0.71
Path: /usr/ports/sysutils/jailctl
Info: Jail management tool
Port: jailer-1.1.2
Path: /usr/ports/sysutils/jailer
Info: Manage FreeBSD jail startup, shutdown and console
Port: jailuser-1.9_1
Path: /usr/ports/sysutils/jailuser
Info: Builds a chrooted environment
Port: jailutils-1.0
Path: /usr/ports/sysutils/jailutils
Info: Several utilities for managing jails
Port: p5-BSD-Jail-Object-0.02
Path: /usr/ports/sysutils/p5-BSD-Jail-Object
Info: An object oriented perl interface to jail(2)
Pour une gestion plus facile des jails depuis le serveur hôte, je conseille l’installation des ports jailadmin et jailutils ; l’upgrade des enclos se fait de la même manière qu’un serveur FreeBSD (y compris pour le mergemaster) sauf qu’on change la variable $DESTDIR pour pointer dans le répertoire du jail à mettre à jour. Figure 1
#
# To use rc's built-in jail infrastructure create entries for
# each jail, specified in jail_list, with the following variables.
# NOTES:
# - replace 'example' with the jail's name.
# - except rootdir, hostname and ip, all of the following variables may be made
#   global jail variables if you don't specify a jail name (ie. jail_interface).
#
#jail_example_rootdir="/usr/jail/default"       # Jail's root directory
#jail_example_hostname="default.domain.com"     # Jail's hostname
#jail_example_ip="192.168.0.10"                 # Jail's IP number
#jail_example_interface=""                      # Interface to create the IP alias on
#jail_example_exec_start="/bin/sh /etc/rc"              # command to execute in jail for starting

#jail_example_exec_afterstart0="/bin/sh command"        # command to execute after the one for
                                                        # starting the jail. More than one can be
                                                        # specified using a trailing number
#jail_example_exec_stop="/bin/sh /etc/rc.shutdown"      # command to execute in jail for stopping
#jail_example_devfs_enable="NO"                 # mount devfs in the jail
#jail_example_fdescfs_enable="NO"               # mount fdescfs in the jail
#jail_example_procfs_enable="NO"                # mount procfs in jail
#jail_example_mount_enable="NO"                 # mount/umount jail's fs
#jail_example_devfs_ruleset="ruleset_name"      # devfs ruleset to apply to jail
#jail_example_fstab=""                          # fstab(5) for mount/umount
#jail_example_flags="-l -U root"                # flags for jail(8)
Figure 2
# jls
   JID  IP Address      Hostname                      Path
     6  192.168.0.10    gcujail.gcu.info              /home/jails/gcujail
# ps auxwww | grep J
root     2392  0.0  0.1  1376  1052  ??  SsJ   8:06PM   0:00.00 /usr/sbin/syslogd -s
root     2448  0.0  0.3  3524  3084  ??  IsJ   8:06PM   0:00.00 /usr/sbin/sshd
root     2455  0.0  0.1  1388  1064  ??  IsJ   8:06PM   0:00.00 /usr/sbin/cron -s
Figure 3
# Device Mountpoint FStype Options Dump Pass#
md /home/jails/gcujail/tmp mfs rw,-S,noexec,nosuid,-F/home/jails/gcujail.tmp 2 0

Conclusion

Et voici un petit tour d’horizon sur les jails avec, je l’espère, une présentation qui sort un peu des howtos classiques qu’on trouve sur différents sites web. Références [1] http://fr.wikipedia.org/wiki/Phacochère [2] http://www.freebsd.org/cgi/man.cgi?query=jail&sektion=8 [3] http://www.freebsd.org/cgi/man.cgi?query=securelevel&sektion=8
Il y a : 0 commentaire(s)

Donnez votre avis

Vous devez avoir ouvert une session pour écrire un commentaire.

Brèves
Édito : Linux Pratique Essentiel N°24
Édito : Linux Pratique HS N°23
Édito : GNU/Linux Magazine 146
Édito : GNU/Linux Magazine HS N°58
Édito : Open Silicium N°5
Communication
Linux Pratique HS 23 – Communiqué de presse
Linux Pratique Essentiel N°24 – Communiqué de presse
Gnu/Linux Magazine sponsor et partenaire de PROLOGIN
Linux Essentiel partenaire des Rencontres du Libre de Lion sur Mer (Normandie)
GNU/Linux Magazine HS 58 – Communiqué de presse
prochainement moteur de recherches des articles
 
:
:
Jours heures minutes secondes
En kiosque
Le tout nouveau Linux Pratique Essentiel est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine HS est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Open Silicium est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Misc est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...