Para mantener la seguridad en nuestro servidor es altamente recomendable crear un servidor virtual por cada servicio que deseamos ofrecer (mail, dns, http, etc) dejando el servidor real libre de cualquier programa susceptible de Bugs, evitando de esta forma que un atacante pueda explotar dichos Bugs y penetrar así nuestro sistema, en freebsd tenemos una excelente forma de lograr todo esto mediante el sistema de jails[1][2].
Es necesario mencionar que el hecho de tener servidores virtuales para cada uno de nuestros servicios no nos exenta de que un atacante penetre alguno de ellos (eso dependerá de que tan a menudo actualizamos el software de nuestros servicios aplicándoles los respectivos parches de seguridad que vayan saliendo).
Sin embargo utilizando servidores virtuales para cada servicio, si alguno de ellos es comprometido, el atacante estará limitado a ese servidor virtual en particular, permaneciendo los demás servidores virtuales y el sistema real íntegros, es por tal motivo que es sumamente importante mantener el sistema real lo mas simple posible evitando instalar cualquier servicio en el, puesto que si el sistema real es comprometido tendremos que considerar todos los servidores virtualizados (que son soportados por el sistema real) comprometidos de igual forma..
Plataforma: FreeBSD: 7.2-RELEASE #0
IP del servidor/sistema real: 192.168.1.64/24
Introducción a ezjail
ezjail[3] es un framework que permite crear y administrar servidores virtuales utilizando el sistema de jails de FreeBSD.
Este tipo de virtualizacion[4] comparte el kernel con el servidor real teniendo un userland, filesystem y subsistema de red del kernel totalmente aislado del servidor real y los demás servidores virtuales, este tipo de virtualización tiene la ventaja de ser muy rápido en comparación con otro tipo de virtualizaciones como la que lleva a cabo vmware y otros softwares de virtualización.
El Framework ezjail consiste de tres partes fundamentales.
Dos scripts:
- ezjail-admin: Utilizado para crear, listar, actualizar y remover instancias de servidores virtualizados, adicionalmente el script ezjail-admin es utilizado para crear y actualizar el basejail.
- ezjail.sh: Utilizado para iniciar, detener y reiniciar los entornos virtualizados.
Basejail:
Con basejail nos referimos al directorio que contiene todos los binarios y librerías del userland que utilizarán los servidores virtuales el cual será montado en modo de solo lectura en todos los entornos virtualizados mediante mount_nullfs(8), este hecho nos proporciona varias ventajas como son:
- Ahorro de espacio en el disco duro.
- Facilidad de actualización de todos los servidores virtuales: (actualizando un único basejail tendremos actualizado todo el userland de los servidores virtuales).
- Debido a la característica de solo lectura al montar el basejail, un intruso no podrá instalar rootkits que reemplacen archivos binarios del sistema base.
Instalando ezjail
ezjail esta disponible en la colección de ports[5] así es que para instalarlo no tenemos más que ejecutar los siguientes comandos:
realsystem# cd /usr/ports/sysutils/ezjail
realsystem# make
realsystem# make install
El proceso anterior creará los scripts necesarios (ezjail-admin y ezjail-sh) además de crear e instalar el archivo de configuración ezjail.conf.
El archivo ezjail.conf
El archivo ezjail.conf contiene variables que controlan algunos aspectos de los scripts del Framework ezjail, por default no hace falta mover nada a este archivo de configuración para poder trabajar con ezjail sin embargo vale la pena mencionar algunas opciones de el archivo.
- ezjail_jaildir: indica el directorio donde se crearan los servidores virtualizados.
- ezjail_jailtemplate: indica donde se encuentra el template (plantilla) usada cada vez que se crea un nuevo servidor virtual.
- ezjail_jailbase: indica donde se encuentra el directorio basejail (ya hablamos de este directorio anteriormente).
- ezjail_sourcetree: indica en que directorio se encuentran los archivos fuente del sistema real.
- ezjail_ftphost: indica de que servidor se descargara el directorio basejail (en caso de no crearlo nosotros mismos).
Creando el basejail
Existen dos formas diferentes de crear el directorio basejail, los cuales son descargándolo desde algún servidor ftp o creando el directorio y su contenido nosotros mismos, afortunadamente si decidimos crearlo nosotros mismos, ezjail nos facilita enormemente la forma de hacerlo.
Para descargar el directorio basejail junto con todo su contenido ejecutamos el comando:
ezjail-admin install
Adicionalmente podemos pasar los parámetros –s –m y –p los cuales descargarán e instalarán en el directorio basejail el código fuente del sistema, las paginas man y el árbol de ports.
Para crear el directorio basejail por nosotros mismos tenemos que ejecutar el comando siguiente:
realsystem# ezjail-admin update –b -p
El cual ejecutará todo lo necesario para construir un userland desde los archivos de código fuente de nuestro sistema (/usr/src), esto implica que el script ejecutará los comandos make world y make installworld e instalará todo dentro del directorio basejail, este procedimiento tomará un tiempo considerable dependiendo las características de nuestro hardware, el parametro –p le indica al script ezjail-admin que tambien instale el arbol de ports dentro del directorio basejail.
Adicionalmente a la creación del directorio basejail el proceso de creación de este mismo directorio creara otros dos directorios los cuales son:
newjail: este directorio representa la plantilla que será aplicada a cada uno de los servidores virtuales que creemos, contiene varios archivos que serán copiados al nuevo servidor virtual.
flavours: este directorio contiene otros directorios los cuales cada uno representa una plantilla diferente que sobrescribe la plantilla contenida en el directorio newjail y su función es darnos las capacidad de crear servidores virtuales con configuraciones definidas por nosotros.
Una vez creado el directorio basejail podemos crear nuestros servidores virtuales.
Pre-requisitos
El único requisito que necesitamos cumplir antes de utilizar servidores virtuales es que los servicios que esta corriendo el sistema real escuchen únicamente en la dirección ip asignada a este mismo y no estar escuchando en las demás ips que serán asignadas a los servidores virtuales, si el sistema real que estamos usando acaba de ser instalado no tendremos mucho trabajo que realizar para lograr esto, de otra forma si al servidor real le hemos instalado algunos servicios (dns, http, smpt, etc) lo más recomendable será que detengamos dichos servicios y los migremos en un servidor virtual para mantener limpio y seguro el sistema real, para averiguar que servicios están escuchando en que ip haremos uso del comando sockstat(1).
Los flags que pasaremos al comando sockstat son los siguientes:
-l Lista todos los sockets que estan a la escucha en nuestro sistema
-4 Muestra todos los sockets de la familia AF_INET (ipv4)
-6 Muestra todos los sockets de la familia AF_INET6 (ipv6)
realsystem# sockstat -l4
USER | COMMAND | PID | FD | PROTO | LOCAL ADDRESS | FOREIGN ADDRESS |
root | sendmail | 750 | 4 | tcp4 | 127.0.0.1:25 | *:* |
root | sshd | 744 | 4 | tcp4 | *:22 | *:* |
root | syslogd | 612 | 7 | udp4 | *:514 | *:* |
realsystem#
Cada una de las líneas de salida de sockstat representa un socket escuchando.
Del resultado que hemos obtenido nos interesan únicamente las columnas COMMAND y LOCAL ADDRESS, la primera columna indica a que servicio se refiere la salida, la columna LOCAL ADDRESS nos indica en que dirección esta escuchando el socket, simplificando tenemos:
COMMAND | PROTO | LOCAL ADDRESS |
sshd | tcp4 | *:22 |
syslogd | udp4 | *:514 |
Analizando las líneas anteriores podemos ver que tanto el servicio de ssh y de syslog están escuchando en todas las ip’s del systema real, por tanto tenemos que modificarlos para que solo escuchen en la ip asignada al servidor real (192.168.1.64).
Para lograr que el servicio de ssh escuche solo en la dirección del sistema real editamos el archivo /etc/ssh/sshd_config y editamos la linea ListenAddress para que quede de la siguiente manera:
ListenAddress 192.168.1.64
Finalmente reiniciamos el servicio de ssh:
realsystem# /etc/rc.d/sshd restart
Stopping sshd.
Starting sshd.
realsystem#
Para lograr que el servicio syslog escuche solo en la ip del sistema real (192.168.1.64) agregamos las siguientes líneas en el archivo /etc/rc.conf
syslogd_flags="-sS"
syslogd_flags="-b 192.168.1.64"
Reiniciamos el servicio de syslogd para que los cambios surtan efecto:
realsystem# /etc/rc.d/syslogd restart
Stopping syslogd.
Starting syslogd.
realsystem#
Y volvemos a verificar con sockstat:
realsystem# sockstat -l46
USER | COMMAND | PID | FD | PROTO | LOCAL ADDRESS | FOREIGN ADDRESS |
root | sendmail | 764 | 3 | tcp4 | 127.0.0.1:25 | *:* |
root | sshd | 746 | 3 | tcp4 | 192.168.1.64:22 | *:* |
root | syslogd | 637 | 6 | udp4 | 192.168.1.64:514 | *:* |
realsystem#
Creando nuestro primer servidor virtual
Para poder crear los entornos virtuales con ezjail es necesario tener una ip disponible para asignarle y un nombre, ya sea que tengamos varias ip’s disponibles o que podamos crear un alias para asignar una nueva dirección ip a nuestra tarjeta de red, en este caso optaremos por la segunda opción, así es que ejecutamos el siguiente comando:
realsystem# ifcofing fxp0 alias 192.168.1.100 netmask 255.255.255.0
El cual asignara la dirección 192.168.1.100 con mascara de red 255.255.255.0 a nuestra tarjeta de red fxp0.
Para que esta dirección sea persistente incluso si reiniciamos el sistema agregamos la siguiente línea al archivo /etc/rc.conf
ifcofig_fxp0_alias0=”192.168.1.100 netmask 255.255.255.0”
Ahora estamos listos para crear el primer servidor virtual, ejecutamos el siguiente comando:
realsystem# ezjail-admin create virtual01 192.168.1.100
virtual01 será tanto el nombre del jail y nombre del host de nuestro servidor virtual.
192.168.1.100 será la ip que tendrá nuestro servidor virtual.
El proceso de creación de nuestro servidor virtual colocará un archivo de configuración propio del entorno ezjail en el directorio /usr/local/etc/ezjail/{nombre} donde el “{nombre}” será el que corresponda a cada uno de nuestros servidores virtuales, dicho archivo de configuración es usado por el escript ezjail.sh que es el encargado de iniciar cada uno de nuestros servidores virtuales.
El proceso de creación también colocará un archivo fstab.{nombre} en el directorio /etc
Donde “{nombre}” será el que corresponda a cada uno de nuestros servidores virtuales, este archivo indicará en donde se debe montar el basejail para que sea accesible en nuestro servidor virtual, este archivo es usado por el script ezjail.sh que es el encargado de iniciar cada uno de nuestros servidores virtuales.
Iniciando nuestros servidores virtuales
El script /usr/local/etc/rc.d/ezjail.sh es el encargado de realizar esta tarea por nosotros, para que el script funcione tenemos que agregar la siguiente línea al archivo /etc/rc.conf
ezjail_enable="YES"
Una vez que hemos agregado la línea anterior ejecutamos el siguiente comando para iniciar nuestro servidor virtual:
realsystem# /usr/local/etc/rc.d/ezjail.sh start virtual01
Configuring jails:.
Starting jails: virtual01.
realsystem#
Si en algún momento necesitáramos detener nuestro servidor virtual lo podemos hacer con el siguiente comando:
realsystem# /usr/local/etc/rc.d/ezjail.sh stop virtual01
Ahora cada vez que reiniciemos el sistema el script /usr/local/etc/rc.d/ezjail.sh se encargará de iniciar todos nuestros servidores virtuales.
Nota: si bien hemos dicho que el script /usr/local/etc/rc.d/ezjail.sh es el encargado de iniciar y detener los servidores virtuales tambien podemos hacer uso del comando ezjail-admin de la siguiente manera:
realsystem# ezjail-admin stop virtual01
Stopping jails: virtual01.
realsystem# ezjail-admin start virtual01
Configuring jails:.
Starting jails: virtual01.
realsystem#
Configuración inicial de nuestros servidores virtuales
Ahora que ya tenemos creado y funcionando nuestro servidor virtual necesitamos una forma de manejarlo para poder implementar cualquier servicio que deseemos funcione dentro de nuestro servidor virtual, ezjail nos proporciona una forma sencilla de acceder a nuestro nuevo servidor virtual mediante el siguiente comando (es necesario que el servidor virtual este en ejecución):
realsystem# ezjail-admin console virtual01
El cual nos dará una shell como usuario root para poder manipular y ajustar todo lo que necesitemos en nuestro nuevo servidor virtual, en este momento podemos realizar cualquier tarea que necesitemos, incluso podemos habilitar el acceso ssh que nos permitirá entrar directamente a nuestro servidor virtual mediante la red.
Viendo el estado de nuestros servidores virtuales
El Framework ezjail nos proporciona una forma muy sencilla de ver que servidores virtuales hemos creado y cual es su estado, para hacerlo solo tenemos que ejecutar el comando siguiente:
realsystem# ezjail-admin list
STA JID IP Hostname Root Directory
--- ----- --------------- ---------------------------- -------------------------
DR 2 192.168.1.100 vitual01 /usr/jails/virtual01
La primera columna corresponde al estado de nuestro servidor virtual y esta compuesto por 2 o 3 letras independientes, el significado de cada una de las letras es el siguiente:
D entorno jail basado en directorio (basejail)
I entorno jail basado en un archivo de imagen
B entorno jail basado en un archivo de imagen encriptada con el método BDE.
E entorno jail basado en un archivo de imagen encriptada con el método ELI.
R entorno jail actualmente en ejecución.
A entorno jail basado en un archivo de imagen ligado al FS pero no en ejecución.
S entorno jail actualmente detenido.
N entorno jail marcado para no ser iniciado en el próximo reinicio del sistema.
La segunda columna corresponde al id que identifica de forma única a nuestro servidor virtual.
La tercera columna corresponde a la ip que tiene asignada nuestro servidor virtual.
La cuarta columna representa el nombre de nuestro servidor virtual que inicialmente es el nombre de host de nuestro servidor virtual.
La quinta columna indica en donde se encuentra el directorio que contiene nuestro servidor virtual.
Manejando los servidores virtuales
Si en algún momento necesitamos que alguno de nuestros servidores virtuales no se inicie automáticamente cuando el sistema real reinicie podemos especificarlo mediante el siguiente comando:
realsystem# ezjail-admin config –r norun virtual01
De esta forma el servidor virtual con nombre virtual01 quedará marcado para no ser inicializado cuando el sistema real reinicie.
Revisamos el estado del servidor virtual para verificar el cambio:
realsystem# ezjail-admin list
STA JID IP Hostname Root Directory
--- ----- --------------- ---------------------------- -------------------------
DRN 2 192.168.1.100 virtual01 /usr/jails/virtual01
realsystem#
Como podemos observar, en la columna STA de la salida del comando anterior el servidor virtual virtual01 aparece marcado con una letra N que indica que en el siguiente reinicio del sistema real este servidor virtual no se iniciara automáticamente.
Para revertir el proceso anterior, es decir que el servidor virtual si se inicie automáticamente cuando el sistema real reinicie ejecutamos el siguiente comando:
realsystem# ezjail-admin config -r run virtual01
Revisamos nuevamente el estado:
realsystem# ezjail-admin list
STA JID IP Hostname Root Directory
--- ----- --------------- ---------------------------- -------------------------
DR 2 192.168.1.100 virtual01 /usr/jails/virtual01
realsystem#
El comando ezjail-admin config nos permite realizar unas cuantas cosas mas, entre ellas renombrar nuestros servidores virtuales, para renombrar el servidor virtual es necesario que no se encuentre en ejecución al momento re renombrarlo, así es que procedemos a detener nuestro servidor virtual:
realsystem# /usr/local/etc/rc.d/ezjail.sh stop virtual01
Stopping jails: virtual01.
realsystem#
Procedemos a renombrar el servidor virtual:
realsystem# ezjail-admin config -n vdns.ezjailexamples.org virtual01
Jail has been renamed. You might want to check /usr/local/etc/ezjail/ vdns_ezjailexamples_org and /etc/fstab.vdns_ezjailexamples_org to ensure everything has gone smoothly.
Also check settings in your Jail's /etc/ directory (especially /etc/rc.conf).
realsystem#
Como podemos observar al terminar el proceso de renombre el script ezjail-admin nos arroja mensajes que debemos tener en cuenta para revisar que todo haya ido bien, si tenemos alguna configuración dentro de nuestro servidor virtual que haga uso del hostname tenemos que cambiarlo.
Para verificar que el servidor virtual ha sido renombrado, utilizaremos el comando ezjail-admin list:
realsystem# ezjail-admin list
STA JID IP Hostname Root Directory
--- ----- --------------- ---------------------------- -------------------------
DS N/A 192.168.1.100 vdns.ezjailexamples.org /usr/jails/vdns.ezjailexamples.org
realsystem#
Auditando los ports instalados en nuestros servidores virtuales
Como mencionamos al principio de este documento es sumamente importante estar al día con las vulnerabilidades que se van encontrando en el software que instalamos en cada uno de nuestros servidores virtuales y actualizarlas o aplicarles los respectivos parches de seguridad, en freebsd contamos con una excelente herramienta que nos reporta si hay vulnerabilidades en el software instalado en nuestro sistema via ports, se trata de la herramienta portaudit[6], si bien podemos instalar portaudit en cada uno de los servidores virtuales que vamos a manejar dentro de nuestro sistema real sería algo tardado y engorroso entrar en cada uno de esos servidores virtuales y ejecutar portaudit cada vez que queramos revisar si hay problemas en el software que hemos instalado, para facilitarnos este trabajo existe otro port llamado jailaudit[7] que podemos instalar en nuestro sistema base y que creara un reporte de vulnerabilidades por cada servidor virtual que tengamos instalado haciendo uso de poraudit instalado en el sistema base, para instalar jailaudit entramos en el directorio /usr/ports/ports-mgmt/jailaudit
realsystem# cd /usr/ports/ports-mgmt/jailaudit
y ejecutamos
realsystem# make && make install
Una vez que tengamos instalado el jailaudit (el cual instalará automáticamente portaudit) seremos capaces de generar reportes fácilmente para cada uno de nuestros servidores virtuales simplemente ejecutando el siguiente comando:
realsystem# jailaudit generate
Downloading a current audit database:
auditfile.tbz 100% of 56 kB 55 kBps
New database installed.
Database created: Mon Jul 27 15:50:01 PDT 2009
realsystem#
en este momento jailaudit habrá revisado todos nuestros servidores virtuales y habrá generado sus respectivos reportes, en mi caso tengo instalados dos servidores virtuales los cuales son:
realsystem# ezjail-admin list
STA JID IP Hostname Root Directory
--- ----- --------------- ---------------------------- -------------------------
DR 1 192.168.1.201 vhttp2.ezjailexamples.org /usr/jails/vhttp2.ezjailexamples.org
DR 2 192.168.1.100 vdns.ezjailexamples.org /usr/jails/vdns.ezjailexamples.org
realsystem#
Por lo tanto jailaudit ha generado dos reportes independientes, los cuales siempre serán colocados en la ruta /usr/local/jailaudit/reports/.
viendo el contenido de ese directorio podemos ver los dos reportes creados:
realsystem# ls /usr/local/jailaudit/reports/
vdns.ezjailexamples.org_2 vhttp2.ezjailexamples.org_1
realsystem#
el nombre de cada uno de los reportes es simplemente el nombre de cada uno de los servidores virtuales mas el id que los identifica de forma única, los reportes son simplemente archivos de texto que contienen la salida de portaudit así es que podemos verlos con cualquier herramienta para visualizar texto:
realsystem# cat /usr/local/jailaudit/reports/vdns.ezjailexamples.org_2
0 problem(s) found.
realsystem# cat /usr/local/jailaudit/reports/vhttp2.ezjailexamples.org_1
0 problem(s) found.
realsystem#
En este momento no hay problemas conocidos en ninguna aplicación que hay instalada en los servidores virtuales.
Eliminando los servidores virtuales
Si por alguna razon ya no vamos a hacer uso de alguno de nuestros servidores virtuales podemos eliminarlos sin mayor problema con el siguiente comando:
realsystem# ezjail-admin delete -w vhttp2.ezjailexamples.org
realsystem#
Nota: para eliminar los servidores virtuales estos mismos no deben estar en ejecución.
Algunas variables del kernel sobre el sistema de jails
security.jail.allow_raw_sockets: determina si en el servidor virtual se pueden crear sockets raws, al permitirlo utilidades como ping o traceroute estaran disponibles para usarlas, sin embargo los sockets raws se pueden usar de forma maliciosa ya que permiten generar paquetes de red con datos definidos totalmente por un usuario.
security.jail.sysvipc_allowed: determina si los procesos que están dentro del jail tienen o no acceso a las primitivas IPC de System V. Aunque esto podría permitir que los procesos de nuestro jail afecten otros procesos fuera del jail.
security.jail.set_hostname_allowed: estavariable determina si los usuarios privilegiados dentro del servidor virtual pueden o no cambiar el nombre del host, si en el servidor virtual se permitirá la entrada a usuarios teceros es recomendable establecer esta variable a 0.
security.jail.socket_unixiproute_only: El sistema de jails permite la virtualizacion solo de sockets tipo ip y sockets unix, sin embargo dentro del sistema de jails es factible utilizar otros protocolos no-ip como lo es IPX, para lograr esto hay que establecer esta variable a 0 sin embargo es poco recomendable hacer esto, ya que el acceso a protocolos distintos de ip estará disponible a todos los servidores virtuales.
Actualizando el arbol de ports de los servidores virtuales
Para actualizar el árbol de ports de los servidores virtuales (que esta contenido en el directorio basejail) haremos uso del comando ezjail-update mediante el parámetro –P (en mayúscula), esta tarea puede ser realizada mientras los servidores virtuales están en ejecución sin ningún problema.
realsystem# ezjail-admin update -P
Looking up portsnap.FreeBSD.org mirrors... 3 mirrors found.
Fetching snapshot tag from portsnap2.FreeBSD.org... done.
Fetching snapshot metadata... done.
Updating from Sun Jul 26 13:04:01 PDT 2009 to Mon Jul 27 21:01:33 PDT 2009.
Fetching 3 metadata patches.. done.
Applying metadata patches... done.
Fetching 1 metadata files... done.
Fetching 78 patches.....10....20....30....40....50....60....70.... done.
Applying patches... done.
Fetching 3 new ports or files... done.
Removing old files and directories... done.
Extracting new files:
/usr/jails/basejail/usr/ports/GIDs
/usr/jails/basejail/usr/ports/UIDs
/usr/jails/basejail/usr/ports/UPDATING
.
.
.
.
Building new INDEX files... done.
realsystem#
Actualizando el basejail
En ocasiones será necesario que actualicemos nuestro sistema operativo, ya sea para aplicar parches de seguridad o porque deseamos tener alguna nueva característica que ha sido implementada recientemente, cada vez que actualicemos nuestro sistema base del servidor real será necesario que también actualicemos el directorio basejail, si hemos actualizado nuestro sistema operativo desde las fuentes solo tendremos que ejecutar el comando ezjail-admin update con el flag –i (instalar) y ezjail realizara un make installworld sobre el directorio basejail, omitiendo realizar un make buildworld, esto nos ahorrara una gran cantidad de tiempo, si no se especifica el flag -i el comando make buildworld será invocado.
Conclusiones:
Hemos visto como crear y manipular servidores virtuales mediante el sistema de jails de FreeBSD, como pudimos darnos cuenta los servidores virtuales agregan un nivel de seguridad a todo el conjunto de servicios y sistema real que administramos, sin embargo la mejor forma de asegurarnos de correr el menor riesgo posible de una penetración es mantener actualizado el software que utilizamos y estar al pendiente de las alertas de seguridad, así como auditar regularmente nuestros sistemas.
Enlaces:
[1] http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/jails.html
[2] http://en.wikipedia.org/wiki/FreeBSD_jail
[3] http://erdgeist.org/arts/software/ezjail/
[4] http://en.wikipedia.org/wiki/Operating_system-level_virtualization
[5] http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ports-using.h…
[6] http://www.freebsd.org/doc/en/books/handbook/security-portaudit.html
[7] http://anonsvn.h3q.com/projects/jailaudit/
Autor: Jorge Sánchez Escobedo
Fecha: 29/07/2009
Se otorga permiso para copiar, modificar y distribuir este documento en cualquier medio siempre y cuando se mantenga el autor y esta nota.
Cualquier comentario o critica son bienvenidos.