Jail archive
Un article de Diablotins.org.
|
Mise en oeuvre d'une Jail
PRINCIPE
OBJECTIFS D'UNE JAIL
Le présent document se propose d'expliquer les avantages et la mise en oeuvre de JAIL dans de multiples cas, tel que des services chrootes, des environnements clos et restreints, des machines virtuelles. Le principe de JAIL, est d'emprisonner un processus et tous ses fils dans un espace mémoire restreint, clos et spécifique. La commande JAIL existe sur le système UNIX FreeBSD.
Cette commande permet de créer une ou des machines virtuelles au dessus d'un système hôte FreeBSD ainsi que des services isolés.
DETAILS SUR LE PRINCIPE DE JAIL
Jail permet à la fois de mettre enoeuvre plusieurs machines virtuelles sur une même machine, mais aussi de sécuriser le système en plaçant tous les démons de services de la machine dans un environnement mémoire clos et sécurise pour le quel les accès au disques sont limite a une racine fictive. Les processus lancé dans une Jail, non pas accès au système hôte, il tourne dans un environnement cloisonné. Au lancement d'une Jail, on lui donne un nom de domaine, une IP, un chemin et une commande.
Le chemin fourni à la commande est en fait la racine de l'environnement qui sera cree au démarrage de la Jail. L'IP sert à la communication réseau de la Jail, on s'aperçoit donc que notre Jail possède une limite quant à sa connectivite. On verra plus tard qu'il y a d'autre précaution à prendre sur la mise en réseau d'une Jail.
La commande elle, est celle qui est lancée comme processus clos, toutes ses filles seront-elles aussi enfermées dans l'espace mémoire de la mère et chroote a sa racine.
MISE EN OEUVRE THEORIQUE
AVANTAGES DE JAIL ET DE FREEBSD POUR CE TYPE DE TECHNOLOGIE
Sur la mise en oeuvre de machine virtuelles
D'autre procèdes de création de machine virtuelle existent sur d'autre système Unix ou Microsoft et même sur FreeBSD. Aucun n'apporte les avantages de Jail. Les Procèdes existant permettent certes de faire tourner des systèmes différents mais ce sont de vrais gouffre de ressources systèmes ; de mémoire et de puissance de calculs. De plus ils posent des problèmes de fiabilité et de sécurité Des solutions comme VMware ne peuvent que servirent de machine virtuelles de tests ou de développement, mais en aucun cas de machine de production. De plus, ce procède est un gouffre de mémoire et de puissance machine.
Il devient donc impossible de faire fonctionner plusieurs VMware sur une même machine, or c'est la un des intérêts primordiaux des machines virtuelles. FreeVSD, sous Linux est une approche plus réaliste, mais elle n'a pas encore le niveau d'implémentation de Jail sous BSD, ni le recule en terme de temps et de tests face a cette dernière. De plus, Jail fait partie intégrante du noyaux FreeBSD, et donc offres de performances bien plus intéressantes que FreeVSD.
La seule alternative concrète, est la solution SOLARIS, mais il s'agit cette fois-ci d'un problème de coût et de packaging.
Il apparaît, dans le cadre d'une offre de serveurs virtuels, important d'envisager les deux cas et de créer deux solutions judicieusement packagée sur le long terme. FreeBSD, apparaît ici comme une arme sérieuse pour évaluer et débuter un telle offre.
Sur la mise en oeuvre de service isoles et pilotes
Ici, seul FreeBSD peut proposer ce service, la ou sur la majorité des systèmes UNIX, on ne peut que chrooter le service sensible, sur FreeBSD on va pouvoir, l'isoler en mémoire, assurant ainsi un niveau de sécurité beaucoup plus tolérable. Le mécanisme peut être mis en oeuvre sur beaucoup de services.
Nous en verrons divers exemples et réalisations. Les cas les plus intéressant sont bien sur les accès SSH, FTP, les services comme un DNS, et tout services a ressources closes. Nous verrons les différences de mise en oeuvres de chaque cas.
AVANTAGES DE FREEBSD
Precheur de convaincu...
FreeBSD offre la fiabilité des systèmes UNIX, la robustesse d'une distribution BSD, La sécurisation via des outils comme Jail, ipfilter, etc … FreeBSD apporte une certitude sur la qualité des développements due a l'utilisation des code de 4.4BSD et des standards d'UNIX, de plus ce code a été teste et éprouve depuis de longues années. FreeBSD apporte aussi de gros avantage de mise a jour et une facilite de déploiement de nombreux packages.
Une bonne maîtrise de FreeBSD est requise bonne avoir une approche suffisante et bien comprendre les mise en oeuvre de ce document, je vous renvoie donc vers la documentation que j'ai écrite sur l'installation et la configuration de FreeBSD. Les autres sources d'informations de FreeBSD, tel que le HANDBOOK, les mans des services vous apporteront un complément sur la mise en oeuvre de certain démons que nous verrons sans les détailler.
RAPPEL SUR LES AVANTAGES DE SECURITE ET D'USAGES D'UNE JAIL STANDARD
Le principe de la Jail, comme il a déjà été dit au dessus est de limiter la visibilité des processus ainsi que leur inter connectivite tant en mémoire que sur le disque. Ce principe s'appuis il est vrai sur une commande standard UNIX, chroot, qui permet de limiter a une arborescence donnée un processus, pour le quel la racine serait alors le point de chroot. Mais Jail va plus loin, il permet de limiter les accès et la vision de la mémoire et des autres processus, permettant ainsi de cloisonner entièrement un processus et ses fils. Le mécanisme est directement inclut dans le noyau limitant au maximum les ressources monopolisées. Il se base sur un système de flags entre les processus. Jail, peut être mis en oeuvre soit par scripts BASH ou PERL, soit par des programmes en C, via les API du noyau de FreeBSD, il devient donc possible d'envisager des structures sécurisées et complexes d'ensembles pour la mise en oeuvre de machine virtuelles ou de services sécurisés.
MISE EN OEUVRE D'UNE JAIL STANDARD SOUS FREEBSD
OBJECTIFS
Ce chapitre va exposer la commande Jail, et les contraintes de configurations qu'elle entraîne dans le cas le plus général. Nous allons voir que l'utilisation de Jail, impose des règles de configuration de l'hôte strict au niveau réseau.
Nous commencerons par voir l'aspect topologique, puis la configuration du système et des services obligatoire. D'une manière générale et je le redirait, il doit y avoir un minimum de services qui tourne sur l'hôte.
CONVENTION DE TOPOLOGIE ET D'ADRESSAGE
On considérera pour notre document une machine physique ayant deux interfaces réseaux : xl0 et xl1 (ces noms de devices sont ceux des cartes reseaux typiques de 3COM 3cXXX). (Il est intéressant quelque soit le type de jail que l'on veut mettre en oeuvre d'avoir deux interfaces Ethernet sur la machine hôte, nous verrons pourquoi dans le chapitre sur la sécurisation de la Jail depuis l'hôte.) L'hôte aura pour IP : 192.168.1.1 sur le réseau 1. Les jails prendrons IP sur le réseau 2. (Deux réseaux physiques peuvent êtres mis en place améliorant ainsi la sécurité)
D'où pour une première Jail : L'IP sera 192.168.2. 1 .
DESCRIPTION DE LA COMMANDE JAIL
Revenons sur la commande FreeBSD en elle-même, et décrivons son prototypage. La commande Jail à pour paramètres : Jail
Jail correspond en faite a un environnement chroote et un cloisonnement de processus.
Le cloisonnement est effectue au niveau du noyau, c'est pourquoi cette fonctionnalité n'est disponible que sur les systèmes UNIX BSD.
Pour mettre en oeuvre une Jail de service, il faut lui recréer un environnement autonome dans lequel on va enfermer le service spécifique et toutes ses dépendances. Cette opération est plus ou moins spécifique et fastidieuse suivant le type de services a chrooter. Dans tous les cas, il revient en faite a recréer un système base sur UNIX, et respectant ses règles et sa structure, mais plus ou moins complexe, mais notre tache dans tout les cas revient a isoler une ou plusieurs fonctionnalités de UNIX et de les faire tourner de façons autonomes.
Pour résumer, le gros avantage de cette commande réside dans le fait que l'on peut faire tourner de véritable microsystème ou des structures plus complexes de façon multiples et autonomes dans un espace que l'on met en oeuvre soit même en utilisant que les bases de connaissances nécessaires a la maîtrise d'UNIX et plus particulièrement FreeBSD ou l'om peut maîtriser tout les facteurs.
On entrevoit ici, un des autres avantages de Jail, c'est un formidable outil d'apprentissage et de créativité sous UNIX.
Vous pouvez isoler une fonctionnalité quelconque pour l'étudier ou pour vous assurer de son autonomie sans déployer plusieurs machines, réduisant ainsi d'éventuelles coût de développement.
MODIFCATION DE LA CONFIGURATION DE L'HOTE EN VUE D'UNE MISE EN OEUVRE DE JAIL
Modification du fichier /etc/rc.conf du maître
(Ici, encore, et comme dans la majeur partie du reste de cette documentation, il est important de bien maîtriser la configuration de FreeBSD, et donc je vous renvoie a la documentation sur la configuration de FreeBSD)
Pour rappel, le processus d'initialisation de FreeBSD s'appelle RC et le se configure par l'intermédiaire du fichier /etc/rc.conf.
Voici les lignes qu'il faut modifier au minimum (si vous avez suivit la procédure de configuration et d'installation prescrite).
# vi /etc/rc.conf -- [...] inetd_flags= "-wW -a 192.168.1.1" sendmail_enable= "NO" syslogd_flags="-s" [...]
Nous allons détailler chaque ligne modifie ou ajoute au fichier de configuration de RC.
Aspect réseaux et super démon UNIX BSD
L'IP 192.168.1.1 est l'IP réel de la machine. Le flag passé à INETD, sert à l'obliger à n'écouter que sur l'IP réel de la première interface et non sur les alias ou l'adresse de la deuxième interface que l'on réservera aux Jails de notre système…
Le cas de SENDMAIL
Pour Sendmail, soit on coupe le démon, soit on modifie sa configuration. (Dans cette documentation on ne verra pas comment faire cette configuration) On ne chargera pas le démon.
Syslogd
Syslogd reçoit le flag -s qui lui indique de travailler en mode securise, c'est-à -dire qu'il n'écoute plus en UDP, les autres machines. Il n'est important de faire travailler syslogd en mode securise sur l'hôte, une machine spécifique par réseau doit réaliser la tache de regrouper les logs venant des facilitées des autres machines.
Mise en place des l'alias IP des jails et de l'adresse de l'hĂ´te
Il nous faut maintenant créer un alias Ip pour notre Jail. (Exemple pour un serveur Intel ISC ou Dell POWER EDGE) Device : xlX
La commande manuelle est :
# ifconfig xl0 inet alias 192.168.1. 1 netmask 255.255.255.0
Dans le cas general on veut que les interfaces et les alias soit monte au démarrage, il faut donc ajouter des lignes de configuration pour RC, dans le /etc/rc.conf :
# vi /etc/rc.conf -- [...] # carte ethernet 1 hote ifconfig_xl0="inet 192.167.1.1 netmask 0xffffff00" #carte ethernet 2 (jails) ifconfig_xl1="inet 192.168.2.1 netmask 0xffffff00" ifconfig_xl1_alias0="inet 192.168.2.2 netmask 0xffffffff" ifconfig_xl1_alias1="inet 192.168.2.3 netmask 0xffffffff"
(Pour plus d'information voir le man de ifconfig et de rc et la documentation sur l'installation de FreeBSD et se configuration. )
Configuration des démons standard
Aller a l'essentiel
IL ne faut faire tourner qu'un minimum de démons sur la machine hôte, Pour être précis seul SSH devrait tourner.
Configuration de SSH
Pour sshd, le principe est le mĂŞme que pour inetd , on le bind sur une seul IP. Dans le fichier de conf de sshd, /etc/ssh/sshd_config , on ajoute :
# vi /etc/ssh/sshd_config -- [...] ListenAddress 192.168.1.1 [...]
Vérification des routes existantes
Vous devez alors vérifier si il n'existe pas de route existante entre vos jails du réseau 2 et votre hôte du réseau 1, pour cela il y a deux chose a faire :
- Vérifier qu'il n'a pas de forward entre les deux interfaces réseaux ethernet :
Tapez :
# sysctl -a |grep net.inet.ip.forwarding
Si la variable est a 1, alors passez la a 0, en tapant :
# sysctl -w net.inet.ip.forwarding=0
Vous pouvez automatiser ses mise a zéro au démarrage en mettant le ligne suivante dans le fochier /etc/sysctl.conf
# echo "net.inet.ip.forwarding=0" >> /etc/sysctl.conf
- Vérifier les routes via la commande :
# netstat -rn
Si il existe des routes entre les deux réseaux, supprime les via la commande : route delete
Suppression de messages d'erreurs ARP
Dans le cas ou les Jails sont dans le même réseaux, les deux interfaces vont répondre l'une pour l'autre aux requêtes ARP sans que ce soit réellement un problème, mais FreeBSD log tout, et va donc miner le /var/log/messages d'erreur du noyaux ARP. Pour les supprimer il faut cette fois-ci forcer a 0 la variable
# sysctl -w net.link.ether.inet.log_arp_wrong_iface=1 # echo "net.link.ether.inet.log_arp_wrong_iface=1" >> /etc/sysctl.conf
MISE EN OEUVRE DE MACHINES VIRTUELLES A L'AIDE D'UNE JAIL
OBJECTIF
Ici, l'objectif est de créer des machines virtuelles iso fonctionnelles au système hôte.
L'utilisateur d'une des machines virtuelles devient donc le root d'une vraie distribution FreeBSD, disposant de toutes commandes standard UNIX et de FreeBSD.
On va recompiler un FreeBSD dans une Prison, c'est ici le point de départ de la construction d'une machine virtuelle d'usage standard.
On recompile UNIX dans UNIX.
Pour ce faire, FreeBSD possède une fonctionnalité intéressante. La recompilation d'environnement et de distribution.
On utilise la commande make BSD depuis la racine des sources de FreeBSD…
PROCEDE PREPARATOIRE ET CONVENTION AVANT COMPILATION
Pour bien maîtriser cette rubrique, il peut être utile de bien maîtriser le procède de mise a jour d'une FreeBSD. Savoir recompiler le monde sur un système hôte est primordiale pour bien comprendre se que nous allons effectuer.
On va travailler avec une variable d'environnement, $JAIL, dans laquelle, on place le chemin D'accès de la Jail, (machine virtuelle).
Pour le test mais aussi de façon préconisée, on va considérer que nos Jails de machines virtuelles, sur ce système, se trouve dans /data/jails/.
A l'installation on prendra donc grand soin de créer une grosse partition /data ou de monter un disque dur en /data.
Par convention, on nommera la racine d'une Jail par son adresse IP.
NOUS ALLONS RECOMPILER LE " MONDE " POUR NOTRE JAIL
La compilation de la distribution FreeBSD dans la Jail, se fait par le script suivant :
(Pour toutes les taches séquentielles, le BASH sera employé, mais il est tout a fait possible d'interfacer ses séquences en PERL) Nous allons nomme cette Jail, microide.
# JAIL = /data/jails/192.168.2.1 # cd /usr/src # make world DESTDIR=$JAIL # cd etc/ # make distribution DESTDIR=$JAIL NO_MAKEDEV_RUN=yes # [mkdir $JAIL/dev] # cd $JAIL/dev # sh MAKEDEV jail # cd $JAIL # ln -sf dev/null kernel
Je reviens en détail sur cette séquence :
Tout d'abord, on définit la cible de la Jail, le point de chroot.
# JAIL = /data/jails/192.168.11.100
Ensuite, on va se situer dans le répertoire des sources de la FreeBSD. (Ici encore, je renvoie à la documentation sur l'installation et la configuration d'une FreeBSD, dans laquelle, je décris les différentes méthodes de récupération et de mise a jour des sources de la FreeBSD. Je vous déconseille de vouloir mettre a jour les versions de FreeBSD trop souvent, pour une machine hôte de serveurs virtuels. Contentez vous de suivre les upgrades de sécurité, car a chaque mise a jour, vous devrez recompiler le monde de toutes les machines virtuelles, mais aussi de l'hôte, pour enfin pouvoir recompiler le noyau.)
# cd /usr/src
On compile le monde pour notre Jail dans le répertoire de la JAIL. (on prend la précaution de ne pas faire un /dev pour notre jail normal)
# make world DESTDIR=$JAIL # make distribution DESTDIR=$JAIL NO_MAKEDEV=yes
On crée le répertoire dev de la Jail si besoin et si dirige.
# [mkdir $JAIL] # cd $JAIL/dev
On crée la base des fichiers de périphérique de la Jail.
# sh MAKEDEV jail
On se dirige dans la Jail, et on crée un lien symbolique vers le trou noir pour simuler le fichier du noyau.
# cd $JAIL # ln -sf dev/null kernel
La jail est prette.
= REMISE EN OEUVRE DU PROGRAMME SYSINSTALL
L'utilitaire sysinstall peut-être installé sur une jail. Dans notre cas, on pourrait saisir les commandes suivantes.
# mkdir /data/jails/192.168.2.1/stand # cp /stand/sysinstall /data/jails/192.168.2.1/stand # chmod 775 /data/jails/192.168.2.1/stand/sysinstall # chown root:root /data/jails/192.168.2.1/stand/sysinstall
TESTS
Pour tester la nouvelle Jail, on tape :
# jail /data/jails/192.168.2.1 microide 192.168.2.1/bin/sh
On peut bien sûr, ici, utiliser n'importe quel Shell, mais le sh est bel et bien présent, après un make world.
CONFIGURATION DE LA JAIL
La configuration de la Jail peut alors se faire via Sysinstall comme on le ferait pour un système maitre.
On tape :
# /stand/sysinstall
QUELQUE PRECAUTION VONT ETRES UTILES
- Créer un fichier /etc/fstab vide pour éviter les erreurs au démarrage.
- Vérifier que le port mapper ne fonctionne plus.
- Changer le root password, soit par passwd, soit par /stand/sysinstall
- Installer les packages nécessaires.
- Configurer les derniers détails via sysinstall.
- Configurer les installations exotiques de services pour vos clients.
- Créer des utilisateurs.
Précaution qui doit devenir systématique. Il faudra installer SShd, et éviter d'utiliser Telnetd.
Mise a disposition du système de fichier image des processus
Le système de fichier procfs peut-être utile depuis la Jail, il faut donc le monter.
# mkdir /data/jails/192.168.2.1/proc # mount -t procfs proc /data/jails/192.168.2.1/proc
Démarrage et fichier de démarrage
Un système BSD utilise pour se configurer et s'initialiser au démarrage le process RC, on va donc pour notre Jail l'utiliser de façon plus rudimentaire. Donc on doit lancer à la ligne de commandes.
# jail /data/jails/192.168.2.1 microide 192.168.2.1 /bin/sh /etc/rc
ArrĂŞt de la Jail
Pour terminer notre Jail, il faut se logger dans celle-ci (Telnet, SSH…) en root et taper :
# kill -TERM -1
Ou
# kill -KILL -1
Les commandes halt, shutdown, reboot ne fonctionne pas dans une Jail, vous pouvez si vous le désirez les scripter et de les poser dans le /bin de la jail, soit /data/jails/192.168.2.1/bin, tout dépend de qui utilise la Jail.
Il est aussi possible de tuer un processus d'une Jail d'en dehors de celle-ci.
# kill -9 <jail_pid_sh>
Les processus d'une Jail portent un flag 'J'.
MISE EN PLACE D'UNE JAIL DE SERVICE
OBJECTIFS
Pour le moment, on a vue seulement le cas ou on veut créer une machine virtuelle iso fonctionnelle à la distribution FreeBSD. Mais ce n'est pas toujours ce que l'on cherche a réaliser.
Dans de nombreux cas on voudra seulement isoler un service, ou créer des micros systèmes UNIX, pour des utilisations très spécifiques.
(Nous verrons le cas d'un accès SSH sécurisé et limité). L'usage de tels procèdes à deux avantages :
- Le premier est de mettre à l'écart de façon complète la machine hôte, on dirige le service depuis un système complet sans restrictions sans risque de trou de sécurité due à la mise en oeuvre de maintenance du système.
- Le second est de permettre une disponibilité réduite de commandes dans la Jail, et la suppression des commandes les plus sensible sans limiter la maintenabilite de la structure de service en elle-même. On choisit les commandes que l'on veut.
PRECAUTIONS ET MODE OPERATOIRE GENERAL
On aperçoit déjà la complexité de mise en oeuvre de telles structures.
D'une manière générale, plus le système à isoler a de dépendance quelconque vers différentes ressources, plus sa mise en Jail devient difficile.
Il n'est possible de lancer des services qui accède a des ressources de type fichiers. Sans quelques précautions.
Il faut évidement, que les fichiers soient dans l'arborescence chroote, sinon il ne sera pas possible de les accéder, ils seront même entièrement invisible des le lancement de la Jail.
METHODE GENERALE
Description
D'une manière générale, on peut tracer un modèle structurel pour mettre en oeuvre un service sous Jail. La partie suivante va décrire non pas les éléments a mettre en oeuvre, car il est impossible d'en dresser une liste, et elle est même dépendante du service a enfermer, mais les méthodes et outils pour la réalisation de l'édifice, car il s'agit bien ici d'une construction, on va installer le service morceau par morceau.
La méthode, est base sur une progression de proche en proche de lien en lien, d'assemblage et de réassemblage empirique, régit par les règles de structures des systèmes UNIX et BSD.
On voie se profiler la démarche à suivre, nous allons reconstruire les arborescences de BSD dans un espace disque que l'on va chrooter.
Dans la mesure du possible, il va falloir essayer de créer le service statiquement, ou rapatrier les librairies et les poser dans le repertoires ou le binaires les attends relativement au point de chroot.
Les outils
Les outils les plus utiles pour notre réalisation sont :
- which/whereis : qui sert a localiser un binaire dans le $PATH.
- locate : qui permet la recherche de fichier. (cette commandes impliques une base locate a jour : voir Handbook sur locate.updatedb)
- ldd : qui liste les dépendances d'un binaire exécutable.
- cp/mv/… : toutes les commandes de manipulation des fichiers.
- chown/chmod : toutes les commandes de manipulation de droits et de possession de fichier.
Compilation des outils et des binaires du service ou nécessaire au service
Pour la création du service, si le port FreeBSD, n'existe pas, ou si pour une raison quelconque vous devez ou voulez compiler le programme vous-même, les méthodes a suivre seront souvent similaire.
Vous devrez configurez le Makefile, en changeant le préfix, (emplacement de dépôts de répertoires), préciser le linkage statique du binaire, et s'assurer du répertoire des fichiers de configuration. Toutes ses opérations se feront le plus souvent depuis le script Shell :
# ./configure
Grâce a des paramètres tel que :
- --prefix-cmd=
- pour préciser le chemin d'une command utiles
- --prefix-bin=
- pour préciser le chemin des binaires.
- --config-dir=
- pour le chemin des fichiers de configuration
- --static
- pour linker le binaire en statique.
Remarque : pour les répertoires, il faut bien penser que depuis la jail, la racine est le point de chroot, donc si la Jail est montée depuis /data/jails/192.168.2.1/ , le répertoire /data/jails/192.168.2.1/etc de l'hôte, correspond au répertoire /etc dans la Jail.
Politique sur la structure de l'arborescence d'une jail de service
Dans ce domaine, mes conseils n'ont pas valeurs de références mais de mises en garde.
Je ne peux que vous pousser à conserver la structure des répertoires sur une machine standard BSD, ne cherché pas la complication.
Je ne suis pas sur que vouloir aussi changer les emplacements des fichiers de configurations ou des binaires pour des raisons de sécurité soit nécessaire l'aspect déjà atypique d'une jail, en terme de structure est déjà suffisant. Ne vous compliquer pas trop la tache, a vous et aux personnes qui devront maintenir et faire évoluer le service, mais jouer plutot avec les fichiers pour vous assurer qu'il n'y a pas de trou.
Le but de la Jail, n'est pas de cacher les fichiers de configurations du service, mais de restreindre l'univers de possibilités d'attaques d'un système en le laissant seul visible, et d'autre part voir ne veux pas dire modifier.
N'oubliez pas du fait du mécanisme de Jail, les acquis UNIX, et adopter des règles rigoureuses sur le positionnement des droits sur les fichiers.
En voulant tromper le pirate en changeant les chemins des fichiers vous gagnerez certes du temps sur une attaque, mais Ă quel prix, de plus vous ne ferez que gagner du temps, vous n'empĂŞcherez pas l'attaque.
Avec le temps vous verrez que ce type de décisions engendrera du temps supplémentaire a la conception, a la maintenance, de gros soucis de mise a jour par des personnes tierces, et en plus un gros travail de documentations.
Mode opératoire
- Etape 1 : repérer les binaires et les fichiers de configuration de votre service, et en faire une liste.
- (Toutes les manipulations de fichiers doivent évidement être faites sous l'utilisateur root)
- Etape 2 : trouver les chemins de chaque fichier ainsi que les dépendances de chaque binaires, les librairies les objets partagés, etc...
- (N'oubliez pas des outils comme sed et awk tout au long de ce processus).
- Etape 3 : recréer dans la Jail, l'arborescence ou vous devez poser vos fichiers, dans la majorité des cas faite des répertoires immuables.
- Etape 4 : compiler et copier les programmes de type 'source standard'.
- (ATTENTION : si vous compiler une version d'un service disponible sur l'hôte, mais spécifique a la Jail, prenez garde de bien sauvegarder les fichiers de configurations de votre hôte.)
- Etape 5 : contrôler les droits sur les fichiers de votre Jail, faite des tests via la commande Jail, sur chacun des binaires exécutables pour vous assurer qu'il lui manque aucun composant, vous ne devez pas vous soucier des appels systèmes, votre Jail a évidement droit d'accès aux routines du noyau.
- Etape 6 : créer les scripts d'initialisation de votre Jail, tant interne qu'externe, nous en verrons plusieurs types pour des cas différent, mais le modèle de ces scripts est celui de RC : - boite a état pour le lancement depuis l'extérieur - séquence Shell depuis l'intérieur de la Jail.
ETUDES DE CAS ET IMPLEMENTATION
Cas simple le DNS
Dans le cas du DNS, c'est relativement simple, il suffit de faire une installation de BIND dans un répertoire du type /data/jails/dns/
(Comme vous l'avez constaté, dans le cas d'un service, on donne pour nom à la Jail, le nom du service).
On recherche toutes les dépendances de named et de ndc :
- named est le démon du DNS
- ndc est le loader.
Cas complexe l'accès SSF
Bon ici j'ai fait un script pour automatiser toute les création :
#!/usr/local/bin/ruby require 'ipaddr' puts 'Jail Installation and server initialisation' puts '-------------------------------------------' puts '' # initialisation data_path = String::new('/var/data') data_symlink = String::new('/data') jail_path = String::new("#{data_symlink}/jail") rc = IO::readlines("/etc/rc.conf").delete_if{|line| line !~ /ifconfig/} rc.map!{|line| line = /^ifconfig_.*\d+="inet\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+netmask\s+(\d{1,3}\.){3}\d{\ 1,3}".*$/.match(line)[1]} jail_ip = IPAddr.new "#{rc[0]}" host_ip = IPAddr.new "#{rc[1]}" jail_net = jail_ip.mask(24) host_net = host_ip.mask(24) table_exe = Array::new(['ls','cp','sh','pwd','vi','cat','mv','file','bash','clear','dig','echo','which','id','grep\ ','cut','awk','perl','find','file','tar','gzip','diff','patch','md5','xargs','uniq','sort','sed','more','chmod','w\ c','test','touch']) list_config_file = Array::new(['/etc/termcap','/usr/share/misc/termcap','/usr/share/misc/magic']) # methode recursive d'install des dependances et des outils def install_in_jail(binary,jail_path) IO.readlines("|ldd #{binary} 2>&1").map!{|dep| dep=dep.split(/ /)[2]}.compact.delete_if {|x| x =~ /not/ }.each{|\ file_dep| system("mkdir -p #{jail_path}#{File.dirname(file_dep)}") unless File::exist?("#{jail_path}#{File.dirname(file_\ dep)}") system("cp #{file_dep} #{jail_path}#{File.dirname(file_dep)}") unless File::exist?("#{jail_path}#{file_dep}") install_in_jail(file_dep,jail_path) } system("mkdir -p #{jail_path}#{File.dirname(binary)}") unless File::exist?("#{jail_path}#{File.dirname(binary)}"\ ) system("cp #{binary} #{jail_path}#{File.dirname(binary)}") if not File::exist?("#{jail_path}#{binary}") end # création de la jail def create_jail_skeleton(data_path,jail_path,data_symlink) puts "* Building filetree for the jail." system("mkdir #{data_path}") if not File::exist?(data_path) system("ln -s #{data_path} #{data_symlink}") if not File::exist?(data_symlink) system("mkdir #{jail_path}") if not File::exist?(jail_path) end # copie des executables en liste avec les dependance dans le points de chroot def install_executable(table_exe,jail_path) puts "* Installation of the jail's executables." table_exe.each{|exe| puts " => AJout de #{exe} et de ses dépendances ..." if File::exist?(`which #{exe}`.chomp) then install_in_jail(`which #{exe}`.chomp,jail_path) else puts 'ERROR : command not found' end } enddef create_ld_tools(jail_path) puts '* Installation of the ld tools and configuration files' system("mkdir #{jail_path}/libexec && cp /libexec/* #{jail_path}/libexec/") unless File::exist?("#{jail_path}/l\ ibexec") system("mkdir -p #{jail_path}/var/run && cp /var/run/ld*.so.hints #{jail_path}/var/run/") unless File::exist?("\ #{jail_path}/var/ru\ n") end def put_config(list_config_file,jail_path) puts '* Installation of arbitrary configuration files.' list_config_file.each{|config_file| puts " => AJout du fichier de configuration : #{config_file}" system("mkdir -p #{jail_path}#{File.dirname(config_file)}") unless File::exist?("#{jail_path}#{File.dirname(c\ onfig_file)}") system("cp #{config_file} #{jail_path}#{File.dirname(config_file)}") unless File::exist?("#{jail_path}#{confi\ g_file}") } end def make_temporary_path(jail_path) puts '* Building temporary paths.' system("mkdir #{jail_path}/tmp; chmod 1777 #{jail_path}/tmp") unless File::exist?("#{jail_path}/tmp") system("mkdir #{jail_path}/var/tmp; chmod 1777 #{jail_path}/var/tmp") unless File::exist?("#{jail_path}/var/tmp"\ ) end def put_script(jail_path) puts '* Installing jail managing script' system("mkdir -p /usr/local/bin/") unless File::exist?("/usr/local/bin/") myscript = open("/usr/local/bin/manage_jail",'w+') DATA.each{|line| myscript.puts line } myscript.close system("chmod 700 /usr/local/bin/manage_jail") end # exemple pour l'install du port MySQL def install_mysql(jail_path) puts '* Installing the mysql command in jail.' puts ' => Installing port.' if `pkg_info|grep mysql-client`.empty? system("cd /usr/ports/databases/mysql-client/; make install clean") if `pkg_info|grep mysql-client`.empty? puts ' => Installing binaries.' install_in_jail(`which mysql`.chomp,jail_path) end def create_sshd_config(jail_path) puts ' => make sshd configuraiton file' myconf = open("#{jail_path}/etc/ssh/sshd_config",'w+') myconf.puts('Port 23') myconf.puts('Protocol 2') myconf.puts('ListenAddress 0.0.0.0') myconf.puts('HostKey /etc/ssh/ssh_host_key') myconf.puts('HostKey /etc/ssh/ssh_host_dsa_key') myconf.puts('SyslogFacility AUTH') myconf.puts('PermitRootLogin no') myconf.puts('StrictModes yes') myconf.puts('RSAAuthentication yes') myconf.puts('PubkeyAuthentication yes') myconf.puts('AuthorizedKeysFile .ssh/authorized_keys') myconf.puts('RhostsRSAAuthentication no') myconf.puts('HostbasedAuthentication no') myconf.puts('IgnoreUserKnownHosts no') myconf.puts('IgnoreRhosts yes') myconf.puts('PasswordAuthentication no') myconf.puts('PermitEmptyPasswords no') myconf.puts('ChallengeResponseAuthentication yes') myconf.puts('UsePAM yes') myconf.puts('GatewayPorts no') myconf.puts('AllowTcpForwarding no') myconf.puts('X11Forwarding no') myconf.puts('PrintMotd yes') myconf.puts('PrintLastLog yes') myconf.puts('TCPKeepAlive yes') myconf.puts('UseLogin no') myconf.puts('UsePrivilegeSeparation yes') myconf.puts('PermitUserEnvironment no') myconf.puts('Compression yes') myconf.puts('UseDNS yes') myconf.puts('#Banner /some/path') myconf.puts('Subsystem sftp /usr/libexec/sftp-server') myconf.puts('PidFile /var/run/sshd.pid') myconf.puts('MaxStartups 10')def install_sshd(jail_path) myconf.close end def install_sshd(jail_path) puts '* Installing the sshd daemon in jail.' puts ' => Installing binaries.' install_in_jail(`which sshd`.chomp,jail_path) puts ' => Installing configuration.' system("mkdir -p #{jail_path}/etc/ssh") unless File::exist?("#{jail_path}/etc/ssh") system("cp /etc/ssh/moduli #{jail_path}/etc/ssh") unless File::exist?("#{jail_path}/etc/ssh/moduli") system("/usr/bin/ssh-keygen -t rsa1 -b 1024 -f #{jail_path}/etc/ssh/ssh_host_key -N ''") unless File::exist?("#{\ jail_path}/etc/ssh/ssh_host_key") system("/usr/bin/ssh-keygen -t dsa -f #{jail_path}/etc/ssh/ssh_host_dsa_key -N ''") unless File::exist?("#{jail_\ path}/etc/ssh/ssh_host_dsa_key") system("/usr/bin/ssh-keygen -t rsa -f #{jail_path}/etc/ssh/ssh_host_rsa_key -N ''") unless File::exist?("#{jail_\ path}/etc/ssh/ssh_host_rsa_key") create_sshd_config(jail_path) unless File::exist?("#{jail_path}/etc/ssh/ssh/sshd_config") system("mkdir -p #{jail_path}/var/empty") unless File::exist?("#{jail_path}/var/empty") end def start_pseudo_fs(jail_path) puts '* Starting pseudo FS.' puts ' => proc in host.' unless File::exist?("/proc") system("mkdir /proc") unless File::exist?("/proc") system("echo 'proc /proc procfs rw 0 0' >> /etc/fstab") if `grep ' /proc' /etc/fstab`.empty? system("mount /proc") if `mount |grep '/proc '`.empty? puts ' => dev in host.' unless File::exist?("#{jail_path}/dev") system("mkdir #{jail_path}/dev") unless File::exist?("#{jail_path}/dev") system("echo 'dev #{jail_path}/dev devfs rw 0 0' >> /etc/fstab") if `grep #{jail_path}/dev /etc/fstab`.empty? system("mount #{jail_path}/dev") if `mount |grep '#{jail_path}/dev '`.empty? puts ' => proc in jail.' unless File::exist?("#{jail_path}/proc") system("mkdir #{jail_path}/proc") unless File::exist?("#{jail_path}/proc") system("echo 'proc #{jail_path}/proc procfs rw 0 0' >> /etc/fstab") if `grep #{jail_path}/proc /etc/fstab`.empty\ ? system("mount #{jail_path}/proc") if `mount |grep '#{jail_path}/proc '`.empty? end def install_pam(jail_path) puts '* Installing pam' puts ' => Puts libraries module PAM.' install_in_jail("/usr/lib/pam_unix.so",jail_path) puts ' => Puts configuration files.' system("mkdir -p #{jail_path}/etc/pam.d") unless File::exist?("#{jail_path}/etc/pam.d") if not File::exist?('#{jail_path}/etc/pam.d/sshd') then sshd_pam = open("#{jail_path}/etc/pam.d/sshd",'w') sshd_pam.puts('auth required pam_unix.so no_warn try_first_pass') sshd_pam.puts('account required pam_unix.so') sshd_pam.puts('session required pam_unix.so') sshd_pam.puts('password required pam_unix.so no_warn try_first_pass') sshd_pam.close end end def activate_syslog_in_jail(jail_path) puts '* Activate syslogd in jail.' puts ' => add in rc.' system("echo 'syslogd_enable=\"YES\"' >> /etc/rc.conf") if `grep 'syslogd_enable' /etc/rc.conf`.empty? system("echo 'syslogd_program=\"/usr/sbin/syslogd\"' >> /etc/rc.conf") if `grep 'syslogd_program' /etc/rc.conf`.\ empty? system("echo ' syslogd_flags=\"-s -p #{jail_path}/var/run/log\"' >> /etc/rc.conf") if `grep 'syslogd_flags' /etc\ /rc.conf`.empty? puts ' => reload syslogd' system("killall syslogd;syslogd -s -p #{jail_path}/var/run/log") end def tune_sysctl puts '* Tuning host Sysctl' sysctl_list = ['security.bsd.see_other_uids=0','net.inet.tcp.blackhole=1','net.inet.udp.blackhole=0','security.b\ sd.see_other_gids=0','security.jail.set_hostname_allowed=0','security.jail.allow_raw_sockets=1'] sysctl = open("/etc/sysctl.conf",'w') sysctl_list.each{|item| system("sysctl -b #{item}") sysctl.puts item } sysctl.close end def patch_sshd_config_host(host_ip) sshd_config = IO::readlines('/etc/ssh/sshd_config') sshd_config.map!{|line| if line =~ /^.*ListenAddress\s+(\d+\.){3}\d+.*$/ then line = "ListenAddress #{host_ip}" else line = line end } sshd_config.delete_if{|line| line =~ /^#/} sshd_config.delete_if{|line| line =~ /^\n/} dest = open('/etc/ssh/sshd_config','w') sshd_config.each{|line| dest.puts line } dest.close end def init_user_in_jail puts '* Initialising users on host and jail' system("/usr/local/bin/manage_jail cp") end def add_crontab_line puts '* adding task managing user in crontab' system("echo '0 0 * * * root /usr/local/bin/manage_jail convert >/dev/null 2>&1' >> /etc/crontab") if `grep '/us\ r/local/bin/manage_jail' /etc/crontab`.empty? end def put_freebsd_rc_loader puts '* Putting rc loader FreeBSD for the jail.' jail_rc = open("/usr/local/etc/rc.d/jail.sh",'w') jail_rc.puts('#!/bin/sh') jail_rc.puts('/usr/local/bin/manage_jail $1') jail_rc.close end # MAIN create_jail_skeleton(data_path,jail_path,data_symlink) install_executable(table_exe,jail_path) create_ld_tools(jail_path) put_config(list_config_file,jail_path) make_temporary_path(jail_path) put_script(jail_path) install_mysql(jail_path) install_sshd(jail_path) start_pseudo_fs(jail_path) install_pam(jail_path) activate_syslog_in_jail(jail_path) tune_sysctl patch_sshd_config_host(host_ip) init_user_in_jail add_crontab_line put_freebsd_rc_loader puts ' =*= jail OK' __END__ #!/usr/local/bin/ruby require 'ipaddr' param = ARGV[0] ID_LIMIT=500 data_root = "/data" data_jail = "#{data_root}/jail" rc = IO::readlines("/etc/rc.conf").delete_if{|line| line !~ /ifconfig/} rc.map!{|line| line = /^ifconfig_.*\d+="inet\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+netmask\s+(\d{1,3}\.){3}\d{\ 1,3}".*$/.match(line)[1]} jail_ip = IPAddr.new "#{rc[0]}" host_ip = IPAddr.new "#{rc[1]}" jail_net = jail_ip.mask(24) host_net = host_ip.mask(24) case param when 'cp' then puts '* Adding in the jail path' system("cp /etc/master.passwd /etc/passwd /etc/spwd.db /etc/pwd.db #{data_jail}/etc") puts ' => Correction of the UNIX mode in jail' system("chmod 600 #{data_jail}/etc/master.passwd #{data_jail}/etc/spwd.db") puts ' =*= jail users OK' when 'start' if not File::exist?("#{data_jail}/var/run/sshd.pid") then puts '* Starting Jail' system("jail /data/jail omicron #{jail_ip} /usr/sbin/sshd") puts ' =*= Jail running OK' else puts ' =/= Jail already running NOK' end when 'stop' if File::exist?("#{data_jail}/var/run/sshd.pid") then puts '* Stopping Jail' pid = `cat #{data_jail}/var/run/sshd.pid`.chomp system("kill #{pid}") puts ' =*= Jail stopping OK' else puts ' =/= Jail not running NOK' end end
