Gentoo Logo

Renuncia de responsabilidad: La versión original de este artículo fue publicada por IBM developerWorks y es propiedad de Westtech Information Services. Este documento es una versión actualizada del artículo original y contiene mejoras introducidas por el Equipo de Documentación de Gentoo.
Este documento carece de soporte activo.


Cortafuegos dinámicos iptables

Contenido:

1.  Introducción

Seguridad de red flexible (y divertida)

La mejor forma de ver los beneficios de las macros de cortafuegos dinámicos es verlas en acción. Para lograr esto, imaginemos que soy el administrador de un proveedor de servicios de internet (ISP) y que he configurado un cortafuegos Linux para proteger a mis clientes y a los sistemas internos de usuarios maliciosos en internet. Para lograrlo, mi cortafuegos utiliza la completa funcionalidad de iptables en el núcleo 2.4 para permitir que las conexiones de salida sean establecidas por mis clientes y servidores y, por supuesto, para permitir conexiones entrantes, pero solo para los servicios "públicos", como web, ftp, ssh y SMTP. Dado que he usado un diseño de denegación por defecto, cualquier conexión de internet a cualquier servicio que no sea público, como la caché de proxy de squid o el servidor Samba, serán automáticamente rechazadas. De hecho, tengo un cortafuegos muy decente que ofrece un buen nivel de protección para cualquiera de nuestros clientes en la ISP.

Durante la primera semana o así, el cortafuegos funciona estupendamente, pero entonces algo malo ocurre: Roberto, alguien que trabaja en un ISP de la competencia, decide inundar mi red con paquetes en un intento por denegar el servicio a mis clientes. Lamentablemente, Roberto ha estudiado cuidadosamente mi cortafuegos y sabe que mientras que estoy protegiendo muchos servicios internos, los puertos 25 y 80 deben estar públicamente accesibles, por lo que puedo recibir correo y servir solicitudes HTTP. Roberto decide aprovecharse de ello lanzando un ataque que consuma la mayor parte del ancho de banda contra mi servidor web y de correo.

En aproximadamente un minuto o así Roberto comienza su ataque, noto que la conexión al satélite comienza a verse saturada con paquetes. Después de echar un vistazo a la situación con tcpdump determino que este es otro ataque de Roberto, y averiguo las direcciones IP que está usando para ello. Ahora que dispongo de esta información, lo único que necesito hacer es bloquear estas direcciones IP, con ello se resolverá el problema -- una solución bastante sencilla, según creo.

Responder a un ataque

Cargo inmediatamente la macro con la configuración de mi cortafuegos en vi y comienzo a buscar una solución en mis reglas iptables, modificando mi cortafuegos para que bloquee los paquetes entrantes que manda Roberto. Después de un minuto o así, encuentro el lugar exacto para hacer la modificación adecuada en la regla DROP y la añado. Entonces reinicio el cortafuegos, pero cometí un pequeño error al crear las reglas. Cargo las macros del cortafuegos de nuevo, resuelvo el problema y treinta segundos después el cortafuegos está listo para bloquear el ataque del mes de Roberto. Al principio parece que he frustrado el ataque... Hasta que los teléfonos de la compañía comienzan a sonar. Aparentemente, Roberto ha sido capaz de inhabilitar mi red durante 10 minutos y ahora los clientes llaman para saber qué es lo que ha sucedido. Aún peor, después de unos minutos noto que la conexión al satélite vuelve a estar saturada de nuevo. Parece que Roberto está usando un nuevo conjunto de direcciones IP para sus ataques. En respuesta, comienzo a revisar las macros del cortafuegos, excepto que en esta ocasión estoy un poco asustado -- después de todo, puede que mi solución no sea tan buena.

Esto es lo que fue mal en la sitación anterior. A pesar de que tengo un cortafuegos decente en el lugar y de que identifiqué rápidamente la causa del problema en la red, no fui capaz de modificar el funcionamiento de mi cortafuegos para responder al problema a tiempo. Por supuesto, cuando atacan nuestra red, querríamos responder inmediatamente y vernos forzados a alterar la configuración del archivo de comandos de nuestro cortafuegos atemorizados, no solo incrementará nuestro estrés, sino que además será muy poco eficaz.

2.  Macros

ipdrop

Sería mucho mejor si tuviera una macro especial ipdrop que está diseñada con el propósito específico de insertar las reglas necesarias para bloquear las direcciones IP que se le especifiquen. Con dicha macro, bloquear con un cortafuegos no volverá a requerir dos minutos; le tomará cinco segundos como mucho. Dado que la macro me evita la tarea de editar las reglas del cortafuegos a mano, elimina la mayor fuente de problemas. Todo lo que me queda por hacer es determinar la dirección IP que debería bloquear y teclear después:

Listado de Código 2.1: Ignorar una IP

# ipdrop 129.24.8.1 on
IP 129.24.8.1 drop on.

La macro ipdrop bloqueará inmediatamente 129.24.8.1, la dirección IP mala de Roberto por esta semana. Esta macro mejora nuestras defensas sustancialmente, dado que bloquear ahora una IP ni tan siquiera requiere pensar. Veamos ahora la implementación de mi macro ipdrop:

Listado de Código 2.2: macro ipdrop

#!/bin/bash

source /usr/local/share/.sh

args 2 $# "${0} IPADDR {on/off}"

# Drops packets to/from IPADDR. Good for obnoxious
networks/hosts/DoS"

if [ "$2" == "on" ]
then
# Rules will be appended or inserted as normal
 APPEND="-A"
  INSERT="-I"
  rec_check ipdrop $1 "$1 already blocked" on
  record ipdrop $1
elif [ "$2" == "off" ]
then
# Rules will be deleted instead
 APPEND="-D"
  INSERT="-D"
  rec_check ipdrop $1 "$1 not currently blocked" off
  unrecord ipdrop $1
else
  echo "Error: \"off\" or \"on\" expected as second argument"
  exit 1
fi

# Block outside IP address that's causing problems
# Attacker's incoming TCP connections will take a minute or so to time
out, reducing DoS effectiveness

iptables $INSERT INPUT   -s $1 -j DROP
iptables $INSERT OUTPUT  -d $1 -j DROP
iptables $INSERT FORWARD -d $1 -j DROP
iptables $INSERT FORWARD -s $1 -j DROP

echo "IP ${1} drop ${2}."

ipdrop: explicación

Si echamos un vistazo a las cuatro últimas líneas resaltadas, veremos los comandos que insertan las reglas apropiadas en las tablas del cortafuegos. Como puede verse la definición de la variable de entorno $INSERT varía, dependiendo de si lo ejecutamos en el modo "on" u "off". Cuando se ejecuten las líneas de iptables, las reglas correspondientes se insertarán o se eliminarán adecuadamente.

Ahora, veamos la función de las reglas, que deberían funcionar a la perfección con cualquier tipo de cortafuegos, e incluso en un sistema sin cortafuegos; todo lo que se necesita es el soporte iptables integrado en nuestro núcleo 2.4. Bloqueamos los paquetes entrantes desde la dirección IP que causa los problemas (la primera línea iptables), bloqueamos los paquetes salientes a dicha dirección IP (la siguiente línea iptables) y después evitamos las redirecciones en cada dirección para dicha IP (las últimas dos líneas iptables). Una vez se apliquen dichas reglas, nuestro sistema descartará cualquier paquete proveniente que caiga en una de esas categorías.

Otro apunte rápido: hacemos llamadas a "rec_check", "unrecord", "record", y "args". Son funciones de ayuda especiales en bash definidas en dynfw.sh . La función "record" graba la ip bloqueada en el archivo /root/.dynfw-ipdrop, mientras que "unrecord" lo elimina de /root/.dynfw-ipdrop. La función "rec_check" se usa para abortar la macro con un mensaje de error si se intenta bloquear de nuevo una dirección IP ya bloqueada, o quitar el bloqueo a una dirección IP que no está bloqueada. La función "args" se asegura de que recibimos la cifra correcta de argumentos y también muestra una información de gran ayuda. He creado el archivo dynfw-1.0.tar.gz que contiene todas estas herramientas; ver la sección de Recursos al final de este artículo para obtener más información.

tcplimit

La siguiente macro de cortafuegos dinámica es útil si se necesita limitar el uso de un servicio de red basado en TCP, algo que posiblemente sobrecargue la CPU en el servidor. Se llama "tcplimit", esta macro coge un puerto TCP, una tasa, una escala y "on" u "off" como argumento:

Listado de Código 2.3: Limitar el uso de un servicio particular basado en TCP

# tcplimit 873 5 minute on
Port 873 new connection limit (5/minute, burst=5) on.

tcplimit usa el nuevo módulo de iptables "state" (hay que asegurarse de haberlo habilitado en el núcleo o de haber cargado el módulo) para permitir solo un cierto número de conexiones entrantes en un determinado periodo de tiempo. En este ejemplo, el cortafuegos únicamente permitirá cinco conexiones por minuto a mi servidor rsync (puerto 873) -- y es posible especificar el número de conexiones que se deseen por segundo/minuto/hora o día, tal y como se necesite.

tcplimit ofrece una buena forma de limitar servicios que no sean esenciales -- para que la inundación de tráfico en un servicio no esencial no estropee nuestra red o el servidor. En mi caso, uso tcplimit para establecer el límite superior de uso de rsync para prevenir que mi línea DSL se vea saturada por excesivas conexiones rsync. Los servicios cuya conexión se ha visto limitada se almacenan en /root/.dynfw-tcplimit y si alguna vez quiero inhabilitar el nuevo límite de conexiones, sencillamente puedo teclear:

Listado de Código 2.4: Inhabilitar la limitación de conexiones

# tcplimit 873 5 minute off
Port 873 new connection limit off.

tcplimit funciona creando una cadena completamente nueva en la tabla "filter". Esta nueva cadena rechazará todos los paquetes que excedan el límite especificado. Entonces, se inserta una única regla en la cadena de entrada (INPUT) que redirige todos los paquetes de conexión nuevos (NEW) dirigidos al puerto de destino (873 en este caso) a esta cadena especial, limitando efectivamente las nuevas conexiones de entrada, sin afectar a los paquetes que forman parte de una conexión ya establecida.

Cuando tcplimit deja de funcionar, la regla INPUT y la cadena especial son eliminadas. Este es el tipo de cosas que realmente hacen considerar la importancia de tener una macro que maneje, después de haberla comprobado concienzudamente, las reglas de nuestro cortafuegos por nosotros. Así como con ipblock, la macro tcplimit debe ser compatible con cualquier tipo de cortafuegos, e incluso con ningún cortafuegos, siempre que se tenga la funcionalidad necesaria de iptables habiltada en el núcleo.

host-tcplimit

host-tcplimit es muy parecido a tcplimit, pero limita las nuevas conexiones IP provenientes de una dirección IP concreta dirigidas a un puerto TCP en concreto de nuestro servidor. host-tcplimit es muy útil para limitar el abuso de una única persona de los recursos de nuestra red. Por ejemplo, digamos que tenemos un servidor CVS y descubrimos que un nuevo desarrollador parece estar usando una macro que actualiza su código fuente con respecto al repositorio cada 10 minutos, usando una gran cantidad de recursos de la red innecesariamente a lo largo del día. De todas formas, mientras intentamos redactar un mensaje explicándole lo erróneo de su forma de proceder, recibimos el siguiente mensaje:

Listado de Código 2.5: Mensaje recibido

¡Hola chicos!

Me alegra formar parte de vuestro proyecto en desarrollo. He configurado una
macro para que actualice mi copia local del código cada diez minutos. Voy a
estar fuera durante dos semanas porque me marcho de viaje, pero cuando vuelva
tendré todo el código fuente actualizado y ¡estaré listo para ayudar! Salgo por
la puerta en este preciso instante... ¡Nos vemos en dos semanas!


Sinceramente,

Sr. Novato

En dichas situaciones, un sencillo comando host-tcplimit resolverá el problema:

Listado de Código 2.6: Comando host-tcplimit

# host-tcplimit 1.1.1.1 2401 1 day on

Ahora, el Sr. Novato (dirección IP 1.1.1.1) ha sido limitado a una conexión CVS por día (puerto 2401), evitando el desperdicio de un gran ancho de banda en la red.

user-outblock

La última y posiblemente la más intrigante de todas mis macros de cortafuegos dinámicas es user-outblock. Esta macro proporciona una forma ideal de permitir a un usuario en particular hacer telnet o ssh en nuestro sistema, pero sin permitir a este usuario realizar ninguna nueva conexión saliente desde la línea de comandos. He aquí una situación en la que user-outblock resultaría muy práctico. Digamos que una familia en concreto tiene una cuenta en mi ISP. Mamá y papá usan un cliente gráfico de correo electrónico para leer su correo y para navegar por la red de vez en cuando, pero su hijo aspira a ser un genio de la informática, y usa generalmente su acceso al intérprete de comandos para hacer cosas malas en las computadoras de otras personas.

Un día, nos topamos con que ha establecido conexiones ssh con varios sistemas que aparentemente pertenecen al ejército pakistaní -- oh. Nos gustaría emplear a este joven en actividades más benéficas, por lo que hacemos lo siguiente:

Primero, hacemos una revisión de nuestro sistema y nos aseguramos de quitar el bit suid de todos los binarios de red, como ssh:

Listado de Código 2.7: Eliminar el bit suid de todos los binarios de red

# chmod u-s /usr/bin/ssh

Ahora, todos los procesos que intente usar para interactuar con la red tendrán como propietario su UID. Ahora podremos usar user-outblock para bloquear todo el tráfico de salida TCP iniciado por dicho UID (que además es el 2049):

Listado de Código 2.8: Bloquear todas las conexiones de salida TCP de un UID

# user-outblock 2049 on
UID 2049 block on.

Ahora, puede ingresar y leer su correo, pero no podrá usar nuestro servidor para establecer conexiones ssh ni cosas similares. Ahora podría instalar un cliente ssh en su PC doméstico. De todos modos, no sería demasiado complicado elaborar otra macro de cortafuegos dinámico que limitase su PC doméstico a la web, correo y las conexiones salientes ssh (en nuestro servidor únicamente).

3.  Recursos

Tarballs

Dado que he encontrado estas macros dinámicas de cortafuegos muy útiles, las he incluido todas en un pequeño tarball (dynfw-1.0.1.tar.bz2) que se puede descargar e instalar en nuestra máquina.

Para instalarlas, extraemos el tarball y ejecutamos la macro que se incluye install.sh. Esta macro instalará una macro compartida bash en /usr/local/share/dynfw.sh, e instalará todas las macros dinámicas del cortafuegos en /usr/local/sbin. Si se desea tenerlos en /usr/share y /usr/sbin en su lugar, sencillamente tecleamos esto antes de ejecutar install.sh:

Listado de Código 3.1: Exportar la localización del directorio de instalación

# export PREFIX=/usr

He añadido también la página en Gentoo Linux macros dinámicas de cortafuegos (en inglés) que se puede visitar para obtener la última versión del tarball. Me gustaría continuar mejorando y añadiendo nuevas cosas a la colección, alcanzando la meta de hacer realidad un recurso verdaderamente útil para todos los administradores de sistemas a lo largo del mundo. Ahora que disponemos de iptables en el núcleo es el momento de sacarle partido.

Si todo este material acerca del cortafuegos iptables es nuevo para nosotros, recomiendo encarecidamente el 2.4 stateful firewall tutorial (es necesario registrarse), que contiene instrucciones completas acerca de cómo elaborar nuestro cortafuegos con seguimiento de estado basado en iptables.

tcpdump es una herramienta esencial de bajo nivel para explorar los intercambios de paquetes y para verificar que nuestro cortafuegos está funcionando correctamente. Si no disponemos de la misma, hay que obtenerla. Si disponemos de la misma, hemos de empezar a usarla. Si ya se está usando, ¡excelente! :)

Visitar la página del equipo netfilter para encontrar muchos recursos excelentes, incluyendo el código fuente de iptables, y las excelentes guías no fiables de Rusty (traducidas al español siguiendo el enlace). Incluyen una guía de conceptos básicos de red, una de filtrado de paquetes, una acerca de NAT y el netfilter hacking HOWTO (no dispone de traducción al español) para los desarrolladores. También hay un PUF netfilter disponible, así como algunas otras cosas.

Afortunadamente, hay muchos recursos de netfilter en línea; pero, de todos modos, no hay que olvidar los más básicos. La página del manual de iptables es muy detallada y es un ejemplo brillante de lo que cualquier página de manual debería ser.

Tenemos el Advanced Linux Routing and Traffic Control HOWTO. Disponible en español en formato PDF Enrutamiento avanzado y control de tráfico en Linux, que dispone de una sección que muestra cómo usar iptables para marcar paquetes, para después usar la funcionalidad de Linux para encaminar dichos paquetes basándose en estas marcas.

Hay una lista de correo netfilter (iptables) disponible, así como una para los desarrolladores netfilter. Se puede acceder a sus archivos en esos mismos enlaces.



Imprimir

Página actualizada 9 de octubre, 2005

Sumario: Los cortafuegos son buenos y divertidos, pero ¿qué podemos hacer cuando se necesitan cambios rápidos y complejos en las reglas de nuestro cortafuegos? Fácil, usar las macros de Daniel Robbins para crear cortafuegos dinámicos que se muestran en este artículo. Se pueden usar dichas macros para incrementar la seguridad y el rendimiento de nuestro tráfico de red y para inspirar nuestros propios diseños creativos.

Daniel Robbins
Autor

LinuxBlues
Traductor

Donate to support our development efforts.

Copyright 2001-2014 Gentoo Foundation, Inc. Questions, Comments? Contact us.