Seguridad en Unix y Redes
Libro en Formato HTML y PDF de seguridad informática realizado por Antonio Villalon Huerta

Los contenidos pueden estar desactualizados con respecto al original

Este documento se encuentra disponible también en formato PDF

Cortafuegos: Casos de estudio

next up previous contents
Siguiente: Ataques remotos Subir: Seguridad de la subred Anterior: Cortafuegos: Conceptos teóricos   Índice General

Subsecciones

Cortafuegos: Casos de estudio

Firewall-1

Introducción

Quizás el cortafuegos más utilizado actualmente en Internet es FireWall-1, desarrollado por la empresa israelí Check Point Software Technologies Ltd. (http://www.checkpoint.com/). Este firewall se ejecuta sobre diferentes sistemas Unix (Solaris, AIX, Linux y HP-UX), así como sobre Windows NT y también en `cajas negras' como las desarrolladas por Nokia, que poseen un sistema operativo propio (IPSO) basado en FreeBSD.

Quizás la característica más importante de Firewall-1 sea que incorpora una nueva arquitectura dentro del mundo de los cortafuegos: la inspección con estado (stateful inspection). Firewall-1 inserta un módulo denominado Inspection Module en el núcleo del sistema operativo sobre el que se instala, en el nivel software más bajo posible (por debajo incluso del nivel de red), tal y como se muestra en la figura 16.1; así, desde ese nivel tan bajo, Firewall-1 puede interceptar y analizar todos los paquetes antes de que lleguen al resto del sistema: se garantiza que ningún paquete es procesado por ninguno de los protocolos superiores hasta que Firewall-1 comprueba que no viola la política de seguridad definida en el cortafuegos.
Figura 16.1: Ubicación del Inspection Module dentro de la pila de protocolos OSI.
Image fw1

Firewall-1 es capaz de analizar la información de una trama en cada uno de los siete niveles OSI y a la vez analizar información de estado registrada de anteriores comunicaciones; el cortafuegos entiende la estructura de los diferentes protocolos TCP/IP - incluso de los ubicados en la capa de aplicación -, de forma que el Inspection Module extrae la información relevante de cada paquete para construir tablas dinámicas que se actualizan constantemente, tablas que el firewall utiliza para analizar comunicaciones posteriores. En el módulo de inspección se implantan las políticas de seguridad definidas en cada organización mediante un sencillo lenguaje denominado INSPECT, también diseñado por Check Point Software Technologies; desde un cómodo interfaz se genera un script en este lenguaje, que se compila y se inserta en el Inspection Module.

La gran potencia y flexibilidad de Firewall-1 hacen imposible que se aquí se puedan explicar con el suficiente nivel de detalle todas sus características; para más información, excelentes lecturas pueden ser [GB99] o (más reciente) [WA02]. También la documentación que acompaña al producto, y la disponible en el servidor web de Check Point Software Technologies, es de gran ayuda para cualquier administrador que utilice este cortafuegos en su red.

Arquitectura

Firewall-1 está basado en dos módulos independientes: el de gestión (o control) y el de cortafuegos. El primero de ellos está formado por el gestor gráfico de políticas (incluyendo el visor de registros) y el servidor de gestión, típicamente un demonio (fwm) que se ejecuta en una máquina Unix. El gestor gráfico puede ser un cliente Unix (con X/Motif) o Windows 9x/NT; es triste que a estas alturas no exista un cliente gráfico para Linux, encontrándose únicamente para otros Unices, y que además el cliente X/Motif contenga errores y sea bastante ineficiente, lo que motiva que se tienda a utilizar clientes Windows para gestionar los cortafuegos. En cualquier caso, el gestor gráfico puede ejecutarse en la misma máquina que el servidor de gestión o en una diferente, mediante un esquema cliente/servidor. Este gestor no hace más que presentar de una forma cómoda al administrador del cortafuegos la información generada por el servidor de gestión (el demonio fwm), que es el verdadero `corazón' de la gestión del firewall y que permite administrar diferentes sistemas con módulo de cortafuegos (en castellano plano, diferentes cortafuegos) desde una misma estación de control.

Por otra parte, el módulo de cortafuegos está formado por el inspection module, los demonios de Firewall-1 y los servidores de seguridad del firewall. El inspection module se instala como ya hemos comentado (figura 16.1) entre el nivel de enlace y el nivel de red, por completo antes de la pila de protocolos TCP/IP, con lo que se asegura que Firewall-1 analiza todos y cada uno de los paquetes que pasan por el sistema. Los demonios del firewall son simples programas con diferentes funciones, como la comunicación con el servidor de gestión o la carga de las reglas definidas para el cortafuegos en el inspection module. Finalmente, los servidores de seguridad son módulos que se invocan cuando así se define en la política (por ejemplo, cuando la acción asociada a una determinada regla es User Authentication), y que realizan tareas de autenticación y seguridad de contenidos; la conexión entre origen y destino se divide en dos, una entre el origen y el servidor de seguridad y otra entre este y el destino.

Instalación

Antes de instalar Firewall-1 en un sistema Unix es muy importante deshabilitar en el núcleo del operativo el IP Forwarding, de forma que todo el reenvío de tramas sea gestionado por el software de cortafuegos (esta opción se define durante la instalación). Esto permite que el reenvío sólo sea posible si el firewall está ejecutándose - es decir, protegiendo nuestra red -, lo que imposibilita que la máquina reenvíe paquetes si Firewall-1 no está activo, algo que como vimos a la hora de hablar de diferentes clones de Unix puede ser problemático para nuestra seguridad.

Teniendo en cuenta la consideración anterior, y asumiendo que en la máquina donde vamos a instalar Firewall-1 no existen problemas ajenos al cortafuegos (conectividad, resolución de nombres, reconocimiento de interfaces de red...), la instalación del software no ofrece ninguna dificultad: simplemente hemos de instalar los paquetes correspondientes con las órdenes habituales de cada Unix (pkgadd en Solaris, swinstall en HP-UX...) o, en algunas versiones del programa, ejecutar la orden fwinstall, que no es más que una instalación seguida de una configuración del cortafuegos equivalente a la que veremos a continuación.

Una vez instalado el firewall hemos de configurarlo; para ello no tenemos más que ejecutar la orden fwconfig (versión 4.0) o cpconfig (versión 4.1), que paso a paso nos guiará a través de la configuración (o reconfiguración, una vez el cortafuegos esté ya funcionando) de Firewall-1:
anita:/# fwconfig

Welcome to VPN-1 & FireWall-1 Configuration Program
=================================================
This program will let you re-configure
your VPN-1 & FireWall-1 configuration.


Configuration Options:
----------------------
(1)  Licenses
(2)  Administrators
(3)  GUI clients
(4)  Remote Modules
(5)  SMTP Server
(6)  SNMP Extension
(7)  Groups
(8)  IP Forwarding
(9)  Default Filter
(10) CA Keys

(11) Exit

Enter your choice (1-11) : 11

Thank You...
anita:/#
Como podemos ver, esta herramienta permite realizar tareas como la instalación de licencias, la planificación del software en el arranque de la máquina o la definición de módulos de firewall remotos. Aunque todo es vital para el correcto funcionamiento del cortafuegos, existen dos apartados especialmente importantes para la posterior gestión del firewall: la definición de administradores y la definición de estaciones que actuarán como clientes gráficos; si no definimos al menos un administrador y una estación cliente, no podremos acceder al cortafuegos para gestionarlo (evidentemente, en esta situación no estaría todo perdido, ya que siempre podemos añadir ambos elementos, así como modificar su relación, a posteriori).

El administrador o administradores que definamos serán los encargados de acceder a las políticas del cortafuegos a través del gestor gráfico, únicamente desde las estaciones que hayamos definido como cliente. Podemos añadir elementos a ambas listas (la de administradores y la de estaciones gráficas) ejecutando de nuevo fwconfig o cpconfig, o bien de forma más directa ejecutando la orden fwm (para añadir administradores) y modificando el archivo $FWDIR/conf/gui-clients (para añadir clientes gráficos); este archivo no es más que un fichero de texto donde se listan las direcciones IP (o los nombres DNS) de las máquinas que pueden acceder a gestionar el firewall:
anita:/# cat $FWDIR/conf/gui-clients
192.168.0.1
192.168.0.2
192.168.0.3
158.42.22.41
anita:/# fwm -p
FireWall-1 Remote Manager Users:
================================
toni (Read/Write)
avh (Read/Write)

Total of 2 users
anita:/# fwm -a admin -wr
Password:
Verify Password:
User admin added succesfully
anita:/# fwm -p
FireWall-1 Remote Manager Users:
================================
toni (Read/Write)
avh (Read/Write)
admin (Read Only)

Total of 3 users
anita:/# fwm -r prova
User prova removed succesfully
anita:/#
Para acabar con la instalación de Firewall-1 es necesario definir la variable de entorno $FWDIR, que apuntará al directorio /etc/fw/, y añadirla en los scripts de inicio de sesión correspondientes. También es recomendable añadir el directorio $FWDIR/bin/ a nuestro $PATH, ya que ahí se ubican las utilidades de gestión del cortafuegos, y hacer lo mismo con $FWDIR/man/ y la variable $MANPATH, ya que en este directorio se encuentran las páginas de manual del firewall.

Antes de finalizar este punto quizás es necesaria una pequeña advertencia: como Firewall-1 inserta módulos en el núcleo del operativo, es dependiente de la versión del kernel utilizada. Todas las versiones más o menos modernas funcionan correctamente sobre Solaris 2.6 y la última también sobre Solaris 7; no obstante, sobre este último el resto de versiones no funcionan bien, aunque se instalen correctamente. Es posible, y esto lo digo por experiencia, que la máquina no arranque tras instalar el software debido a las modificaciones de los scripts de arranque (concretamente los ubicados en /etc/rcS.d/), que al ser invocados desde /sbin/rcS producen errores que impiden montar correctamente los discos y proseguir el arranque; para solucionar estos problemas, lo más rápido es eliminar cualquier modificación que la instalación de Firewall-1 haya realizado sobre los programas ejecutados al iniciar el sistema.

Gestión

Como cualquier sistema cortafuegos, Firewall-1 permite al usuario definir una política de seguridad formada por reglas, cada una de las cuales se basa principalmente en el origen, destino y servicio de una determinada trama. El conjunto de reglas se examina de arriba hacia abajo, de forma que si una determinada regla hace match con el paquete que se está inspeccionando, se aplica y las que quedan por debajo de ella ni siquiera se examinan; como debería suceder en cualquier sistema cortafuegos, las tramas no explícitamente aceptadas se rechazan.

La gestión de Firewall-1 suele ser completamente gráfica, a través de dos interfaces principales: el de gestión de políticas (fwui) y el visor de logs (fwlv, mostrado en la figura 16.2). En versiones más recientes del firewall ambos se unifican en fwpolicy, basado en X/Motif (los anteriores se basan en OpenLook), más cómodo e intuitivo que sus predecesores. En cualquier caso, siempre tenemos la opción de trabajar en modo texto mediante la orden fw, aunque esta opción no suele ser la habitual entre los administradores de Firewall-1.

Para gestionar el cortafuegos, cada uno de los administradores definidos anteriormente puede conectar desde las estaciones gráficas autorizadas al servidor de gestión (máquina en la que se ha instalado el módulo de gestión de Firewall-1), para lo cual necesita autenticarse mediante su nombre de usuario y su clave; una vez conectado, si su acceso es de lectura y escritura, puede comenzar a trabajar con el cortafuegos. Lo primero que verá será la política del firewall (de hecho, ha conectado con el editor de políticas de Firewall-1); estas políticas no son más que ficheros ubicados en $FWDIR/conf/, con un nombre finalizado en `.W', que se compilan y cargan en los sistemas donde está instalado el módulo de cortafuegos.

Desde el editor gráfico, las políticas se ven como un conjunto de reglas que se examina de arriba a abajo hasta que una de ellas hace match con el paquete que se está analizando (como ya hemos comentado, si ninguna de ellas hace match, el paquete se deniega). Cada una de estas reglas está numerada en función del orden de aplicación, y sus campos principales son los habituales en cualquier cortafuegos: origen, destino, servicio y acción. Además, existen un campo que indica si se ha de registrar la trama (`Track'), otro para determinar dónde se ha de instalar (`Install On'), otro para especificar el tiempo que la regla estará activa (`Time') y finalmente un campo de texto donde se pueden incluir comentarios.

Evidentemente, como sucede en cualquier firewall, tanto el campo origen como el destino pueden ser sistemas concretos o redes completas. En Firewall-1 ambos elementos, así como los servicios, se manejan como objetos: elementos definidos por el administrador e identificados mediante un nombre - en principio algo fácilmente identificable por el mismo -, con una serie de propiedades determinadas. Sin duda, en el caso de los hosts o las redes la propiedad más importante es la dirección IP o la dirección de red con su máscara correspondiente asociadas al objeto; en el caso de los servicios, definidos también por un nombre, la característica más importante es el puerto o rango de puertos asociado al mismo. Por ejemplo, podemos definir el objeto `servidor1', con su IP correspondiente, el objeto DMZ, con su dirección de red y máscara asociada, o el objeto ssh, con su puerto concreto; en todos los casos, el nombre dice mucho más al encargado de gestionar el cortafuegos que una simple IP, dirección de red o número de puerto, lo que facilita enormemente la administración del firewall.

El campo `Action' de cada regla define qué se ha de hacer con una conexión cuando hace match con la regla; al igual que en la mayor parte de cortafuegos del mercado, tres son las acciones principales a tomar: `Accept', si dejamos que la conexión se establezca a través del firewall, `Reject', si la rechazamos, y `Drop', si la rechazamos sin notificarlo al origen. Para las conexiones que no permitimos, esta última suele ser la mejor opción, ya que el paquete se elimina sin ningún tipo de notificación hacia el origen; si utilizáramos `Reject' sí que informaríamos de las conexiones no permitidas, lo que puede ayudar a un atacante a conocer tanto nuestra política de seguridad como la topología de nuestra red.

Por su parte, el campo `Track' de una regla determina una medida a tomar cuando un paquete hace match con la regla en cuestión: ninguna medida (campo vacío), un registro en diferentes formatos (`Short Log', `Long Log' y `Accounting'), una alerta de seguridad, un correo electrónico, un trap SNMP o una acción definida por el usuario (estas cuatro últimas acciones han de ser configuradas por el administrador del cortafuegos). Evidentemente, este campo es muy útil para obtener información acerca de posibles hechos que traten de comprometer nuestra seguridad, tanto en un log habitual como para implantar en el firewall un sistema de detección de intrusos y respuesta automática en tiempo real ([Spi01a]); en el punto 16.1.5 hablaremos con más detalle del sistema de log de Firewall-1.

Una vez que hemos definido una política - un conjunto de reglas - lo más habitual es aplicarla en un sistema con el módulo de cortafuegos de Firewall-1 instalado en él; hemos de recordar que habitualmente trabajamos con un simple editor de políticas, de forma que las modificaciones que realicemos sobre una determinada política (añadir o eliminar reglas, definir nuevos objetos, etc.) no tendrán ningún efecto hasta que esa política se instale en el cortafuegos correspondiente. Para instalar una política no tenemos más que escoger la opción del menú del gestor gráfico adecuada; a partir de ese momento, Firewall-1 verifica que la política escogida es lógica y consistente, genera y compila el código INSPECT (en el punto 16.1.6 hablamos mínimamente de este lenguaje) correspondiente para cada objeto sobre el que vayamos a instalarla, y carga dicho código en el objeto donde se encuentra el módulo de cortafuegos a través de un canal seguro.
Figura 16.2: Una imagen de fwlv.
Image fwlv


El sistema de log

Cuando una regla tiene definido en el campo Track que guarde un log, siempre que una trama haga match con la misma se generará un registro del evento, tanto si la conexión se acepta como si se deniega. A diferencia de la mayor parte del software de un sistema Unix, los logs de Firewall-1 no son simples ficheros ASCII, sino que se almacenan en un formato propio dentro del directorio $FWDIR/logs/. Para consultarlos hemos de utilizar o bien el visor gráfico fwlv (figura 16.2) o bien la orden fw, que también permite rotarlos (`fw logswitch') y exportarlos a ficheros ASCII (`fw logexport'):
anita:/etc/fw/bin# ./fw log
Date: May 2, 2000
 3:28:43 ctl    anita      >daemon started sending log to localhost
 3:49:27 ctl    anita      >daemon started sending log to localhost
 4:30:30 ctl    anita      >daemon started sending log to localhost
anita:/etc/fw/bin# ./fw logexport -o /etc/fw/logs/salida.ascii
Starting pass 1 of the log file.
Starting pass 2 of the log file..
   100.00% of log file processed.

anita:/etc/fw/bin# cat /etc/fw/logs/salida.ascii
num;date;time;orig;type;action;alert;i/f_name;i/f_dir;sys_msgs
0;2May2000; 3:28:43;anita;control;ctl;;daemon;inbound;started sending log
to localhost
1;2May2000; 3:49:27;anita;control;ctl;;daemon;inbound;started sending log
to localhost
2;2May2000; 4:30:30;anita;control;ctl;;daemon;inbound;started sending log
to localhost

anita:/etc/fw/bin#
Evidentemente, rotar los logs o exportarlos a ficheros ASCII nos puede resultar muy útil a la hora de realizar estadísticas o tareas similares, ya que podemos separar los registros por días, meses, horas...o cualquier otro parámetro que se nos ocurra y utilizar las herramientas propias de cualquier Unix (awk, perl, grep...) sobre el fichero de texto para extraer el tipo de registros que nos interese; no obstante, esto a todas luces presenta un grave inconveniente: los registros de Firewall-1, con lo que hemos visto hasta ahora, no pueden utilizarse para monitorizar el tráfico en tiempo real o para ofrecer una respuesta automática ante un ataque. Por supuesto, la detección de un ataque offline, sobre un fichero de registro histórico (por ejemplo, podemos buscar tráfico sospechoso cada noche sobre el log del día anterior) es muy importante, pero sin duda lo es más el que seamos capaces de detectar ese mismo ataque justo cuando se está produciendo, para ofrecer así una respuesta inmediata y minimizar el riesgo asociado a las actividades de un pirata; cuanto más tardemos, más posibilidades tiene el atacante de tener éxito en su tarea ([Coh99]).

Para implantar un sistema de respuesta automática en tiempo real, o simplemente para visualizar los registros generados por el cortafuegos también en tiempo real podemos utilizar la orden `fw log', que con las opciones adecuadas imprimirá en pantalla cualquier registro que se genere al mismo tiempo que la entrada se guarda en el fichero de log correspondiente con el formato propio de Firewall-1:
anita:/# fw log -f -n |head -3
2:21:12 drop   anita   >nei0 proto tcp src 192.168.0.3 dst 158.42.22.41 \
service finger s_port 13000 len 40 rule 5 
2:22:23 drop   anita   >nei0 proto tcp src 192.168.0.10  dst 158.42.2.1 \
service NetBus s_port 32344 len 40 rule 6 
2:22:45 drop   anita   >nei0 proto tcp src 192.168.0.1  dst 192.168.2.3 \
service echo-tcp s_port 30298 len 40 rule 5
anita:/#
Como vemos, la salida de esta orden ya puede ser procesada desde línea de comandos con las herramientas habituales de Unix para implantar así la respuesta automática, por ejemplo mediante `fw sam', que bloquea todo el tráfico proveniente de una determinada dirección en el cortafuegos, de forma permanente o temporal ([Spi01a]).


INSPECT

Como ya hemos comentado, al instalar una política en un cortafuegos (máquina con el módulo de firewall) desde el servidor de gestión (máquina donde se ha instalado el Management Module) Firewall-1 genera en el mismo servidor de gestión un código - un script, un simple fichero ASCII editable - en un lenguaje de alto nivel propio de Firewall-1: este lenguaje se denomina INSPECT, es orientado a objetos, y está diseñado explícitamente para trabajar con cortafuegos, lo que permite por ejemplo programar las acciones típicas de un firewall: detener una trama, aceptarla, generar un registro...

El script de INSPECT generado a partir de la política editada en el gestor gráfico (o desde línea de comandos, mediante la orden `fw gen') es un fichero `.pf' que se encuentra en $FWDIR/conf/; este archivo es compilado mediante fwc y a partir de él se genera un código (un fichero `.fc') dentro de $FWDIR/tmp/ junto a otros archivos adicionales en el mismo directorio. Como hemos dicho el código generado se transmite al módulo de cortafuegos a través de un canal seguro, y en este módulo los demonios de Firewall-1 son los encargados de cargar el código en el núcleo del operativo, comenzando así a ser operativa la nueva política.

La carga del código en el cortafuegos se realiza de forma automática tras generar y compilar el fichero `.pf' desde el editor gráfico de políticas, aunque puede llevarse a cabo manualmente mediante órdenes como `fw load' o `fw fetch'; este código se ejecuta en una máquina virtual ubicada en el núcleo del operativo, y su ejecución básicamente consiste en inspeccionar todas las tramas que pasan por el firewall para decidir qué hacer con ellas.

Evidentemente es imposible describir aquí de forma exhaustiva tanto la sintaxis como la funcionalidad de INSPECT; para obtener más información acerca de este lenguaje podemos consultar la documentación que acompaña a Firewall-1, en concreto el capítulo 11 del `Architecture and Administration User Guide', que presenta una excelente introducción a INSPECT.

ipfwadm/ipchains/iptables

Introducción

Desde la series 1.1, el kernel de Linux posee en mayor o menor medida capacidad para filtrar tramas. Originalmente (1994), ipfwadm era la herramienta proporcionada con Linux para la implementación de políticas de filtrado de paquetes en este clon de Unix; derivaba del código de filtrado en BSD (ipfw), y debido a sus limitaciones (por ejemplo, sólo puede manejar los protocolos TCP, UDP o ICMP) ipfwadm fue reescrito para convertirse en ipchains a partir del núcleo 2.1.102 (en 1998). Esta nueva herramienta (realmente, todo el subsistema de filtrado de los núcleos 2.2) introdujo bastantes mejoras con respecto a la anterior, pero seguía careciendo de algo fundamental: el stateful; era difícil ver a un sistema tan potente como Linux sin una herramienta de firewalling decente, libre, y `de serie' con el sistema, mientras otros clones de Unix, también gratuitos hacía tiempo que la incorporaban, como es el caso de FreeBSD e IPFilter.

De esta forma, no es de extrañar que a partir del núcleo 2.3.15 (por tanto, en todos los kernels estables, de la serie 2.4, desde mediados de 1999) ipchains fuera sustituido por iptables, que de nuevo introducía importantes mejoras con respecto a su predecesor. Sin duda la más importante era que ya incorporaba el stateful no presente en ipchains, pero no era la única; además, iptables ofrecía - y de hecho, ofrece - un sistema de NAT (Network Address Translation) mucho más avanzado, incorpora mejoras en el filtrado (llegando incluso a filtrar en base a la dirección física de las tramas) e inspección de paquetes, y presenta un subsistema de log mucho más depurado que ipchains. Por tanto,iptables es en la actualidad el software de firewalling en Linux IPv4; aunque todas las versiones de Linux lo incorporan por defecto, se puede descargar una versión actualizada desde http://netfilter.samba.org/.

Históricamente, todos los sistemas de firewalling nativos de Linux han sido orientados a comando: esto significa, muy por encima, que no leen su configuración de un determinado fichero, por ejemplo durante el arranque de la máquina, sino que ese archivo de arranque ha de ser un script donde, línea a línea, se definan los comandos a ejecutar para implantar la política de seguridad deseada; esta es una importante diferencia con respecto a otros cortafuegos, como IPFilter (del que hablaremos a continuación), orientados a archivo: en estos la política se define en un simple fichero ASCII con una cierta sintaxis, que el software interpreta y carga en el sistema.

La sintaxis de iptables (o la de ipchains, bastante similar) puede llegar a resultar muy compleja si se invoca al sistema de filtrado desde línea de órdenes; por fortuna (o no por fortuna), existen diferentes interfaces para el administrador, algunos tan cómodos e intuitivos como el de Firewall-1, capaces de presentar las políticas de una forma gráfica basada en objetos y de transformar después esas políticas en scripts con las órdenes de iptables o ipchains equivalentes. Un ejemplo de estos interfaces es fwbuilder, disponible libremente desde http://www.fwbuilder.org/.

Para conocer mejor todo el subsistema de filtrado en Linux, así como sus herramientas de gestión, consultas imprescindibles son los HowTo [Rus00], [Rus02] y [Gre00]; la mayor parte de esta sección está basada en estas obras. Otros documentos que pueden resultar especialmente interesantes son [Mou00] y [Zie01].

iptables o ipchains son herramientas flexibles, potentes e, igual de importante, gratuitas, que funcionan sobre un sistema operativo también gratuito; quizás para una organización de I+D o para una empresa no muy grande sea difícil permitirse soluciones comerciales cuyo precio puede ascender a varios millones de pesetas, especialmente si se van a instalar cortafuegos internos o arquitecturas DMZ de varios niveles. Sin embargo, no hay excusa para no utilizar este software de filtrado: un pequeño PC corriendo Linux es más que suficiente para, en muchas ocasiones, garantizar - o al menos incrementar - la seguridad de un laboratorio, un aula informática o un conjunto de despachos.

Arquitectura

En Linux el filtrado de paquetes está construido en el kernel (se habla con más detalle del núcleo de este sistema operativo en la sección 10.6); en la serie 2.2, para poder utilizar ipchains hemos de compilar el núcleo con las opciones CONFIG/SMALL>_FIREWALL y CONFIG/SMALL>_IP/SMALL>_FIREWALL activadas, mientras que en las 2.4, para iptables, hemos de activar CONFIG/SMALL>_NETFILTER: es toda la `instalación' (aparte de las herramientas de gestión de espacio de usuario, que vienen de serie con Linux) que nuestro firewall va a necesitar, de ahí que en este caso no dediquemos una subsección específica a la instalación del cortafuegos.

Cuando ya estamos ejecutando un núcleo con el firewalling activado utilizaremos las herramientas de espacio de usuario ipchains e iptables para insertar y eliminar reglas de filtrado en él; al tratarse de información dinámica, cada vez que el sistema se reinicie las reglas establecidas se perderán, por lo que es recomendable crear un script que se ejecute al arrancar el sistema y que las vuelva a definir. Para ello nos pueden resultar útiles un par de shellscripts que acompañan a las herramientas de espacio de usuario: se trata de ipchains-save e ipchains-restore (núcleos 2.2) y de iptables-save e iptables-restore (núcleos 2.4); en ambos casos, la primera orden vuelca en pantalla las reglas definidas en el núcleo y la segunda carga dichas reglas desde un archivo.

El núcleo de Linux agrupa las diferentes reglas definidas por el administrador en tres listas denominadas chains: input, output y forward (en mayúsculas para los kernels 2.4); en función de las características de una trama, Linux aplica las reglas definidas en cada una de estas listas para decidir qué hacer con el paquete. En primer lugar, al recibir una trama utiliza las reglas de la chain input (su nombre es autoexplicativo) para decidir si la acepta o no; si las reglas definidas en esta lista indican que se ha de aceptar el paquete, se comprueba a dónde ha de enrutarlo, y en el caso de que el destino sea una máquina diferente al cortafuegos se aplican las reglas de la lista forward para reenviarlo a su destino. Finalmente, la lista output se utiliza obviamente antes de enviar un paquete por un interfaz de red, para decidir si el tráfico de salida se permite o se deniega.

Como hemos dicho, los elementos de cada lista se denominan reglas y definen - junto a los targets, de los que hablaremos a continuación - qué hacer con los paquetes que cumplen ciertas características; si un paquete no cumple ninguna de las reglas de la lista que le corresponde, lo mejor si queremos un sistema seguro es rechazarlo o denegarlo, para lo cual podemos definir un tratamiento por defecto. Mediante ipchains e iptables podemos crear listas, modificarlas y eliminarlas17.1 y, lo realmente importante, definir las reglas para cada lista; para estudiar las opciones de ambas órdenes se pueden consultar las páginas ipchains(8), ipfw(4), ipchains-restore(8), ipchains-save(8) e iptables(8).

Cuando un paquete cumple cumple una determinada regla de una chain definimos qué hacer con él mediante lo que se denomina `objetivo' o target (quizás una traducción menos literal pero más clarificadora sería `acción'). Aunque existen más targets, son tres los que más se suelen utilizar: ACCEPT permite el paso de un paquete, DENY lo bloquea, y REJECT también lo bloquea pero a diferencia del anterior envía al origen una notificación mediante un mensaje ICMP de tipo DEST/SMALL>_UNREACH (siempre que el paquete bloqueado no sea también de tipo ICMP). Realmente, aunque REJECT y DENY nos parezcan igual de seguros - y de hecho en la mayoría de situaciones lo sean - siempre es más recomendable utilizar DENY, ya que mediante mensajes ICMP un posible atacante podría conseguir información sobre nuestro entorno que en ciertos casos puede comprometer nuestra seguridad, tal y como hemos comentado cuando hablábamos de Firewall-1.

Gestión

Vamos a ver un ejemplo de definición de una política de seguridad básica utilizando tanto iptables como ipchains; por cuestiones de simplicidad nos centraremos exclusivamente en el filtrado de paquetes, no en otros aspectos como la redirección de puertos o el NAT.

Lo primero que posiblemente nos interese antes de comenzar a definir reglas de filtrado sea `vaciar' las chains, es decir, eliminar todas las reglas asociadas a cada lista, de forma que no interfieran con las que vamos a comenzar a definir; para ello podemos utilizar la opción `-F' tanto de iptables como de ipchains (recordemos que en el primer caso, los nombres de las chains son los mismos, pero en mayúsculas). Además, podemos definir una política por defecto mediante la opción `-P' de ambas herramientas; esta política será la que se aplicará cuando un paquete no sea contemplado por ninguna de las reglas de una determinada chain:
luisa:~# /sbin/ipchains -P input DENY
luisa:~# /sbin/ipchains -F input
luisa:~# /sbin/ipchains -P output ACCEPT
luisa:~# /sbin/ipchains -F output
luisa:~# /sbin/ipchains -P forward DENY
luisa:~# /sbin/ipchains -F forward
luisa:~#
Como vemos, lo que vamos a hacer por defecto es denegar todo el tráfico que se dirija al cortafuegos, tanto si va dirigido a él como si se ha de reenviar a otro sistema, y permitir todo el tráfico de salida. Como vemos, estas políticas por defecto se pueden definir antes de `limpiar' cada chain, ya que la limpieza sólo afecta a las reglas en sí (y esta acción por defecto no se considera una regla).

Una vez aplicadas las primeras acciones, nos interesará sobre todo, ya que la salida la permitimos por completo (y de las redirecciones de tráfico ya hemos dicho que no vamos a entrar en detalle), definir accesos permitidos a nuestro sistema; por ejemplo, es posible que necesitemos un acceso total al puerto 80 para que todo el mundo pueda maravillarse de esas páginas web que hemos hecho con vi. Si es ese el caso, podemos permitir dicho acceso mediante una regla similar a la siguiente:
luisa:~# /sbin/ipchains -A input -p tcp -j ACCEPT -d 158.42.22.41 80
luisa:~#
Estamos indicando que se añada (`-A') en la chain `input' (tramas de entrada) una regla que permita (`ACCEPT') el tráfico TCP (`-p') cuyo destino (`-d') sea el puerto 80 de la dirección 158.42.22.41 - en principio, la IP de nuestro servidor web -. Con iptables, la sintaxis cambia ligeramente:
luisa:~# /sbin/iptables -A INPUT -p TCP -j ACCEPT -d 158.42.22.41 --dport 80
luisa:~#
Una vez definidas estas reglas, mediante la opción `-L' de ipchains e iptables podemos comprobar que efectivamente se están aplicando (utilizamos también `-n' para que no se haga resolución DNS):
luisa:~# /sbin/ipchains -L -n
Chain input (policy DENY):
target     prot opt     source                destination           ports
ACCEPT     tcp  ------  0.0.0.0/0            158.42.22.41          * ->   80
Chain forward (policy DENY):
Chain output (policy ACCEPT):
luisa:~#
Ahora pensemos que quizás también queremos acceder a nuestro servidor de forma remota, utilizando SSH, pero en este caso no desde cualquier lugar de Internet sino desde una dirección concreta; la regla a añadir a la chain `input' en este caso sería la siguiente:
luisa:~# /sbin/ipchains -A input -p tcp -j ACCEPT -s 158.42.2.1 -d \
> 158.42.22.41 22
luisa:~#
Podemos ver que ahora especificamos la dirección origen (`-s') desde la que vamos a permitir el tráfico (en este ejemplo, 158.42.2.1). Si utilizáramos iptables la sintaxis sería la siguiente:
luisa:~# /sbin/iptables -A INPUT -p TCP -j ACCEPT -s 158.42.2.1 -d \
> 158.42.22.41 --dport 22
luisa:~#
Tal y como hemos definido hasta ahora nuestra política de seguridad, sólo estamos permitiendo conexiones al puerto 80 desde cualquier máquina y al puerto 22 desde la especificada; el resto del tráfico de entrada está siendo denegado gracias a la política por defecto que hemos establecido para la chain input (DENY). Así, tráfico como los mensajes ICMP de vuelta, o las llamadas al servicio ident que realizan ciertos servidores cuando se les solicita una conexión no alcanzarán su destino, lo cual puede repercutir en la funcionalidad de nuestro entorno: simplemente hemos de pensar en una comprobación rutinaria de conectividad vía ping o en el acceso a un servidor FTP externo que sea denegado si no se consigue la identidad del usuario remoto. Para evitar estos problemas, podemos permitir el tráfico de ciertos paquetes ICMP y el acceso al servicio auth (puerto 113):
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type \ 
> destination-unreachable -j ACCEPT
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type source-quench -j ACCEPT
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type time-exceeded -j ACCEPT
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type parameter-problem \
> -j ACCEPT
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type echo-reply -j ACCEPT
luisa:~# /sbin/ipchains -A input -p tcp -j ACCEPT -d 158.42.22.41 113
luisa:~#
Como vemos, hemos ido definiendo las reglas que conforman nuestra política desde línea de comando; ya hemos comentado que toda esta configuración se pierde al detener el sistema, por lo que es necesario crear un script que las vuelva a generar y planificarlo para que se ejecute en el arranque de la máquina. Para ello no tenemos que escribir línea a línea la configuración vista en este punto (mejor, la configuración adecuada a nuestro entorno), o utilizar ipchains-restore o iptables-restore para leer esa configuración de un fichero; si elegimos esta opción, antes de detener al sistema hemos de ejecutar ipchains-save o iptables-save para guardar dicha política en el fichero que posteriormente leeremos. De esta forma, en la parada de la máquina hemos de ejecutar una orden similar a:
luisa:~# /sbin/ipchains-save >/etc/rc.d/policy
Saving `input'.
luisa:~#
Mientras que en el arranque, en nuestro script cargaremos la política guardada al detener la máquina con una orden como:
luisa:~# /sbin/ipchains-restore </etc/rc.d/policy
luisa:~#

El sistema de log

Evidentemente, tanto ipchains como iptables están preparados para generar logs en el sistema: ambos permiten registrar mediante syslogd los paquetes que cumplan cierta regla - por norma general, todos -. Un registro exhaustivo de las acciones que se toman en el núcleo con respecto al filtrado de paquetes no es conveniente: la gran cantidad de información guardada hace imposible detectar actividades sospechosas, y además no es difícil que se produzcan ataques de negación de servicio, ya sea por disco ocupado o por tiempo consumido en generar y guardar registros. Por tanto, lo habitual es almacenar sólamente los paquetes que no sean rutinarios (por ejemplo, intentos de conexión desde direcciones no autorizadas, ciertos paquetes ICMP no habituales...).

En el caso de ipchains el núcleo de Linux, a través de klogd y de syslogd, registra estos eventos con prioridad `info', y al provenir del kernel (no olvidemos que el subsitema de filtrado forma parte del núcleo del operativo), su tipo es obviamente `kernel'. Para que cuando un paquete haga match con una regla se genere un registro hemos de utilizar la opción `-l'; por ejemplo, si deseamos que cada vez que alguien intente hacer un finger contra la máquina el tráfico, aparte de ser denegado, registre un log, ejecutaremos una orden como la siguiente:
luisa:~# /sbin/ipchains -A input -p tcp -j DENY -l -s 0.0.0.0/0 \
> -d 158.42.22.41 79
luisa:~#
Así, si estos registros se almacenan en el fichero /var/adm/fwdata, sus entradas serán de la siguiente forma:
rosita:~# tail -1 /var/adm/fwdata
Apr  3 02:03:13 rosita kernel: Packet log: input DENY eth0 PROTO=6 \
 158.42.2.1:1032 158.42.22.41:79 L=34 S=0x00 I=18 F=0x0000 T=254
rosita:~#
El anterior mensaje nos dice principalmente que un paquete con protocolo 6 (corresponde a TCP en nuestro archivo /etc/protocols) proveniente de la dirección 158.42.2.1 y destinado a nuestro servicio finger ha sido denegado; el resto de la información no la veremos aquí (se puede consultar la documentación del producto para ver el significado concreto de todos y cada uno de los campos registrados).

En el caso de iptables el registro de eventos generado por el subsistema de filtrado es algo diferente al de ipchains, tanto al hablar de su funcionamiento como de su sintaxis. Ahora el log se realiza a través de un target independiente (LOG) que registra las tramas que hacen match con una regla determinada, y la prioridad de registro ya no es `info' sino que se puede indicar en la propia línea de órdenes (por defecto es `warning'). Además, se ha definido una nueva extensión denominada `limit' que permite restringir el número de registros que una regla puede generar por unidad de tiempo, lo cual es evidentemente útil para evitar que alguien ataque con éxito nuestros recursos mediante un flood del log en el subsistema de filtrado.

Volvamos de nuevo al ejemplo anterior, en el que registrábamos los intentos de acceso a nuestro puerto 79 (finger) para tener constancia de cuándo alguien trataba de obtener información de los usuarios de nuestro sistema; en el caso de iptables deberíamos definir una regla como la siguiente:
luisa:~# /sbin/iptables -A INPUT -p TCP -m limit -j LOG --log-prefix \
> "FINGER ATTEMPT:" -d 158.42.22.41 --dport 79
luisa:~#
Lo que indicamos mediante esta orden es que genere un mensaje cada vez que alguien envíe tráfico al puerto 79 de la dirección 158.42.22.41 (esto es, cada vez que alguien haga finger contra la máquina). Podemos observar que ahora definimos el target LOG (opción `-j'), y que además aplicamos la extensión `limit' (parámetro `-m') para limitar el registro y evitar así ciertas negaciones de servicio; cada vez que esta regla genere un log añadirá al principio del mismo la cadena `FINGER ATTEMPT:', lo que nos permite identificar de una forma más clara el mensaje. Podemos fijarnos en que a través de esta regla no estamos ni aceptando ni negando el tráfico, sino sólo registrando su existencia: para detener la trama, hemos de indicarlo explícitamente o bien a través de la acción por defecto que hayamos especificado para la chain INPUT (mediante la opción `-P').

IPFilter

Introducción

IP Filter (http://coombs.anu.edu.au/~avalon/ip-filter.html) es un cortafuegos disponible para muchos clones de Unix (Solaris, IRIX, FreeBSD, NetBSD, HP-UX...); su precio (se trata de un software gratuito) y sus excelentes características técnicas lo han convertido en una solución muy interesante para entornos medios donde otros cortafuegos como Firewall-1 no resultan apropiados por diferentes razones: incluso en Solaris puede ser (>es?) en muchos casos una alternativa más interesante que SunScreen Lite, de la propia Sun Microsystems.

Este cortafuegos permite filtrar el tráfico en función de diferentes campos de la cabecera IP de una trama, como las clases de seguridad, las direcciones origen y destino y el protocolo (obvio) o diferentes bits de estado. Además es posible utilizarlo como redirector de tráfico para configurar proxies transparentes, efectuar NAT e IP Accounting, y ofrece también mecanismos de comunicación con el espacio de usuario; por si todo esto fuera poco, IP Filter es stateful y soporta además IPv6.

No obstante, no todo es positivo; el argumento más utilizado por los detractores de IP Filter no es técnico sino jurídico, pero en cualquier caso vale la pena comentarlo: se trata del tipo de licencia, o de la interpretación de la misma, que hace el autor del software (el australiano Darren Reed), y que aunque distribuye el código fuente de forma gratuita, no permite efectuar modificaciones sobre el mismo. Aunque parezca una tontería, esta postura choca frontalmente con la filosofía de diferentes sistemas Unix para los que el producto está disponible, lo que ha generado problemas de distribución y utilización del mismo; el ejemplo más extremo es el de OpenBSD, que por indicación expresa del mismísimo Theo de Raadt eliminó IP Filter de sus distribuciones en Mayo de 2001 y comenzó desde entonces el desarrollo de pf, similar al anterior pero liberado bajo otro tipo de licencia.

Instalación

IP Filter no se distribuye oficialmente en formato binario (en forma de paquete), por lo que el código ha de ser compilado antes de ser utilizado; de cualquier forma, su instalación en un sistema Unix suele ser muy sencilla: por ejemplo, en el caso de Solaris, la única precaución a tener en cuenta es que GNU CC (gcc) no puede compilar IP Filter en modo 64 bits, por lo que será necesario utilizar el compilador de Sun Microsystems o, en su defecto, EGCS. En cualquier caso, los pasos a seguir una vez descargado el archivo .tar.gz17.2 son los siguientes:
anita:/var/tmp# gzip -dc ip-fil3.4.17.tar.gz |tar xf -
anita:/var/tmp# cd ip_fil3.4.17
anita:/var/tmp/ip_fil3.4.17# /usr/xpg4/bin/make solaris
anita:/var/tmp/ip_fil3.4.17# cd SunOS5
anita:/var/tmp/ip_fil3.4.17/SunOS5# /usr/xpg4/bin/make package
La última de estas órdenes creará y añadirá automáticamente un paquete con el cortafuegos en nuestro sistema. Podemos comprobar que está correctamente instalado con la orden pkginfo:
anita:/var/tmp# pkginfo -l ipf
   PKGINST:  ipf
      NAME:  IP Filter
  CATEGORY:  system
      ARCH:  i386
   VERSION:  3.4.17
    VENDOR:  Darren Reed
      DESC:  This package contains tools for building a firewall
  INSTDATE:  Apr 06 2001 19:10
     EMAIL:  darrenr@pobox.com
    STATUS:  completely installed
     FILES:     80 installed pathnames
                12 shared pathnames
                 1 linked files
                24 directories
                11 executables
             21441 blocks used (approx)

anita:/var/tmp#
Tras instalar el paquete, definiremos las reglas de filtrado y NAT en los archivos correspondientes (tal y como veremos a continuación), y una vez hecho esto ya podremos inicializar nuestro firewall con la orden /etc/init.d/ipfboot start, que podemos incluir en el arranque de nuestra máquina de la forma habitual.

Si le pegamos un vistazo a este shellscript de inicialización del cortafuegos, generado al instalar el paquete ipf (en Solaris, /etc/init.d/ipfboot) podemos observar que en sus primeras líneas se definen los ficheros en los que se guardarán las reglas a instalar, tanto para filtrado como para traducción de direcciones. Se trata de simples archivos ASCII ubicados por defecto en el directorio /etc/opt/ipf/ que podemos modificar con nuestro editor preferido, aunque también podemos utilizar cómodos interfaces gráficos como fwbuilder (que ya hemos comentado al hablar de iptables e ipchains), capaces de generar reglas también para IP Filter.

Gestión

Como ya hemos comentado, una de las grandes diferencias de IP Filter con respecto a otros sistemas cortafuegos es que este toma su configuración - su política - de simples ficheros ASCII; realmente esto es una diferencia importante con respecto a otros sistemas cortafuegos, como iptables, que no están orientados a archivo: un script de arranque de IP Filter instala políticas leídas del fichero correspondiente, que posee una cierta sintaxis, mientras que uno de iptables ejecuta línea a línea órdenes que conforman la política a implantar.

El hecho de que IP Filter esté orientado a archivo es principalmente una cuestión de diseño, pero no tanto de gestión; la segunda - pero quizás la más importante - diferencia de IP Filter con respecto a casi todo el resto de firewalls del mercado sí que es puramente relativa a su gestión, y la encontramos a la hora de implantar en el cortafuegos la política de seguridad definida en nuestro entorno de trabajo: se trata del orden de procesamiento de las reglas de IP Filter, completamente diferente a Firewall-1, ipchains o iptables. En todos estos firewalls se analizan en orden las reglas instaladas hasta que una coincide con el tipo de tráfico sobre el que actuar (como se dice habitualmente, hasta que hace match); en ese momento ya no se analizan más reglas, sino que se aplica la acción determinada por la regla coincidente. IP Filter no sigue este esquema; por contra, se suelen (digo `se suelen' porque se puede forzar un comportamiento diferente) procesar todas las reglas definidas en nuestra configuración, desde la primera a la última, y se aplica la última coincidente con el tipo de tráfico sobre el que se va a actuar. Como esta forma de trabajar puede resultar al principio algo confusa (especialmente para la gente que ha trabajado con otros cortafuegos), veamos un ejemplo que aclare un poco nuestras ideas; imaginemos un conjunto de reglas como el siguiente (utilizando una nomenclatura genérica):
  Origen           Destino           Tipo        Puerto        Accion
----------------------------------------------------------------------
    *                 *               *             *           Allow
    *                 *               *             *           Deny
Si un administrador de Firewall-1 ve esta política implantada en su cortafuegos seguramente se llevará las manos a la cabeza, ya que este firewall interpretará únicamente la primera regla: como cualquier tráfico coincide con ella, es la única que se aplicará; de esta forma, la política anterior dejaría pasar todo el tráfico hacia y desde nuestra red (algo que evidentemente no es ni recomendable ni práctico, porque es exactamente lo mismo que no tener ningún firewall).

En cambio, IP Filter no sigue este mecanismo; el software procesará ambas reglas, y aplicará la última que coincida con el tipo de tráfico sobre el que se quiere actuar; como la segunda y última regla coincidirá con todo el tráfico que circule por el cortafuegos, será la que se aplicará siempre: en definitiva, todo será parado por el firewall (aunque esto sería evidentemente muy beneficioso para nuestra seguridad, en la práctica es impensable: equivale a desconectar a cada sistema, o al menos a cada segmento, del resto de la red).

Teniendo en cuenta esta peculiaridad del software, ya podemos comenzar a definir nuestra política de filtrado en el fichero correspondiente; como siempre, por seguridad vamos a denegar todo el tráfico que no esté explícitamente autorizado, por lo que la primera regla del archivo será justamente la que niegue todo, y a continuación se definirán más entradas contemplando el tráfico que deseamos permitir:
anita:/# head -4 /etc/opt/ipf/ipf.conf 
#####
# Bloqueamos todo lo que no se permita explicitamente
#####
block in all
anita:/#
Esta regla viene a decir que se bloquee (`block') todo el tráfico (`all') de entrada (`in') al sistema; como podemos ver, una de las ventajas de este cortafuegos, orientado a archivo, es que la sintaxis del fichero de configuración es extremadamente sencilla: al menos al nivel más básico, casi únicamente sabiendo inglés podemos deducir qué hace cada regla, a diferencia de ipchains o ipfilter y sus opciones, que a decir verdad no son precisamente inmediatas...

Una vez negado todo el tráfico que no habilitemos explícitamente ya podemos comenzar a definir las reglas que acepten tramas; como en el anterior ejemplo, imaginemos que deseamos permitir todo el tráfico web cuyo destino sea la dirección 158.42.22.41, así como los accesos SSH a esta misma IP desde la 158.42.2.1. Para conseguirlo, definiremos un par de reglas similares a las siguientes:
# HTTP
pass in on elxl0 from any to 158.42.22.41 port = 80
# SSH
pass in on elxl0 from 158.42.2.1 to 158.42.22.41 port = 22
Podemos seguir viendo la facilidad para interpretar la sintaxis del archivo: estamos permitiendo (`pass') el tráfico de entrada (`in') por el interfaz elxl0 desde cualquier sitio (`from any', en el caso de HTTP) o desde una dirección concreta (en el caso de SSH) a los puertos correspondientes de la máquina destino (`to 158.42.22.41'). Una vez hecho esto - realmente, las reglas que vamos a comentar a continuación deberíamos ubicarlas antes que las reglas `pass' en un sistema real, pero a efectos de comprender la sintaxis de IP Filter esto es irrelevante - vamos a definir ciertas reglas para bloquear y detectar ataques, que además nos van a servir para introducir la directiva `quick'. Al igual que hacíamos sobre nuestro firewall Linux, vamos a bloquear el tráfico dirigido a ciertos puertos sospechosos, como 31337 (BackOrifice), 79 (finger) o 7 (echo); además, nos interesa bloquear también el tráfico que entre por el interfaz externo (donde se supone que está Internet) y provenga de redes que no están pinchadas en este interfaz. En conseguir ambos objetivos, usaremos un conjunto de reglas similar al siguiente:
#####
## LOG de escaneos
#####
block in log quick on elxl0 from any to any port = 31337
block in log quick on elxl0 from any to any port = 79

#####
# Trafico que no deberia verse en la interfaz externa
#####
block in     quick on elxl0 from 192.168.0.0/16 to any
block in     quick on elxl0 from 172.16.0.0/12 to any
block in     quick on elxl0 from 10.0.0.0/8 to any
block in     quick on elxl0 from 127.0.0.0/8 to any
block in     quick on elxl0 from 0.0.0.0/8 to any
De nuevo, vemos que entender lo que hace cada regla es inmediato; lo que ahora nos puede llamar la atención es, por un lado, la utilización de la directiva `log', de la que hablaremos en el punto siguiente - aunque no hace falta ser muy listo para imaginar qué hace - y por otro, lo que vamos a ver ahora, el uso de `quick': esta directiva provoca que la regla se aplique inmediatamente y para el tráfico afectado el resto de reglas no se examine. De esta forma, con la política definida hasta ahora, si no hubiéramos utilizado la directiva `quick' para bloquear el acceso a nuestro puerto 79, siempre que se viera tráfico hacia este servicio se analizaría el fichero completo, y como la última regla que hace match es la que indica su bloqueo, las tramas se denegarían; al utilizar `quick', en el momento que esta regla hace match, el tráfico se deniega sin seguir examinando la política, presentando así un comportamiento más similar al de las reglas de otros firewalls.

Hasta ahora nos hemos limitado a crear o modificar el fichero donde definimos la política de IP Filter, pero esos cambios no van a tener efecto hasta que la máquina se reinicie o hasta que obliguemos al firewall a releer su archivo de configuración; para esto último podemos invocar al shellscript que carga el cortafuegos en el arranque de la máquina pasándole el parámetro `reload', de la forma /etc/init.d/ipfboot reload.

El sistema de log

Como cualquier sistema cortafuegos, IP Filter es capaz de generar registros cuando una determinada trama hace match con una regla que así lo indica; la forma de indicarlo, como ya hemos adelantado en el punto anterior, es mediante la directiva `log':
block in log quick on elxl0 from any to any port = 79
Esta regla bloquea (`block') de forma inmediata (`quick') el tráfico de entrada (`in') a través del interfaz elxl0, desde cualquier origen (`from any') a cualquier destino (`to any') y cuyo puerto destino sea el 79 (correspondiente a finger); mediante `log' hacemos que siempre que se haga match con ella esta regla genere un registro, para lo cual se utiliza la utilidad ipmon, inicializada en el mismo script que hemos visto antes para cargar la política de seguridad.

Por defecto, ipmon registra eventos con tipo `local0' y las siguientes prioridades predeterminadas ([McC00])
  • info: Paquetes que son sólo registrados, no aceptados o denegados.
  • notice: Paquetes registrados en una regla `pass'.
  • warning: Paquetes registrados en una regla `block'.
  • error: Paquetes cortos que pueden evidenciar un ataque basado en fragmentación de tramas IP.
Aunque este modelo suele ser más que suficiente en la mayoría de situaciones, si necesitamos un registro más fino podemos especificar, mediante la directiva `level', el tipo y la prioridad con que deseamos que una determinada regla registre las tramas que hacen match con ella; así, en el caso de la regla anterior, si queremos que cuando alguien trate de acceder al servicio finger de una máquina el tráfico se bloquee y además se registre un evento con tipo `auth' y prioridad `alert' (en lugar de `local0' y `warning', que serían los que le corresponderían por defecto), debemos reescribir la regla de una forma similar a:
block in log level auth.alert quick on elxl0 from any to any port = 79
Cuando esta regla haga match, se generará en el fichero correspondiente (no debemos olvidarnos de pegarle un vistazo a nuestro /etc/syslogd.conf para ver dónde se van a registrar los mensajes) una entrada de esta forma:
anita:/# tail -1 /var/log/syslog
02:59:04 anita ipmon[7043]: [ID 702911 auth.alert] 02:59:04.700386 elxl0 \
@0:2 b 62.42.102.18,4897 -> 192.168.0.3,79 PR tcp len 20 48 -S IN
anita:/#
Aparte de generar eventos a través de syslog, la herramienta ipmon permite monitorizar en tiempo real las tramas que generan registros mediante opciones como `-o' o `-a', en línea de comandos; evidentemente esto es útil para visualizar en una terminal el estado del log en nuestro cortafuegos, por ejemplo para iniciar mecanismos de respuesta automática ante un determinado evento; para obtener más información acerca de esta herramienta, y del sistema de log de IP Filter en general, podemos consultar la página de manual de ipmon(8).

PIX Firewall

Introducción

PIX (Private Internet eXchange) es una de las soluciones de seguridad ofrecidas por Cisco Systems; se trata de un firewall completamente hardware: a diferencia de otros sistemas cortafuegos, PIX no se ejecuta en una máquina Unix, sino que incluye un sistema operativo empotrado denominado Finesse que desde espacio de usuario se asemeja más a un router que a un sistema Unix clásico. Por tanto, dado que la gestión de este cortafuegos no es tan inmediata para un administrador de sistemas como la de uno que se ejecute sobre Unix, vamos a dedicarle más tiempo al PIX Firewall de lo que hemos dedicado al resto de cortafuegos.

El cortafuegos PIX utiliza un algoritmo de protección denominado Adaptive Security Algorithm (ASA): a cualquier paquete inbound (generalmente, los provenientes de redes externas que tienen como origen una red protegida) se le aplica este algoritmo antes de dejarles atravesar el firewall, aparte de realizar comprobaciones contra la información de estado de la conexión (PIX es stateful) en memoria; para ello, a cada interfaz del firewall se le asigna un nivel de seguridad comprendido entre 0 (el interfaz menos seguro, externo) y 100 (el más seguro, interno). La filosofía de funcionamiento del Adaptive Security Algorithm se basa en estas reglas:
  • Ningún paquete puede atravesar el cortafuegos sin tener conexión y estado.
  • Cualquier conexión cuyo origen tiene un nivel de seguridad mayor que el destino (outbound) es permitida si no se prohíbe explícitamente mediante listas de acceso.
  • Cualquier conexión que tiene como origen una interfaz o red de menor seguridad que su destino (inbound) es denegada, si no se permite explícitamente mediante listas de acceso.
  • Los paquetes ICMP son detenidos a no ser que se habilite su tráfico explícitamente.
  • Cualquier intento de violación de las reglas anteriores es detenido, y un mensaje de alerta es enviado a syslog.
Cuando a un interfaz del cortafuegos llega un paquete proveniente de una red con menor nivel de seguridad que su destino, el firewall le aplica el adaptive security algorithm para verificar que se trata de una trama válida, y en caso de que lo sea comprobar si del host origen se ha establecido una conexión con anterioridad; si no había una conexión previa, el firewall PIX crea una nueva entrada en su tabla de estados en la que se incluyen los datos necesarios para identificar a la conexión.

El cortafuegos PIX puede resultar muy complejo de gestionar, especialmente a los que provenimos del mundo Unix, ya que como hemos dicho se asemeja más a un router que a un servidor con cualquier flavour de Unix; es por tanto recomendable consultar bibliografía adicional antes de trabajar con estos equipos. Una buena referencia puede ser [JF01], así como la documentación sobre el producto que está disponible a través de la web de Cisco Systems (http://www.cisco.com/).

La primera sesión con PIX Firewall

Si conectamos al firewall por consola a través de una línea serie entramos directamente sin necesidad de contraseña, en modo no privilegiado; esto lo sabemos porque nos aparece el prompt siguiente:
pixie>
Si en este prompt tecleamos la orden `?', nos mostrará la ayuda disponible en el modo sin privilegios:
dixie> ?
enable          Enter privileged mode or change privileged mode password
pager           Control page length for pagination
quit            Disable, end configuration or logout
dixie>
Son pocos comandos con los que apenas se puede hacer nada; la orden pager nos permite ajustar el número de líneas para paginar, la orden quit (o exit) sale del firewall, y la orden enable nos pasa a modo superusuario, pidiendo la contraseña (que por defecto será `cisco'); cada orden del PIX se puede abreviar (por ejemplo, en lugar de enable podríamos teclear ena):
dixie> ena
Password: *****
dixie#
Como vemos, al estar en modo privilegiado, el prompt cambia y nos muestra una almohadilla; en este modo ya podemos reconfigurar parámetros del PIX, y tenemos más órdenes disponibles que antes:
dixie# ?
arp             Change or view the arp table, and set the arp timeout value
auth-prompt     Customize authentication challenge, reject or acceptance prompt
configure       Configure from terminal, floppy, or memory, clear configure
copy            Copy image from TFTP server into flash.
debug           Debug packets or ICMP tracings through the PIX Firewall.
disable         Exit from privileged mode
enable          Modify enable password
flashfs         Show or destroy filesystem information
kill            Terminate a telnet session
pager           Control page length for pagination
passwd          Change Telnet console access password
ping            Test connectivity from specified interface to <ip>
quit            Disable, end configuration or logout
reload          Halt and reload system
session         Access an internal AccessPro router console
terminal        Set terminal line parameters
who             Show active administration sessions on PIX
write           Write config to net, flash, floppy, or terminal, or erase flash
dixie#
Para comenzar a reconfigurar el firewall nos pondremos en modo configuración (desde modo privilegiado) con la orden configure (la `t' corresponde a Terminal); de nuevo, cambia el prompt que nos aparece en consola:
dixie# con t
dixie(config)#
En este modo disponemos de más comandos para configurar el PIX; como siempre, podemos verlos con la orden `?':
dixie(config)# ?
aaa             Enable, disable, or view TACACS+ or RADIUS
                user authentication, authorization and accounting
access-group    Bind an access-list to an interface to filter inbound traffic
access-list     Add an access list
age             This command is deprecated. See ipsec, isakmp, map, ca commands
alias           Administer overlapping addresses with dual NAT.
apply           Apply outbound lists to source or destination IP addresses
arp             Change or view the arp table, and set the arp timeout value
auth-prompt     Customize authentication challenge, reject or acceptance prompt
aaa-server      Define AAA Server group
ca              CEP (Certificate Enrollment Protocol)
        Create and enroll RSA key pairs into a PKI (Public Key Infrastructure).
clock           Show and set the date and time of PIX
conduit         Add conduit access to higher security level network or ICMP
crypto          Configure IPsec, IKE, and CA
configure       Configure from terminal, floppy, or memory, clear configure
copy            Copy image from TFTP server into flash.
debug           Debug packets or ICMP tracings through the PIX Firewall.
disable         Exit from privileged mode
domain-name     Change domain name
dynamic-map     Specify a dynamic crypto map template
enable          Modify enable password
established     Allow inbound connections based on established connections
failover        Enable/disable PIX failover feature to a standby PIX
filter          Enable, disable, or view URL, Java, and ActiveX filtering
fixup           Add or delete PIX service and feature defaults
flashfs         Show or destroy filesystem information
ipsec           Configure IPSEC policy
isakmp          Configure ISAKMP policy
global          Specify, delete or view global address pools,
                or designate a PAT(Port Address Translated) address
hostname        Change host name
vpdn            Configure VPDN (PPTP) Policy
interface       Identify network interface type, speed duplex, and if shutdown
ip              Set ip address for specified interface,
                define a local address pool, or
                toggle Unicast Reverse Path Forwarding on an interface.
kill            Terminate a telnet session
link            This command is deprecated. See ipsec, isakmp, map, ca commands
linkpath        This command is deprecated. See ipsec, isakmp, map, ca commands
logging         Enable logging facility
map             Configure IPsec crypto map
mtu             Specify MTU(Maximum Transmission Unit) for an interface
name            Associate a name with an IP address
nameif          Assign a name to an interface
names           Enable, disable or display IP address to name conversion
nat             Associate a network with a pool of global IP addresses
outbound        Create an outbound access list
pager           Control page length for pagination
passwd          Change Telnet console access password
ping            Test connectivity from specified interface to <ip>
quit            Disable, end configuration or logout
radius-server   Specify a RADIUS aaa server
reload          Halt and reload system
rip             Broadcast default route or passive RIP
route           Enter a static route for an interface
session         Access an internal AccessPro router console
snmp-server     Provide SNMP and event information
sysopt          Set system functional option
static          Map a higher security level host address to global address
tacacs-server   Specify a TACACS+ server
telnet          Add telnet access to PIX console and set idle timeout
terminal        Set terminal line parameters
tftp-server     Specify default TFTP server address and directory
timeout         Set the maximum idle times
url-cache       Enable URL caching
url-server      Specify a URL filter server
virtual         Set address for authentication virtual servers
who             Show active administration sessions on PIX
write           Write config to net, flash, floppy, or terminal, or erase flash
dixie(config)#

Interfaces de red

Cisco denomina a cada uno de sus interfaces hardware de la forma ethernetN o token-ringN. Desde el modo configuración podemos asignarles nombres simbólicos y niveles de seguridad, teniendo en cuenta que el nombre outside se asigna por defecto a la tarjeta ethernet0 y el nombre inside a la ethernet1. Además, el nivel de seguridad de la interfaz outside ha de ser el más bajo, 0, y el reservado para inside el más elevado, 100; el resto de tarjetas pueden tener cualquier número comprendido entre los dos anteriores.

Si queremos asignarle un nombre simbólico y un nivel de seguridad a un interfaz hemos de utilizar la orden nameif; por ejemplo, para denominar dmz a la tarjeta ethernet2, y darle un nivel 50, ejecutaríamos lo siguiente17.3:
dixie(config)# nameif e2 dmz security50
dixie(config)#
Es muy importante que exista una interfaza llamada outside con un nivel 0 y una inside con un nivel 100; si alguna de las dos no existe, o si está duplicada, el cortafuegos parará todo el tráfico que pase por él. Podemos ver si la configuración actual de las interfaces es correcta mediante la orden show nameif:
dixie(config)# show nameif
nameif ethernet0 outside security0
nameif ethernet1 inside security100
nameif ethernet2 dmz security50
nameif ethernet3 intf3 security15
dixie(config)#

Accesos entre interfaces

Para conseguir excepciones a las reglas de funcionamiento del adaptive security algorithm se utilizan los comandos nat y static; la orden nat permite que una interfaz de mayor seguridad pueda acceder a uno de menor, mientras que static hace justo lo contrario.

Para cada interfaz de mayor nivel de seguridad que quiera acceder a una de menor nivel hemos de ejecutar la orden nat:
dixie(config)# nat (dmz) 0 0.0.0.0 0.0.0.0
dixie(config)# sh nat
nat (dmz) 0 0.0.0.0 0.0.0.0 0 0
pixie(config)#
La orden anterior indica que el interfaz dmz accederá sin realizar NAT (el primer `0'), aplicando esto a todas las máquinas de la subred conectada a ese interfaz: los dos grupos `0.0.0.0' representan la dirección y la subred, respectivamente, de los equipos a los que permitimos la salida; si sólo quisiéramos que una de las máquinas conectada al interfaz dmz accediera a segmentos de menor prioridad, pondríamos su dirección IP y su máscara (255.255.255.255).

Si lo que queremos es permitir el acceso desde un interfaz de menor nivel de seguridad a uno de mayor ejecutaremos la orden static, que tiene la sintaxis siguiente:
static (if_interna,if_externa) dir_destino dir_destino netmask mascara
El hecho de que aparezca por duplicado la dirección destino de la máquina que estamos `publicando' al exterior es porque, al ejecutar la orden nat, hemos decidido no hacer NAT real; si lo estuviéramos haciendo, en lugar de la dirección destino utilizaríamos en primer lugar la dirección que le damos a la máquina hacia el exterior (típicamente, una IP pública) y en segundo la dirección que tiene el equipo dentro de la red a la que está directamente conectado (una privada).

De esta forma, si lo que queremos es que desde toda Internet (interfaz outside) se pueda acceder a nuestro servidor de correo POP3, en la máquina 158.42.22.41 (por ejemplo, dentro del interfaz dmz), ejecutaríamos en primer lugar la siguiente orden:
dixie(config)# static (dmz,outside) 158.42.22.41 158.42.22.41
                      netmask 255.255.255.255
dixie(config)# sh static 
static (dmz,outside) 158.42.22.41 158.42.22.41 netmask 255.255.255.255 0 0
dixie(config)#
Con el comando anterior nos limitamos a `publicar' la dirección de una máquina protegida por el PIX firewall al resto de Internet; pero esto no significa que ya se pueda acceder a ese sistema: tras la orden static, es necesario habilitar listas de control de acceso a los diferentes servicios de la dirección que hemos publicado, y asociar dichas listas de control a la interfaz correspondiente; si por ejemplo el acceso necesitado es SMTP, ejecutaríamos la siguiente orden:
dixie(config)# access-list prueba permit tcp any host 158.42.22.41
                      eq smtp
dixie(config)# access-group prueba in interface outside
dixie(config)#
Como vemos, asociamos la lista de control a la interfaz de entrada del tráfico, no a la que está conectada la máquina. El tema de las listas de control de acceso es el que vamos a ver en el punto siguiente.

Listas de control de acceso

Como acabamos de decir, para acceder a determinados servicios de una máquina, una vez hemos dejado establecer las conexiones entre interfaces, es necesario definir permisos sobre el modo de acceso, el origen y los servicios a los que se permite acceder de esa máquina; esto lo conseguiremos mediante la orden access-list, cuya sintaxis es la siguiente:
access-list ID accion proto dir-origen pto-origen dir-destino pto-destino
Si por ejemplo queremos habilitar un acceso HTTP desde cualquier lugar de Internet, y además acceso POP3 desde un determinado segmento externo (por ejemplo, 196.33.22.128/25) a la máquina 158.42.22.41, lo haremos mediante una lista de control de dos entradas (que llamaremos prova), que podemos crear con las siguientes órdenes:
pixie(config)# access-list prova permit tcp any host 158.42.22.41 eq http
pixie(config)# access-list prova permit tcp 196.33.22.128 255.255.255.128 
               host 158.42.22.41 eq http
pixie(config)#
Dentro de una lista de control es importante asegurarse que la regla más general es siempre la última; PIX funciona en este sentido como Firewall-1: en el momento en que una determinada regla hace match, se aplica y no se sigue analizando el resto. Por ejemplo, si queremos que ningún equipo del exterior haga ping a la máquina 158.42.22.41, excepto los que provienen de la red 196.72.31.0/24, definiremos la siguiente lista de control de acceso:
pixie(config)# access-list prova permit icmp 196.72.31.0 255.255.255.0 host 
               158.42.22.41
pixie(config)# access-list prova deny icmp any any
pixie(config)#
Con las órdenes anteriores no hacemos más que definir (o modificar, si ya existía) la ACL `prova'; esto no tiene ningún efecto sobre el funcionamiento del cortafuegos, ya que para que lo tenga tenemos que asociar esta lista a una interfaz de red: en concreto, a aquella de la que va a provenir el tráfico de entrada en cada caso. Para ello, utilizaremos la orden access-group:
pixie(config)# access-group prova in interface outside
pixie(config)#
Con este comando asociamos la lista de control a la interfaz especificada; si esta interfaz ya tenía asociada una lista de control, la nueva reemplaza a la antigua pero las conexiones no se pierden, ni siquiera las que estaban permitidas anteriormente pero ahora se niegan. Esto es útil para poder añadir entradas intermedias a las listas de control sin que las conexiones establecidas por el interfaz al que queremos asociarlas se pierdan: para ello, lo más rápido es copiar la lista en un editor de textos, realizar sobre el mismo las modificaciones necesarias, y grabarla de nuevo en el cortafuegos con otro nombre; tras esto, la asociamos al interfaz correspondiente mediante access-group, y cuando estemos seguros de que todo funciona correctamente la grabamos en memoria mediante write mem.

Si lo que queremos es añadir una entrada al final de la lista de control no es necesario todo esto: basta con ejecutar el access-list correspondiente para que la nueva entrada se añada a la lista, y automáticamente se aplique sobre el interfaz; si no queremos añadir, sino eliminar entradas de una ACL, podemos ejecutar directamente no access-list, orden que recibe como parámetro la entrada a eliminar:
pixie(config)# sh access-list prova
access-list prova permit tcp any host 158.42.22.41 eq smtp (hitcnt=0) 
access-list prova permit tcp any host 158.42.22.41 eq pop3 (hitcnt=0) 
access-list prova permit tcp any host 158.42.22.41 eq telnet (hitcnt=0) 
pixie(config)# no access-list prova permit tcp any host 158.42.22.41 eq pop3
pixie(config)# sh access-list prova
access-list prova permit tcp any host 158.42.22.41 eq smtp (hitcnt=0) 
access-list prova permit tcp any host 158.42.22.41 eq telnet (hitcnt=0) 
pixie(config)#
Como siempre, una vez que estemos seguros de que la configuración es correcta, será necesario grabar los cambios en memoria flash mediante write mem.

Rutado

En el cortafuegos PIX es necesario especificar mediante rutas estáticas cómo vamos a encaminar los paquetes que nos llegan, añadiendo una ruta para cada red conectada a un interfaz; sólo podremos asignar una ruta por defecto, asociada siempre al interfaz outside.

Para ver las rutas del firewall utilizaremos la orden sh route:
pixie(config)# sh route
        outside 0.0.0.0 0.0.0.0 172.17.1.3 1 OTHER static
        inside 172.17.2.0 255.255.255.0 172.17.2.1 1 CONNECT static
        dmz 192.168.63.0 255.255.255.0 192.168.63.156 1 CONNECT static
        failover 192.168.87.208 255.255.255.252 192.168.87.209 1 CONNECT 
                 static
        dmz 158.42.0.0 255.255.0.0 192.168.63.156 1 OTHER static
pixie(config)#
Como vemos, la ruta por defecto está asociada a la interfaz outside; además, la interfaz dmz tiene dos rutas, una para una clase pública y otra para una privada, y también existe una boca del firewall dedicada en exclusiva al failover, del que hablaremos más adelante.

Si lo que queremos es modificar cualquiera de estas rutas, añadir rutas nuevas, o eliminar alguna de ellas, ejecutaremos la orden route, cuya sintaxis es la siguiente:
route interfaz direccion-remota mascara gateway metrica
Por ejemplo, si deseamos enrutar el tráfico dirigido a la red 192.168.63.128/25 a través del interfaz dmz, que tiene como dirección IP 192.168.63.156, y que está directamente conectado a la red (un salto), ejecutaríamos esta orden:
pixie(config)# route dmz 192.168.63.128 255.255.255.128 192.168.63.156 1
pixie(config)#
Para eliminar una ruta, ejecutaremos el comando no route, que recibe como parámetro la ruta que deseamos eliminar (algo similar a lo que sucedía con las listas de control de acceso).

Otras órdenes útiles

Arranque y parada del cortafuegos

La orden reload (modo privilegiado) reinicia el firewall y carga su configuración, bien desde diskette bien desde la memoria flash (en caso de que no haya ningún disco en la unidad). Al ejecutar reload se nos pedirá confirmación para reiniciar el cortafuegos, y es muy importante que en caso de no querer ejecutar el comando tecleemos `n'; cualquier otra respuesta ejecuta la orden.

Configuraciones del sistema

Nombre de la máquina
Mediante la orden hostname cambiamos el nombre de host del cortafuegos:

dixie(config)# hostname pixie
pixie(config)# hostname dixie
dixie(config)#

Contraseñas
En modo configuración podemos cambiar la contraseña de acceso al modo privilegiado mediante la orden enable password; mediante show enable vemos la cadena cifrada con nuestra contraseña:

dixie(config)# show enable
enable password /hVDnFhQPQc4lzN5 encrypted
dixie(config)# enable password passprova
dixie(config)# show enable
enable password S6KVLr8BjSKx8os/ encrypted
dixie(config)#
Esta clave es diferente de la que se utiliza para acceder al cortafuegos vía telnet; para modificar esta última (por defecto será `cisco') utilizaremos la orden passwd, y para visualizar la cadena cifrada resultante show passwd:
dixie(config)# show passwd
passwd 2KFQnbNIdI.2KYOU encrypted
dixie(config)# passwd prova
dixie(config)# show passwd
passwd /hVDnFhQPQc4lzN5 encrypted
dixie(config)#
Si quisiéramos restaurar esta contraseña a su valor original (`cisco'), no tenemos más que ejecutar la orden clear passwd:
dixie(config)# show passwd
passwd /hVDnFhQPQc4lzN5 encrypted
dixie(config)# clear passwd
dixie(config)# show passwd
passwd 2KFQnbNIdI.2KYOU encrypted
dixie(config)#
La cadena `encrypted' que aparece tras la contraseña indica que se trata de una clave cifrada; también nos puede resultar útil para asignar un password directamente en cifrado, en lugar de hacerlo en texto claro:
dixie(config)# show passwd
passwd 2KFQnbNIdI.2KYOU encrypted
dixie(config)# passwd /hVDnFhQPQc4lzN5 encrypted
dixie(config)# show passwd
passwd /hVDnFhQPQc4lzN5 encrypted
dixie(config)# show enable password
enable password 2KFQnbNIdI.2KYOU encrypted
dixie(config)# enable password  /hVDnFhQPQc4lzN5 encrypted
dixie(config)# show enable password
enable password /hVDnFhQPQc4lzN5 encrypted
dixie(config)#
En caso de pérdida de la clave de acceso vía telnet, no tenemos más que conectar al cortafuegos mediante una conexión serie y, desde el modo privilegiado asignar una nueva contraseña; si lo que hemos perdido es la clave para situar al cortafuegos en modo privilegiado, el proceso es algo más complicado: en este caso debemos descargar la utilidad PIX Password Lockout Utility apropiada para nuestra versión de firewall (que podemos ver con sh version), desde la dirección
http://www.cisco.com/warp/public/110/34.shtml
Se trata de un fichero `.bin' que podemos transferir a un disquette mediante la orden dd:
anita:~$ dd if=np51.bin of=/dev/fd0
144+0 records in
144+0 records out
anita:~$
Tenemos que arrancar con el disco al que hemos transferido este sistema, que nos automáticamente nos preguntará si queremos borrar las claves; le diremos que sí y reiniciaremos el cortafuegos, que tendrá como contraseña de acceso remoto `cisco' y no tendrá password para pasar al modo privilegiado.

Cambios permanentes
Cada vez que nuestro PIX se apague perderá su configuración y cargará o bien una introducida en un diskette (esto es sólo teoría, nunca nos ha funcionado correctamente) o bien la que está grabada en su memoria flash; si deseamos que nuestros cambios sean permanentes hemos de grabarlos o en disco o en memoria flash , mediante la orden write (write floppy o write mem, en cada caso):

dixie# write mem
Building configuration...
Cryptochecksum: 206a9447 17e7ec36 d53c98d2 22a06c5e
[OK]
dixie# wr floppy
Building configuration...
[OK]
dixie#
Si lo que queremos es visualizar la configuración que vamos a grabar (la actual), podemos ejecutar la orden write terminal, que la volcará en pantalla; esto representa la configuración que se está ejecutando en estos momentos, cuyo resultado puede ser diferente del proporcionado por sh conf (este último muestra la configuración que hemos cargado al arrancar).

Configuración de terminal
Para reconfigurar el número de líneas de nuestra terminal de conexión, tanto en modo privilegiado como en modo usuario, podemos usar la orden pager, que recibe como parámetro el número de líneas deseado:

dixie> show pager
pager lines 24
dixie> pager 30
dixie> show page
pager lines 30
dixie>
Para configurar el número de columnas de nuestra consola podemos utilizar el comando terminal; si esta orden recibe como parámetro la palabra monitor, habilita la impresión de mensajes de syslog en nuestra pantalla, mientras que si recibe como parámetro la palabra width modifica el número de columnas. De nuevo, para ver la configuración actual utilizaremos la orden show:
dixie# show terminal

Width = 80, monitor
dixie# terminal width 90
dixie# show terminal

Width = 90, monitor
dixie#

Información del sistema

Las órdenes que nos permiten obtener información del estado actual del PIX comienzan por la palabra `show'; algunas de ellas son las siguientes:
  • show processes
    Muestra los procesos que se están ejecutando en el cortafuegos.
  • show version
    Muestra información genérica sobre el firewall, como la versión del software instalado en el PIX, el uptime del sistema, ciertos parámetros hardware, licencias, etc. Este es un ejemplo de dicha información:
    dixie(config)# show version
    
    Cisco Secure PIX Firewall Version 5.1(2)
    Compiled on Tue 16-May-00 16:09 by bhochuli
    Finesse Bios V3.3
    
    dixie up 140 days 0 hours
    
    Hardware:   SE440BX2, 128 MB RAM, CPU Pentium II 349 MHz
    Flash AT29C040A @ 0x300, 2MB
    BIOS Flash AM28F256 @ 0xfffd8000, 32KB
    
    0: ethernet0: address is 0090.279b.c9d2, irq 11
    1: ethernet1: address is 0090.279b.c848, irq 10
    2: ethernet2: address is 0090.279b.c759, irq 15
    3: ethernet3: address is 0090.279b.c84c, irq 9
    
    Licensed connections:   65536
    
    Serial Number: 18018531 (0x112f0e3)
    Activation Key: 0xfe1f8896 0xe1fcb1e2 0x3400545b 0x8f392616
    dixie(config)#
    
  • show interface
    Muestra información detallada sobre cada uno de los interfaces de red del firewall, de forma muy parecida al ifconfig de Unix.
  • show conn
    Muestra las conexiones activas a través del cortafuegos.
  • show history
    Muestra las últimas órdenes ejecutadas en línea de comandos, de una forma similar al histórico que casi todos los shells de Unix incorporan; la interfaz del PIX es muy similar a la de bash: Control-W borra una palabra, Control-E va al final de línea, Control-B al principio, Control-R realiza búsquedas, los cursores recorren el histórico de órdenes, etc.
  • show flashfs
    Muestra información sobre el sistema de ficheros empotrado en la memoria flash de la máquina.
  • show clock
    Muestra la fecha y hora del sistema; podemos modificar esta información mediante la orden clock:
    pixie(config)# sh clock
    01:38:34 Jun 11 2001
    pixie(config)# clock set 03:30:00 Jun 11 2001
    pixie(config)# sh clock
    03:30:02 Jun 11 2001
    pixie(config)#
    
  • show configure
    Muestra la configuración cargada al arrancar el cortafuegos (no tiene por qué ser la que se está ejecutando en estos momentos; esta se puede ver con wr t). Es el contenido de la memoria no volátil.
  • show failover
    Muestra el estado del subsistema de tolerancia a fallos.
  • show who
    Muestra las conexiones establecidas vía telnet con el cortafuegos.

El sistema de log remoto

El PIX Firewall registra los eventos que se producen en la máquina en un sistema de log que podemos visualizar en el propio cortafuegos mediante la orden sh log. También podemos enviar los registros a un sistema Unix que escuche peticiones de syslog remoto, indicando la interfaz por la que se van a enviar los registros y la dirección del sistema remoto mediante logging host:
pixie(config)# logging host inside 192.168.63.22
pixie(config)#
En el sistema donde deseemos enviar los registros, el demonio syslogd ha de estar escuchando peticiones remotas (opción `-r' del programa), y en los cortafuegos intermedios ha de estar habilitado el tráfico desde el PIX al puerto 514 (UDP) de la máquina Unix.

Por defecto, PIX registra eventos más relacionados con el estado del failover que con la seguridad de los sistemas y los posibles ataques que pueden sufrir. Esto genera una gran cantidad de mensajes que pueden hacer crecer al fichero de log de una forma considerable con entradas de este tipo:
Jun  6 09:46:37 192.168.63.156 %PIX-1-103003: (Primary) Other firewall 
                network interface 0 failed.
Jun  6 09:46:49 192.168.63.156 %PIX-1-103005: (Primary) Other firewall 
                reporting failure. 
Jun  6 09:46:49 192.168.63.156 %PIX-1-105004: (Primary) Monitoring on 
                interface 1 normal
Jun  6 09:51:04 192.168.63.156 %PIX-1-105009: (Primary) Testing on interface 
                0 Passed
Para evitar registrar estos mensajes, en el cortafuegos podemos ejecutar la orden no logging message, que recibe como parámetro el número de mensaje que no queremos guardar; por ejemplo, si queremos evitar el registro de la alerta PIX-1-103003, ejecutaremos:
pixie(config)# no logging message 103003
pixie(config)#
Si queremos lo contrario, volver a registrar el mensaje en el sistema remoto, ejecutaremos la misma orden pero sin el `no' delante, o bien clear logging disabled, que habilita el registro de todos los mensajes.
pixie(config)# logging message 103003
pixie(config)#
Podemos ver los mensajes que no estamos registrando mediante el comando sh logging disabled:
pixie(config)# sh logging disabled
no logging message 105008
no logging message 105009
no logging message 103003
no logging message 103004
no logging message 103005
pixie(config)#
A nosotros nos va a interesar más registrar eventos registrados con entradas y salidas al cortafuegos, y también con tráfico negado en el mismo. Para ello, podemos ver la facility y la severity de los mensajes de log en el sistema Unix; la facility es siempre PIX, mientras que la severity es el número siguiente en el código de mensaje registrado (de 1 a 7); por ejemplo, un mensaje con un código como PIX-6-307002 corresponde a una facility PIX y a una severity 6.

Podemos configurar nuestro syslog.conf para registrar los eventos provenientes del PIX (para Unix, con severity local4) en diferentes ficheros; lo más cómodo será registrar todos los eventos (ejecutando logging trap debugging) con una facility 20 (logging facility 20), y luego denegar mensajes determinados - relativos al failover mediante no logging message.

Failover

El sistema de alta disponibilidad implantado por PIX permite utilizar una unidad secundaria que tomará el control de las conexiones en caso de que la primaria falle; ambas unidades estarán conectadas por un cable serie (un RS-232 modificado) que transmite a 9600 baudios, y contínuamente se intercambian mensajes `hello' para que ambas puedan conocer el estado de la otra unidad. Si dos de estos mensajes consecutivos - se envían a intervalos de 15 segundos - no son recibidos en un determinado tiempo, entra en juego el failover para comprobar cual de las dos unidades ha fallado y transferir el control a la otra. Entonces cada unidad cambia de estado: la nueva unidad activa asume las direcciones IP y MAC de la anterior y comienza a aceptar tráfico, y la que antes era la activa ahora asume los parámetros de la que no lo era; el resto de elementos de la red no ve ningún cambio en los dispositivos, por lo que no existen cambios o timeouts en las tablas ARP.

Si queremos saber el estado del failover (por ejemplo para ver cuál es la unidad activa en un determinado momento) hemos de ejecutar la orden sh failover:
pixie(config)# sh failover
Failover On
Cable status: Normal
Reconnect timeout 0:00:00
        This host: Primary - Active 
                Active time: 386520 (sec)
                Interface failover (192.168.87.209): Normal 
                Interface dmz1 (192.168.63.156): Normal 
                Interface outside (172.17.1.1): Normal
                Interface inside (172.17.2.1): Normal 
        Other host: Secondary - Standby 
                Active time: 405 (sec)
                Interface failover (192.168.87.210): Normal 
                Interface dmz1 (192.168.63.157): Normal 
                Interface outside (172.17.1.2): Normal
                Interface inside (172.17.2.2): Normal 

Stateful Failover Logical Update Statistics
        Link : failover
        Stateful Obj    xmit       xerr       rcv        rerr      
        General         53081      0          50149      0         
        sys cmd         52067      0          50146      0         
        up time         0          0          0          0         
        xlate           9          0          0          0         
        tcp conn        1005       0          3          0         
        udp conn        0          0          0          0         
        ARP tbl         0          0          0          0         
        RIP Tbl         0          0          0          0         

        Logical Update Queue Information
                        Cur     Max     Total
        Recv Q:         0       1       50149
        Xmit Q:         0       3       53081
pixie(config)#
En el resultado de la orden anterior vemos que la unidad principal está funcionando normalmente, mientras que la secundaria está en standby; esto será lo habitual si no entra en juego el failover o incluso si entra y la unidad principal se recupera, ya que en ese caso se hace un rebalanceo. Si en lugar de que todas las interfaces estén en estado normal aparecieran errores temporales de escasa duración, no hay ningún problema, ya que esto suele significar que el cortafuegos está testeando la alta disponibilidad y la conectividad de las interfaces.

El failover es casi transparente a la administración de la máquina, en el sentido de que la configuración sólo se realiza en la unidad activa en cada momento, y automáticamente se transfiere a la que está en standby; además, como hemos dicho, cuando entra la alta disponibilidad las unidades intercambian sus direcciones IP, por lo que el acceso vía telnet a la máquina se realiza contra la misma dirección que durante el funcionamiento normal de los equipos. Incluso si trabajamos con stateful failover, las unidades mantienen la información de estado de cada conexión, por lo que en caso de switchover ninguna de ellas se pierde; en caso contrario, las conexiones activas son eliminadas y el cliente debe reestablecerlas.

Con la orden failover podemos habilitar el failover, y con no failover deshabilitarlo:
pixie(config)# no failover
pixie(config)# sh failover
Failover Off
Cable status: Normal
Reconnect timeout 0:00:00
pixie(config)#
Las órdenes anteriores también admiten argumentos; si indicamos `link' podemos definir la interfaz de stateful failover, por la que ambas unidades intercambiarán información. Con `ip address' podemos configurar una dirección de failover para cada interfaz de la unidad secundaria, y con el parámetro `active' forzamos a una unidad determinada ponerse como activa (o en standby, si ejecutamos no failover active). Como siempre, podemos teclear el signo `?' para obtener ayuda desde línea de comandos:
pixie(config)# failover ?
usage: [no] failover [active]
        failover ip address <if_name> <ip_address>
        failover timeout <hh:mm:ss>
        failover reset
        failover link <if_name>
pixie(config)# failover

next up previous contents
Siguiente: Ataques remotos Subir: Seguridad de la subred Anterior: Cortafuegos: Conceptos teóricos   Índice General
2002-07-15