Esta sección está basada en una idea
que Simon L. B. Nielsen presentó por primera vez en http://simon.nitro.dk/service-jails.html
y en
un artículo con contenido adicional escrito por Ken
Tom <locals@gmail.com>
. En esta sección
se detalla cómo configurar un sistema FreeBSD que
añade una capa adicional de seguridad mediante el uso
de jail(8). Para su verdadero aprovechamiento se asume
que el sistema en el que se vaya a aplicar ejecuta al menos
RELENG_6_0 y que la información que contienen las secciones
previas de este capítulo se ha comprendido totalmente.
Uno de los mayores problemas de las jaulas es la gestión de su proceso de actualización. Este proceso tiene a ser un problema porque cada jaula tiene que recompilarse íntegramente desde el código fuente cada vez que hay que actualizarla. Esto no es un gran problema si tenemos una sola jaula puesto que el proceso de actualización es bastante simple, pero si hay muchas jaulas será un trabajo largo y tedioso.
: Esta configuración requiere mucha experiencia con FreeBSD y el uso de sus características. Si los pasos que se detallan a continuación le parecen demasiado complicados puede echar un vistazo a sistemas más sencillos como sysutils/ezjail, que le permitirá acceder a un método de administración de jaulas en FreeBSD más sencillo y no es tan sofisticado como el que le proponemos a continuación.
El origen de esta idea es resolver los problemas antes descritos compartiendo el máximo posible entre distintas jaulas, de un modo seguro (utilizando montajes using read-only mount_nullfs(8) mounts) para que la actualización sea más sencilla y el ubicar servicios aislados en jaulas sea más interesante. Además, se presenta una forma sencilla de añadir o borrar jaulas así como una forma de actualizarlas.
Los ejemplos de servicios en este contexto son: un servidor HTTP,un servidor DNS, un servidor SMTP, etc.
Los objetivos de la configuración descrita en esta sección son:
Crear una estructura de jaulas simple y fácil de entender. Esto implica no tener que ejecutar un “installworld” completo en todas y cada una de las jaulas.
Facilitar la creación de nuevas jaulas o el borrado de jaulas previamente existentes.
Facilitar la actualización de jaulas ya existentes.
Hacer posible el uso de una rama de FreeBSD personalizada.
Ser paranoico en cuanto a seguridad, reduciendo todo lo posible la posibilidad de que los sistemas se vean comprometidos.
Ahorrar todo el espacio e inodos que sea posible.
Como ya se ha dicho, este diseño se basa en gran medida en el disponer de una única plantilla en modo de sólo lectura (a la que llamaremos nullfs) montada en cada jaula y un dispositivo en modo lectura-escritura por cada jaula. El dispositivo puede ser otro disco físico adicional, una partición o un dispositivo md(4) basado en un vnode. En este ejemplo utilizaremos montajes nullfs en modo lectura-escritura.
La estructura del sistema de ficheros se detalla en la siguiente lista:
Cada jaula se montará bajo /home/j
.
/home/j/mroot
será la plantilla para cada jaula y la
partición de sólo lectura para todas las
jaulas.
Se creará un directorio vacío para
cada jaula bajo el directorio /home/j
.
Cada jaula tendrá un directorio /s
que estará enlazado
con la parte de lectura-escritura del sistema.
Cada jaula tendrá su propio sistema en modo
lectura-escritura basado en /home/j/skel
.
Cada parte de lectura-escritura correspondiente a cada
jaula se creará en /home/js
.
Se asume que las jaulas se instalarán bajo
la partición /home
. Por supuesto esto no
es en absoluto obligatorio, pero hay que tener en cuenta que
debe hacerse el mismo cambio en cada uno de los ejemplos que
se muestran más adelante.
En esta sección se describen los pasos necesarios para crear la plantilla maestra que conformará la parte de sólo lectura que usarán las jaulas.
Siempre es recomendable actualizar el sistema FreeBSD a la última rama -RELEASE. Consulte el capítulo correspondiente de este libro si necesita más información. En caso de que la actualización no sea posible tendrá que usar “buidworld” para poder seguir adelante. También necesitará el paquete sysutils/cpdup. Usaremos portsnap(8) para descargar la Colección de Ports de FreeBSD. El capítulo sobre Portsnap es siempre una lectura muy recomendable para quienes no tengan experiencia con su funcionamiento.
Lo primero que haremos será crear una estructura de directorios para el sistema de ficheros de sólo lectura que contendrá los binarios de nuestras jaulas, luego iremos al directorio que contiene el árbol de código de FreeBSD e instalaremos el sistema de ficheros de sólo lectura en la plantilla de las jaulas:
#
mkdir /home/j /home/j/mroot
#
cd /usr/src
#
make installworld DESTDIR=/home/j/mroot
Una vez hecho esto, prepararemos la Colección de Ports de FreeBSD para nuestras jaulas así como un árbol de código FreeBSD, necesario para usar mergemaster:
#
cd /home/j/mroot
#
mkdir usr/ports
#
portsnap -p /home/j/mroot/usr/ports fetch extract
#
cpdup /usr/src /home/j/mroot/usr/src
Crear la estructura de directorios necesaria para la parte de lectura-escritura del sistema:
#
mkdir /home/j/skel /home/j/skel/home /home/j/skel/usr-X11R6 /home/j/skel/distfiles
#
mv etc /home/j/skel
#
mv usr/local /home/j/skel/usr-local
#
mv tmp /home/j/skel
#
mv var /home/j/skel
#
mv root /home/j/skel
Usamos mergemaster para instalar los ficheros de configuración que falten. Después nos libramos de los directorios adicionales que haya creado mergemaster:
#
mergemaster -t /home/j/skel/var/tmp/temproot -D /home/j/skel -i
#
cd /home/j/skel
#
rm -R bin boot lib libexec mnt proc rescue sbin sys usr dev
Ahora enlazamos simbólicamente el sistema
de ficheros de lectura-escritura con el sistema de
ficheros de sólo lectura. Por favor,
asegúrese de que los enlaces simbólicos
se crean en las ubicaciones correctas: s/
. Si se usan directorios
reales o directorios erróneos la instalación
no funcionará.
#
cd /home/j/mroot
#
mkdir s
#
ln -s s/etc etc
#
ln -s s/home home
#
ln -s s/root root
#
ln -s ../s/usr-local usr/local
#
ln -s ../s/usr-X11R6 usr/X11R6
#
ln -s ../../s/distfiles usr/ports/distfiles
#
ln -s s/tmp tmp
#
ln -s s/var var
Como último paso, cree un
/home/j/skel/etc/make.conf
genérico con el siguiente contenido:
WRKDIRPREFIX?= /s/portbuild
El tener WRKDIRPREFIX
configurado
de este modo hará posible compilar ports de FreeBSD
dentro de cada jaula. Recuerde que el el directorio
de los ports es de sólo lectura. La ruta
personalizada por WRKDIRPREFIX
permite ejecutar compilaciones en la parte de
sólo lectura de cada jaula.
Ya tenemos una plantilla de jaulas de FreeBSD completa,
así que podemos configurar nuestras jaulas en
/etc/rc.conf
. En este ejemplo crearemos
3 jaulas: “NS”,
“MAIL” y “WWW”.
Introduzca las siguientes lineas en el fichero
/etc/fstab
; con esto cada jaula
tendrá acceso a la plantilla de sólo lectura
y al espacio de lectura-escritura:
/home/j/mroot /home/j/ns nullfs ro 0 0 /home/j/mroot /home/j/mail nullfs ro 0 0 /home/j/mroot /home/j/www nullfs ro 0 0 /home/js/ns /home/j/ns/s nullfs rw 0 0 /home/js/mail /home/j/mail/s nullfs rw 0 0 /home/js/www /home/j/www/s nullfs rw 0 0
Las particiones que tienen un 0 en la columna
“pass” no serán revisadas por
fsck(8) durante el arranque y las que tienen
un 0 en la columna “dump” no serán
copiadas por dump(8). No nos interesa que
fsck compruebe la
integridad de montajes nullfs
ni que dump haga copias de
seguridad de montajes nullfs de sólo lectura de las
jaulas. Por esta razón el ejemplo de
fstab
tiene en las dos últimas
columnas “0 0”.
Configure las jaulas en
/etc/rc.conf
:
jail_enable="YES" jail_set_hostname_allow="NO" jail_list="ns mail www" jail_ns_hostname="ns.ejemplo.org" jail_ns_ip="192.168.3.17" jail_ns_rootdir="/usr/home/j/ns" jail_ns_devfs_enable="YES" jail_mail_hostname="mail.ejemplo.org" jail_mail_ip="192.168.3.18" jail_mail_rootdir="/usr/home/j/mail" jail_mail_devfs_enable="YES" jail_www_hostname="www.ejemplo.org" jail_www_ip="62.123.43.14" jail_www_rootdir="/usr/home/j/www" jail_www_devfs_enable="YES"
: La razón por la que
jail_
contiene nombre
_rootdir/usr/home
y no
/home
es que la ruta
física del directorio/home
en una instalación
de FreeBSD por omisión es /usr/home
. La variable
jail_
no debe apuntar a una ruta que
contenga un enlace simbólico porque sería
imposible arrancar las jaulas. Utilice
la herramienta realpath(1) para asegurarse del valor
exacto que debe asignar a la variable. Por favor, consulte
el aviso de seguridad FreeBSD-SA-07:01.jail para más
información.nombre
_rootdir
Creamos los puntos de montaje de sistemas de ficheros de sólo lectura correspondientes a cada jaula:
#
mkdir /home/j/ns /home/j/mail /home/j/www
Instalamos la plantilla de lectura-escritura dentro de cada jaula. Observe que utilizamos sysutils/cpdup para asegurarnos de que se hace una copia exacta de cada directorio:
#
mkdir /home/js
#
cpdup /home/j/skel /home/js/ns
#
cpdup /home/j/skel /home/js/mail
#
cpdup /home/j/skel /home/js/www
Llegados a este punto las jaulas están
configuradas y listas para arrancar. Monte los sistemas
de ficheros de cada jaula y luego arránquelas
con el script /etc/rc.d/jail
:
#
mount -a
#
/etc/rc.d/jail start
Las jaulas deberían haber arrancado. Asegúrese de ello con jls(8). La salida que verá debe parecerse a esta:
#
jls
JID IP Address Hostname Path 3 192.168.3.17 ns.ejemplo.org /home/j/ns 2 192.168.3.18 mail.ejemplo.org /home/j/mail 1 62.123.43.14 www.ejemplo.org /home/j/www
En este punto debería ser posible entrar a
cada una de las jaulas, añadir nuevos usuarios o
configurar dæmons. La columna JID
indica el número de identificación de cada
jaula que esté funcionando en el sistema. Con el
siguiente comando puede ejecutar tareas administrativas
en la jaula cuyo JID
sea 3:
#
jexec 3 tcsh
Llegará el momento en el que sea necesario actualizar el sistema, bien por seguridad o porque sea útil para las jaulas disponer de alguna nueva característica del sistema. El diseño de esta configuración facilita una forma fácil de actualizar sus jaulas. Además, minimiza la pérdida de servicio, puesto que las jaulas deben apagarse sólamente al final de todo el proceso. Se ofrece también la posibilidad de volver a la versión anterior en caso de que algo salga mal.
El primer paso es actualizar el servidor que aloja
las jaulas de la forma habitual. Después creamos
una plantilla de sólo lectura temporal en /home/j/mroot2
.
#
mkdir /home/j/mroot2
#
cd /usr/src
#
make installworld DESTDIR=/home/j/mroot2
#
cd /home/j/mroot2
#
cpdup /usr/src usr/src
#
mkdir s
La ejecución de installworld
crea unos cuantos directorios innecesarios que debemos
borrar:
#
chflags -R 0 var
#
rm -R etc var root usr/local tmp
Creamos de nuevo los enlaces simbólicos de lectura-escritura del sistema de ficheros principal:
#
ln -s s/etc etc
#
ln -s s/root root
#
ln -s s/home home
#
ln -s ../s/usr-local usr/local
#
ln -s ../s/usr-X11R6 usr/X11R6
#
ln -s s/tmp tmp
#
ln -s s/var var
Ha llegado el momento de parar las jaulas:
#
/etc/rc.d/jail stop
Desmontamos los sistemas de ficheros originales:
#
umount /home/j/ns/s
#
umount /home/j/ns
#
umount /home/j/mail/s
#
umount /home/j/mail
#
umount /home/j/www/s
#
umount /home/j/www
Los sistemas de ficheros de lectura-escritura
cuelgan del sistema de sólo lectura /s
y por tanto deben
desmontarse antes.
Movemos el sistema de ficheros de sólo lectura viejo y lo reemplazamos por el nuevo. Nos servirá de copia de seguridad y como archivo en caso de que haya problemas. Para darle un nombre usamos la fecha en la que se creado una nueva copia del sistema de ficheros de sólo lectura. Movemos también la Colección de Ports de FreeBSD al sistema de ficheros nuevo para ahorrar un poco más de espacio e inodos:
#
cd /home/j
#
mv mroot mroot.20060601
#
mv mroot2 mroot
#
mv mroot.20060601/usr/ports mroot/usr
Una vez llegados a este punto la nueva plantilla de sólo lectura está lista, de manera que lo único que nos queda por hacer es montar los sistemas de ficheros y arrancar las jaulas:
#
mount -a
#
/etc/rc.d/jail start
Compruebe con jls(8) si las jaulas han arrancado sin contratiempos. No olvide ejecutar mergemaster en cada jaula. Tendrá que actualizar tanto los ficheros de configuración como los scripts rc.d.
Puede descargar éste y muchos otros documentos desde ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/
Si tiene dudas sobre FreeBSD consulte la
documentación antes de escribir a la lista
<questions@FreeBSD.org>.
Envíe sus preguntas sobre la documentación a
<doc@FreeBSD.org>.