Linux · 8 min read · Feb 03, 2026
Entrando a un espejo seguro al iniciar sesión con Unionfs y Chroot
Entrando a un espejo seguro al iniciar sesión con Unionfs y Chroot
1. Introducción
Al leer un ‘hint’ en el sitio web de LinuxFromScratch, descubrí las capacidades especiales de unionfs, especialmente en combinación con chroot. Más tarde leí un HowTo en un wiki de Gentoo, sobre cómo entrar en un directorio personal chrooted al usar un script especial como shell. Combinar estos dos me lleva a usar un entorno chrooted, que se ingresa al iniciar sesión como un usuario especial. Este entorno es una copia exacta (espejo) del sistema en el que estás trabajando. Debido a que estás en una copia segura del sistema real, puedes hacer lo que quieras, nunca cambiará el sistema, todo permanece dentro de la caché (la rama de lectura y escritura).
Enlaces:
TRIP, un empaquetador TRIvial para LFS (y otros sistemas linux) - Hint original en el sitio web de LFS
Home_directory_jail - Guía para configurar una cárcel chroot en Gentoo
2. Técnica básica
Haz lo que quieras, instala, cambia y elimina archivos del sistema, y no habrá ningún daño. Tu sistema real permanece intacto. Esto puede sonar como magia, pero en realidad es posible solo combinando algunas técnicas de todas las disponibles para Linux.
Al usar el sistema de archivos Unionfs, un chroot y algunos directorios remonteados bien elegidos, puedes configurar este sistema virtual.
2.1 Unionfs
La parte más importante es el uso de unionfs. Unionfs te da la posibilidad de crear un sistema de archivos, que es la unión de al menos otros dos. Consulta www.unionfs.org para más información. Ahora, al dejar que el nuevo sistema de archivos sea la unión de nuestro sistema de archivos original (la raíz) en modo solo lectura, y de un sistema de archivos temporal (la caché) en modo de lectura y escritura, tendrás un sistema de archivos que se ve exactamente como tu sistema de archivos original, pero en el que puedes modificar, eliminar y/o agregar archivos sin hacer nada a tu sistema original. Esto no es posible, porque la raíz está montada como solo lectura. Cada modificación es almacenada por unionfs en la caché.
La única diferencia entre el sistema original y el recién creado es la ruta: en el nuevo sistema siempre comienza con la ruta del punto de montaje de la unión. Por eso el siguiente paso es necesario.
Una nota especial: hoy [junio de 2007] parece que unionfs será incluido en el kernel. Unionfs está en un desarrollo intenso en este momento. Consulta el sitio web para más información.
En el sitio web encontrarás información sobre cómo habilitar unionfs. Para los últimos kernels (posteriores a 2.6.19) hay un parche para el código fuente del kernel, para kernels no tan recientes hay un módulo externo.
2.2 (Re)Montaje
Una cosa extra que tendrás que hacer es (re)montar varios directorios cruciales como /dev, /proc y /sys. Esto se debe a que el sistema de archivos de unión no preserva los puntos de montaje existentes.
También se recomienda volver a montar algunos directorios especiales como /tmp y el directorio en el que estás construyendo el software.
2.3 Chroot
Al chrootear a este punto de montaje, entras en un entorno que es absolutamente una copia de tu sistema. Puedes hacer lo que quieras, incluso eliminar directorios y archivos cruciales. ¡Pruébalo! Mira hasta dónde puedes llegar antes de que tu sistema se quede atascado.
2.4 Iniciar sesión en este entorno
Como el concepto explicado en Home_directory_jail, es posible crear un shell de inicio de sesión especial para entrar en el entorno creado con unionfs y chroot.
La idea explicada aquí es crear un usuario especial, con un shell especial. Este shell, antes de entrar en un shell interactivo, primero realizará los pasos necesarios como montar el sistema de archivos de unión, volver a montar algunos directorios importantes y hacer el chroot.
3. Preparación
3.1 La partición de caché
Para comenzar, una partición con suficiente espacio para funcionar como caché. Esto no tiene que ser una partición física, puede ser una unidad virtual.
Crea esta unidad con:
dd if=/dev/zero of=/mnt/cache.img bs=1M count=500
mkfs.ext2 /mnt/cache.img
mkdir /mnt/cache
mount /mnt/cache.img /mnt/cache -o loopchmod 777 /mnt/cachemkdir /mnt/unionEsto crea una partición virtual (o unidad) de 500M.
(Nota: el dispositivo de bucle debe ser compatible con tu kernel. Los kernels de la mayoría de las distribuciones lo son.)
3.2 Shell de inicio de sesión especial
Crea un script de shell chroot-union que realizará todos los pasos necesarios:
El script chroot-union en /bin:
#!/bin/bash
function mount_unionfs {
# montar sistemas de archivos temporales
if [ -z "$(mount -t unionfs | grep -w /mnt/union )" ]; then
sudo /bin/mount -t unionfs -o dirs=/mnt/cache:/=ro unionfs /mnt/union
fi
if [ -n "$(mount -t unionfs | grep -w /mnt/union )" ]; then
# montajes del sistema básico
if [ -z "$(mount | grep -w /mnt/union/dev)" ]; then
sudo /bin/mount --bind /dev /mnt/union/dev 2> /dev/null
fi
if [ -z "$(mount -t devpts | grep -w /mnt/union/dev/pts)" ]; then
sudo /bin/mount -t devpts devpts /mnt/union/dev/pts 2> /dev/null
fi
if [ -z "$(mount -t tmpfs | grep -w /mnt/union/dev/shm)" ]; then
sudo /bin/mount -t tmpfs shm /mnt/union/dev/shm 2> /dev/null
fi
if [ -z "$(mount -t sysfs | grep -w /mnt/union/sys)" ]; then
sudo /bin/mount -t sysfs sysfs /mnt/union/sys 2> /dev/null
fi
if [ -z "$(mount -t proc | grep -w /mnt/union/proc)" ]; then
sudo /bin/mount -t proc proc /mnt/union/proc 2> /dev/null
fi
if [ -z "$(mount | grep -w /mnt/union/tmp)" ]; then
sudo /bin/mount --bind /tmp /mnt/union/tmp 2> /dev/null
fi
else
echo "El montaje de /mnt/union falló."
exit 2
fi
}
function umount_unionfs {
#
# desmontar /tmp
#
if [ -n "$(mount | grep -w /mnt/union/tmp)" ]; then
sudo /bin/umount /mnt/union/tmp 2> /dev/null
fi
#
# desmontar /proc
#
if [ -n "$(mount -t proc | grep -w /mnt/union/proc)" ]; then
sudo /bin/umount /mnt/union/proc 2> /dev/null
fi
#
# desmontar /sys
#
if [ -n "$(mount -t sysfs | grep -w /mnt/union/sys)" ]; then
sudo /bin/umount /mnt/union/sys 2> /dev/null
fi
#
# desmontar /dev/shm
#
if [ -n "$(mount -t tmpfs | grep -w /mnt/union/dev/shm)" ]; then
sudo /bin/umount /mnt/union/dev/shm 2> /dev/null
fi
#
# desmontar /dev/pts
#
if [ -n "$(mount -t devpts | grep -w /mnt/union/dev/pts)" ]; then
sudo /bin/umount /mnt/union/dev/pts 2> /dev/null
fi
#
# desmontar /dev
#
if [ -n "$(mount | grep -w /mnt/union/dev)" ]; then
sudo /bin/umount /mnt/union/dev 2> /dev/null
fi
if [ -n "$(mount | grep -w /mnt/union )" ]; then
sudo /bin/umount /mnt/union 2> /dev/null
fi
}
mount_unionfs
# entrar en el chroot
sudo /usr/sbin/chroot /mnt/union /bin/su --shell /bin/bash --login $USER
# desmontar sistemas de archivos temporales
umount_unionfs
EOF
Agrega el nuevo shell de inicio de sesión al archivo /etc/shells. Tendrás que hacer esto cuando PAM verifique el shell.
3.3 Crear usuario y grupo.
Crea un nuevo grupo y usuario con este script como shell:
groupadd -g 27 uniongroup
useradd -c "Usuario de prueba para chrooted union." -d /home/unionuser \
-m -s /bin/chroot-union -g uniongroup -u 27 unionuser
passwd unionuser3.4 Dar al usuario suficientes derechos
Dale al nuevo usuario más derechos con sudo. Agrega la siguiente línea al archivo de configuración de sudo, /etc/sudoers:
unionuser ALL=(ALL) ALL
Nota: hay otras formas de dar permisos a este usuario. Estoy revisándolas en este momento.
Nota: dar estos permisos completos es demasiado para un usuario normal. Pero para un usuario que instalará software y modificará tu sistema es necesario.
Lo que es posible
Entorno seguro y protegido para usuarios normales
Esta construcción es muy adecuada para usuarios invitados, a los que no puedes confiar. Lo primero que intenté fue iniciar una sesión gráfica. No tuve ningún problema.
Instalar software como este usuario
Otro uso posible es la instalación de software como este usuario. Esto se puede hacer de la siguiente manera:
- como este usuario, instala tu software. Debido a la construcción especial, todos los cambios van a la caché.
- después de cerrar sesión, compara el contenido de la caché con el sistema real.
- el usuario controlador (root) tiene la opción de hacer la instalación real simplemente moviendo el contenido de la caché a la raíz.
Por ejemplo, la compilación e instalación de un pequeño paquete, audiofile-0.2.6. Supongamos que la fuente está en /tmp. Primero inicia sesión:
[root@hostname ]# login
hostname login: unionuser
Password:
Last login: Wed Jun 20 19:58:32 CEST 2007 on pts/0
[unionuser@hostname ]$Ahora compila e instala el paquete:
[unionuser@hostname ]$ cd /tmp/audiofile-0.2.6
[unionuser@hostname ]$ ./configure –prefix=/usr
[unionuser@hostname ]$ make
[unionuser@hostname ]$ sudo make install
Ahora sal de la sesión y verifica el contenido de la caché:
[unionuser@hostname ]$exit
[root@hostname ]# cd /mnt/cache
[root@hostname ]# ls -Al
drwxr-xr-x 3 root root 1024 2007-06-05 17:32 home
drwxr-xr-x 6 root root 1024 2007-06-05 17:37 usr
drwxr-xr-x 3 root root 1024 2007-06-05 17:32 var
[root@hostname ]#
El directorio home aparece aquí porque el shell Bash cambia el archivo .bash_history; el directorio var aparece debido a cambios en el archivo /var/run/utmp y el directorio /var/run/sudo. Esto prueba que funciona como debería.
Ahora, al mirar los cambios en el directorio /usr donde he instalado el software, da:
[root@hostname ]# find usr -type f
usr/lib/pkgconfig/audiofile.pc
usr/lib/libaudiofile.la
usr/lib/libaudiofile.a
usr/lib/libaudiofile.so.0.0.2
usr/include/audiofile.h
usr/include/aupvlist.h
usr/include/af_vfs.h
usr/bin/audiofile-config
usr/bin/sfconvert
usr/bin/sfinfo
usr/share/aclocal/audiofile.m4
[root@hostname ]# find usr -type d
usr
usr/lib
usr/lib/pkgconfig
usr/include
usr/bin
usr/share
usr/share/aclocal
Como puedes ver, todo está en el directorio /mnt/cache/usr.
Puedes hacer una copia de seguridad de esto:
[root@hostname ]# find usr | sort -u > /tmp/filelist-audiofile-0.2.6
[root@hostname ]# tar --create --files-from=/tmp/filelist-audiofile-0.2.6 \
--file=/tmp/install-audiofile-0.2.6.tar --directory=/mnt/cache \
--no-recursion --absolute-names --preserve-permissionsTambién es muy posible hacer una copia de seguridad de todos los archivos que serán sobrescritos:
[root@hostname ]# for installfile in $(cat /tmp/filelist-audiofile-0.2.6); do \
if [ -e "/$installfile ]; then \
echo "/$installfile" >> /tmp/backup-audiofile-0.2.6 \
fi \
done
[root@hostname ]# tar --create --files-from=/tmp/backup-audiofile-0.2.6 \
--file=/tmp/backup-audiofile-0.2.6.tar --directory=/mnt/cache \
--no-recursion --absolute-names --preserve-permissionsAhora haz la instalación real copiando todos los archivos a la raíz:
[root@hostname ]# for installfile in $(cat /tmp/filelist-audiofile-0.2.6); do \
cp --verbose --force --recursive --parents --no-dereference \
--preserve --target-directory=/ $installfile \
doneNota: los comandos anteriores son para ilustrar la idea. He creado scripts que realizan la copia de seguridad, la verificación y la instalación, y funciona muy bien.
Recibe nuevas publicaciones en tu bandeja de entrada.
No spam. Cancela la suscripción en cualquier momento.