Con la llegada de Solaris 10 y sus containers, muchos de nosotros comenzamos a "migrar" nuestros servicios a contenedores y, por ello, dejamos de utilizar -y hablar- de los chroot. Es cierto que un "container" o "LDOM" nos proporciona una gestión mucho más fina, y por lo tanto, podemos definir los recursos, usuarios, etc. y sobre todo, aislar totalmente un entorno de otro.
Sin embargo, cuando nuestros recursos físicos están muy limitados -pensemos en un appliance, por ejemplo-, y debemos tratar de tener nuestro "servicio" lo más aislado posible podemos seguir utilizando esta "reliquia del pasado", que, funciona a la perfección.
Nota: Este post es una adaptación a la respuesta que hice en StackOverFlow sobre Cómo crear un SandBox en Unix
Qué es un ChRoot
Bueno, técnicamente es ejecutar un proceso con un "/" diferente a nuestro sistema principal, es decir, por ejemplo "/chroot_example/", por lo tanto, para nuestro "proceso" su "/" será "/chroot_example" y no podrá acceder a aquellas partes que necesitamos asegurar
Para Qué un ChRoot en Tiempos de Containers
Bueno, como os decía en la introducción, depende sobre todo de los recursos que dispongamos, así que si no tenemos muchos, deberemos utilizar técnicas como esta para tratar de aislar -en la medida de lo posible- nuestro proceso
ChRoot o Container
Bueno, esta es una pregunta un poco "compleja de responder", aunque intentaré salir "airoso" diciendo: depende. ¿De qué depende? Principalmente de recursos, tipos de servicios y administración. Mi recomendación es, si es posible utilizar Solaris Containers -o LDOMs- para servicios complejos -PostgreSQL, Hadoop, etc.- pero si necesitáis tener un "mini proceso" -o varios- no vais a crear un montón de Containers para cada uno de ellos. Es ahí donde entra nuestro ChRoot, además siempre podemos unir las dos opciones: ChRoot dentro de Containers
Un Ejemplo Completo
Después de todo este "lío", vamos a verlo claro con un ejemplo. Para ello, necesitamos ejecutar un comando -en nuestro caso ls- que nos devuelva el listado de nuestro "directorio /etc" -no el de sistema- donde tenemos la licencia de nuestro aplicativo.
La estructura de nuestro "chroot" sería la siguiente:
/Creación de la Estructura de ChRoot
/etc
+ license
/bin
+ ls
/lib
+ ...
Hemos comentado que un "ChRoot" es definir un nuevo "root" para el sistema de archivos de un proceso, y por lo tanto, deberemos "reproducir" el sistema principal con, al menos los directorios básicos: /etc, /bin, /lib
itily@openzooey:~$ mkdir chroot_exampleAhora vamos a copiar las "shared lib" que nuestro binario necesita -en nuestro caso ls-, para ello, utilizaremos el comando: <ldd>
itily@openzooey:~$ cd chroot_example/
itily@openzooey:~/chroot_example$ mkdir -p usr/lib lib bin etc
itily@openzooey:~/chroot_example$ cd bin/
itily@openzooey:~/chroot_example/bin$ cp /bin/ls .
itily@openzooey:~/chroot_example/bin$ ldd ls
libsec.so.1 => /lib/libsec.so.1
libnvpair.so.1 => /lib/libnvpair.so.1
libcmdutils.so.1 => /lib/libcmdutils.so.1
libcurses.so.1 => /lib/libcurses.so.1
libc.so.1 => /lib/libc.so.1
libavl.so.1 => /lib/libavl.so.1
libidmap.so.1 => /usr/lib/libidmap.so.1
libnsl.so.1 => /lib/libnsl.so.1
libuutil.so.1 => /lib/libuutil.so.1
libmp.so.2 => /lib/libmp.so.2
libmd.so.1 => /lib/libmd.so.1
libm.so.2 => /lib/libm.so.2
Vamos a copiar las bibliotecas utilizando un pequeño script. Desde el directorio <bin> de nuestro <chroot> hacemos:
itily@openzooey:~/chroot_example/bin$ ldd ls |awk '{print "cp "$3" .."$3}'Una vez verificado, ya podemos copiar las bibliotecas
cp /lib/libsec.so.1 ../lib/libsec.so.1
cp /lib/libnvpair.so.1 ../lib/libnvpair.so.1
cp /lib/libcmdutils.so.1 ../lib/libcmdutils.so.1
cp /lib/libcurses.so.1 ../lib/libcurses.so.1
cp /lib/libc.so.1 ../lib/libc.so.1
cp /lib/libavl.so.1 ../lib/libavl.so.1
cp /usr/lib/libidmap.so.1 ../usr/lib/libidmap.so.1
cp /lib/libnsl.so.1 ../lib/libnsl.so.1
cp /lib/libuutil.so.1 ../lib/libuutil.so.1
cp /lib/libmp.so.2 ../lib/libmp.so.2
cp /lib/libmd.so.1 ../lib/libmd.so.1
cp /lib/libm.so.2 ../lib/libm.so.2
itily@openzooey:~/chroot_example/bin$ ldd /bin/ls |awk '{print "cp "$3" .."$3}'|bashAhora tenemos nuestra estructura completa, y tiene la siguiente forma:
itily@openzooey:~/chroot_example/bin$
itily@openzooey:~/chroot_example$ ls -lAñadimos los archivos de <group> y <passwd> con el usuario que será el encargado de ejecutar el proceso -en mi caso itily- y creamos nuestra "licencia"
total 12
drwxr-xr-x 2 itily staff 3 dic 22 14:37 bin
drwxr-xr-x 2 itily staff 5 ene 10 20:43 etc
drwxr-xr-x 2 itily staff 14 ene 10 20:48 lib
drwxr-xr-x 3 itily staff 3 ene 10 20:40 usr
itily@openzooey:~/chroot_example$ echo "this is a test" > etc/licenseEjecutar el comando <chroot>
itily@openzooey:~/chroot_example$ cd etc/
itily@openzooey:~/chroot_example/etc$ cat /etc/group |grep staff > group
itily@openzooey:~/chroot_example/etc$ cat /etc/passwd |grep itily > passwd
Por último, ya sólo nos queda ejecutar el comando < que tiene el siguiente formato:
chroot rootdir command [arg ...]Debemos tener en cuenta que si ejecutamos el comando <chroot> con un usuario sin privilegios de "root", tendremos el siguiente mensaje
itily@openzooey:~$ chroot chroot_example bin/ls /etcchroot: cannot change root directory to chroot_example: Not ownerAsí que utilizaremos <pfexec> -si tenemos asignado el rol de root, o nos cambiaremos a root- para ejecutarlo:
itily@openzooey:~$ pfexec chroot chroot_example /bin/ls -l /etc total 6
-rw-r--r-- 1 101 10 11 Jan 10 19:43 group
-rw-r--r-- 1 101 10 18 Jan 10 19:42 license
-rw-r--r-- 1 101 10 49 Jan 10 19:43 passwd
Ya está! Hemos conseguido que nuestro comando <ls> nos muestre nuestro directorio </chroot_example/etc> como </etc>
Conclusiones
Aunque a veces parezca que las tecnologías antiguas ya no sirven, puede que en circunstancias nos ayuden, además, <chroot> nos permite montar sin "muchas" complicaciones algunas tareas sencillas sin tener que estar creando cientos de Containers para ello.
Referencias
Llevo un tiempo dándole vueltas a este asunto, pero no consigo que la jaula sea inexpugnable, es decir, si en vez del comando 'ls /' pones 'ls /../' qué ocurre? porque a mi ya con eso se me escapa de la jaula.
ResponderEliminarHay alguna forma de evitar esto? Un saludo