Herramientas de usuario

Herramientas del sitio


doc:freebsd:seguridad001

Configuracion de servidores virtuales con JAIL + NAT

Autor: Jorge Sánchez Escobedo

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:

  Moscu# make world DESTDIR=$D

Por:

  Moscu# buildworld
  Moscu# 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 individual 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.

doc/freebsd/seguridad001.txt · Última modificación: 2022/03/02 08:18 (editor externo)