Вы находитесь на странице: 1из 8

Configuracin de servidores virtuales con

JAIL + NAT
Autor: Espartano
Fecha: 15/01/2006
Plataforma: FreeBSD 5.4-STABLE
Se otorga permiso para copiar, modificar y distribuir este documento en
cualquier medio siempre y cuando se mantenga el autor y esta nota.
Introduccion:
Este documento explica como crear y configurar servidores virtuales para que puedan correr los
servicios que deseamos ofrecer de una forma aislada y con una sola tarjeta de red como si se
tratase de varios servidores independientes y mediante el uso de NATD redirigiremos las
peticiones de cada servicio al servidor virtual correspondiente :).
Configurando nuestro kernel:
Primero que nada tenemos que asegurarnos de tener las fuentes instaladas en nuestro sistema, si
no es asi podemos hacer uso de /stand/sysinstall para lograrlo, una vez con las fuentes
en nuestro sistema debemos hacer lo siguiente procedemos a configurar nuestro kernel con las
siguientes opciones:
options IPFIREWALL
options IPDIVERT
options IPFIREWALL_DEFAULT_TO_ACCEPT
options IPFIREWALL_VERBOSE
options BRIDGE

Creando el entorno del servidor virtual:
Ahora tenemos que crear el userland de nuestro servidor virtual, creamos el directorio en donde
queremos que se instale nuesto jail, por ejemplo /usr/jail y ejecutamos los siguientes comandos:
Moscu# D=/usr/jail
Moscu# cd /usr/src
Moscu# mkdir -p $D
Moscu# make world DESTDIR=$D
Moscu# cd etc
Moscu# make distribution DESTDIR=$D
Moscu# mount_devfs devfs $D/dev
Moscu# cd $D
Moscu# ln -sf dev/null kernel
Esto creara dentro de /usr/jail todo el usrland como si se tratara de un sistema independiente
menos el kernel que sera compartido por ambos sistemas, el real y el virtual, todos los sistemas
virtuales que creemos compartiran el kernel. No debemos olvidar montar el sistema devfs dentro
del directorio /dev de nuestro jail antes de arrancar el servidor virtual cada vez que reiniciemos
nuestro equipo, o agregar unas lineas al /etc/rc.conf como veremos mas adelante para que esto se
haga de forma automatica.
NOTA: en FreeBSD 5.3 RELEASE Make tenia problemas con las variables de entorno,
para solucionar eso tenemos que sustituir la linea make world DESTDIR=$D por
make buildworld installworld DESTDIR=/usr/jail
Creamos el directorio stand dentro del directorio raiz "/" del jail y copiamos el programa
sysinstall para poderlo usar dentro del servidor virtual:
Moscu# mkdir /usr/jail/stand
Moscu# cp /stand/sysinstall /usr/jail/stand/sysinstall
Preparando nuestro sistema:
Ahora tenemos que lograr que nuestros servicios del host anfitrion (el servidor real) escuchen
solo en su ip, para esto agregaremos las siguientes lineas en el /etc/rc.conf y suponiendo que la ip
del anfitrion es 172.16.1.36/16 agregamos lo siguiente:
inetd_flags="-wW -a 172.16.1.36"
rcpbind_enable="NO"
portmap_enable="NO"
syslogd_flags="-s -S"
syslogd_flags="-a 172.16.1.36"
Para apache editamos el /usr/local/etc/apache/httpd.conf y agregamos la siguente linea:
Listen 172.16.1.36:8080
Editamos el /etc/ssh/sshd_config y editamos las siguientes lineas:
ListenAddress 172.16.1.36
Port 2222
Creamos un ip alias que sera la ip en la que estara nuestro servidor virtual:
Moscu# ifconfig rl0 alias 172.16.1.100 netmask 255.255.0.0
Editamos el archivo /etc/rc.conf y agregamos lo siguiente para que el cambio sea permanente
cuando iniciemos:
ifconfig_rl0_alias0="172.16.1.100 netmask 255.255.0.0"
Arrancando nuestro servidor virtual por primera vez
En este momento estamos listos para arrancar nuestro servidor virtual podemos ejecutar desde
nuestro prompt:
Moscu# jail /usr/jail Svhttp 172.16.1.100 /bin/sh
Esto nos arrojara un prompt de root (#) en el cual debemos configurar algunas cosas como la
clave de root, instalar sudo y crear un usuario con sudo para poder logearnos con el desde la red
mediante ssh y poder manipular nuestro servidor virtual, suponiendo que tenemos acceso a
internet en el servidor real tambien debemos tenerlo en el virtual, para distinguir los comandos
del servidor real al del virtual antepondremos el prompt (Moscu#) y (#) respectivamente, asi es
que ejecutamos:
# pkg_add -r sudo
# adduser uj
cambiamos la pass de root:
# passwd
Ahora editamos el archivo /usr/local/etc/sudoers del servidor virtual y ponemos lo siguiente:
uj ALL=(ALL) ALL
uj ALL=(ALL) NOPASSWD: ALL
Con esto lograremos que el usuario que creamos en el servidor virtual (uj) pueda ejecutar
comandos de root sin ser root anteponiendo el comando sudo al comando a ejecutar, sudo se
puede configurar de varias maneras pero eso se sale del alcance del doc, mas informacion en la
page del manual de sudo. Ahora debemos editar el archivo /etc/rc.conf del servidor virtual y
agregamos lo siguiete:
sshd_enable="YES"
ifconfig_rl0="172.16.1.100"
defaultrouter="172.16.1.36"
host_name="Svhttp"
Editamos el archivo /etc/ssh/sshd.config del servidor virtual para lograr que el servicio de ssh de
este servidor virtual escuche solo en su correspondiente poniendo:
Port 22
ListenAddress 172.16.1.100
Nos salimos del servidor virtual con el comando exit y ahora si ya estamos listos para iniciar
nuestro servidor de forma permanente, para ello utilizamos el siguiente comando:
Moscu# jail /usr/jail Svhttp 172.16.1.100 /bin/sh /etc/rc
y ya podremos logearnos como usuario uj, instalar paquetes, levantar servicios etc etc. para
detener nuestro servidor virtual debemos logearnos por ssh y ejecutar el siguiente comando:
Svhttp# sudo KILL -TERM -1
Podemos crear tantos servidores virtuales como necesitemos para ofrecer los servicios que
queramos asignandole a cada uno un alias ip, en nuestro caso creamos dos servidores virtuales,
uno para ofrecer el servicio de web y otro para ofrecer servicio de ftp, y usaremos NATD para
redirigir las peticiones que recibe el ruteador y envia a la ip del servidor real a su correspondiente
servidor virtual.
Activando NATD con ipfw
Agregamos las siguientes lineas al archivo /etc/rc.conf :
firewall_enable="YES"
firewall_type="/etc/firewall.rules"
firewall_script="/etc/rc.firewall"
Creamos el archivo /etc/firewall.rules y agregamos lo siguiente:
-f flush
add divert natd all from any to any via rl0
Configurando NATD
Debemos configurar NATD para que redirija las peticiones de los servicios que llegan al servidor
real y deseamos que atienda alguno de los servidores virtuales basandonos en el puerto al que
van dirigidos los paquetes para distinguir entre un servicio u otro, para lograr eso agregamos al
archivo /etc/rc.conf del servidor virtual las siguientes lineas:
natd_enable="YES"
natd_interface="rl0"
natd_flags="-l -f /etc/rc.natd"
Creamos el archivo /etc/rc.natd y agregamos lo siguiente:
redirect_port tcp 172.16.1.100:80 80
redirect_port tcp 172.16.1.101:21 21
Lo que indican las lineas de arriba es que todo lo que vaya al puerto 21 de la maquina real
(extremo derecho de la linea) sera reenviado hacia el puerto 21 de la maquina con ip
172.16.1.101 (172.16.1.101:21) y todo lo que llegue al puerto 80 de la maquina real sera
reenviado al puerto 80 de la maquina con ip 172.16.1.100 :) de esta forma tendremos dos
servidores perfectamente aislados ejerciendo una funcione especifica de tal forma que si alguien
se apoderara de un servidor virtual solo tendria acceso a ese servidor y no a los demas o al
servidor real, para los mas paranoicos incluso pueden usar chroot para asegurar aun mas el
servicio que ofrece nuestro servidor virtual obteniendo asi doble seguridad ;)
Ahora ya tenemos listos los archivos necesarios para que la siguiente vez que arranque nuestra
maquina este listo el NATD con la redireccion de puertos pero si no queremos esperar podemos
ejecutar los siguientes comandos:
Moscu# ipfw add divert natd all from any to any via rl0
Moscu# natd -f /etc/rc.natd -n rl0
Configuracion adicional (devfs)
Ahora procedemos a configurar las reglas para que cuando montamos el sistema devfs dentro de
nuestro servidor virtual solo se vean los dispositivos necesarios para el funcionamiento del
servicio que corre nuestro servidor virtual, esto no es necesario realmente pero nos dara un poco
de seguridad adicional.
Copiamos el archivo /etc/defaults/devfs.rules a el directorio /etc/ y lo editamos para que quede de
la siguiente forma:

[devfsrules_hide_all=1]
add hide
[devfsrules_unhide_basic=2]
add path null unhide
add path zero unhide
add path crypto unhide
add path random unhide
add path urandom unhide
[devfsrules_unhide_login=3]
add path 'ptyp*' unhide
add path 'ptyq*' unhide
add path 'ptyr*' unhide
add path 'ptys*' unhide
add path 'ptyP*' unhide
add path 'ptyQ*' unhide
add path 'ptyR*' unhide
add path 'ptyS*' unhide
add path 'ttyp*' unhide
add path 'ttyq*' unhide
add path 'ttyr*' unhide
add path 'ttys*' unhide
add path 'ttyP*' unhide
add path 'ttyQ*' unhide
add path 'ttyR*' unhide
add path 'ttyS*' unhide
add path stdin unhide
add path stdout unhide
add path stderr unhide
[devfsrules_net=4]
add path cuaa0 unhide
add path 'net/*' unhide
add path net1 unhide
add path net2 unhide
add path net3 unhide
[devfsrules_jail=5]
add path ad0s2e unhide
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_net
Esto establece 5 grupos de reglas de devfs que pueden ser aplicadas a nuestro sistema o a algun
sistema virtual al momento de montar el sistema devfs dentro del directorio /dev, en el grupo de
reglas devfsrules_net desocultamos los dispositivos que usamos para la red y en el grupo de
reglas devfsrules_jail desocultamos la particion ad0s2e en la cual reciden nuestros servidores
virtuales (particion /usr del servidor virtual) ademas agregamos los demas grupos de reglas ya
que sera la regla devfsrules_jail la que aplicaremos a nuestros servidores virtuales.
Incluimos las siguientes lineas en /etc/rc.conf:
devfs_enable="YES"
devfs_rulesets="/etc/devfs.rules"
devfs_set_rulesets="devfsrules_jail"
Y ya tenemos listo todo para que al reiniciar se carguen las reglas que queremos aplicar, para
poder aplicar las reglas sin reiniciar tendremos que ingresar todas las reglas de los grupos a mano
con el comando devfs exceptuando los nombres de los grupos y los "include":

Moscu# devfs rule -s 5 add hide
Moscu# devfs rule -s 5 add path null unhide
Moscu# devfs rule -s 5 add path zero unhide
...
...
...
Moscu# devfs rule -s 5 add path net2 unhide
Moscu# devfs rule -s 5 add path net3 unhide
Moscu# devfs rule -s 5 add path ad0s2e unhide
Para aplicar las reglas a nuestro directorio /dev de nuestros servidores virtuales tenemos que
detener el servidor virtual logeandonos y ejecutando el comando que anteriormente
especificamos o si aun no montamos el sistema devfs en el directorio /dev del servidor virtual lo
montamos y ejecutamos:
Moscu# devfs -m /usr/jail/dev rule -s 5 applyset
Moscu# devfs -m /usr/jail/dev ruleset 5
En este momento ya podemos iniciar nuestro servidor virtual y las reglas de devfs se aplicaran.
Arrancando los servidores virtuales automaticamente
Ya hemos visto como editar el archivo /etc/rc.conf para que se inicien las configuraciones que
necesitamos, ahora veamos que lineas tenemos que agregar para que se inicien automaticamente
los servidores virtuales al momento del arranque de nuestro FreeBSD real :)
jail_enable="YES"
jail_list="Svftp Svhttp" #los nombres de los servidores virtuales

#ahora las configuraciones de cada uno de los servidores virtuales
jail_Svhttp_rootdir="/usr/jail"
jail_Svhttp_hostname="moscuhttp.org"
jail_Svhttp_ip="172.16.1.100" #el primer ip alias
jail_Svhttp_exec_start="/bin/sh /etc/rc"
jail_Svhttp_devfs_enable="YES"
jail_Svhttp_devfs_ruleset="devfsrules_jail" #la regla de devfs.rules
jail_Svftp_rootdir="/usr/jail2"
jail_Svftp_hostname="moscuftp.org"
jail_Svftp_ip="172.16.1.101" #el segundo ip alias
jail_Svftp_exec_start="/bin/sh /etc/rc"
jail_Svftp_devfs_enable="YES"
jail_Svftp_devfs_ruleset="devfsrules_jail"
No se olviden de poner las lineas de /etc/rc.conf para natd y devfs que especificamos en sus
respectivas secciones
Notas finales
Algunos servicios necesitan opciones especiales para correr dentro de jail ,tal es el caso de
Postgresql, si tenemos pensado correr un servidor postgresql dentro de alguno de nuestros
servidores virtuales tendremos que setear la variable del kernel security.jail.sysvipc_allowed con
el comando sysctl:
Moscu# sysctl security.jail.sysvipc_allowed=1
La variable security.jail.sysvipc_allowed determina si los procesos que estan dentro del jail
tienen o no acceso a las primitivas IPC de System V. Aunque esto podria permitir que los
procesos de nuestro jail afecten otros procesos fuera del jail.
Otras variables del kernel referentes a jail que podemos manipular son las siguientes:
security.jail.set_hostname_allowed determina si el usuario root del jail puede o no cambiar el
nombre del host virtual.
security.jail.getfsstatroot_only determina si los procesos que estan dentro del jail son capaces o
no de ver los datos de los diferentes puntos de montaje que hay en el sistema, o si solo seran
capaces de ver los puntos de montaje del propio servidor virtual
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.
Actualmente no existe un mecanismo para aplicar estas caracteristicas de forma indibidual a cada
uno de los jails que tengamos asi es que si activamos alguna de estas variables el cambio sera
para todos.
Si en algun momento queremos eliminar el jail porque ya no lo vamos a usar y queremos borrar
el directorio donde reside el userland de nuestro servidor virtual, primero tendremos que eliminar
el flag de inmutable que el proceso de creacion del userland del jail agrega a algunos archivos,
esto lo logramos mediante el comando chflags.
Moscu# chflags noschg -R /usr/jail
Moscu# rm -r /usr/jail
Cualquier comentario o critica son bienvenidos.
Agradecimientos
A ACMhUnTeR y todo el equipo de LinuxReal por toda la ayuda con FreeBSD y demas cosas.
A todo el equipo de artec-system.
A los amigos del irc por las platicas siempre tan instructivas/divertidas.

Вам также может понравиться