Chapter 4. La máquina de estados

Este capítulo trata sobre la máquina de estados y la explica detalladamente, de forma que llegarás a comprender cómo trabaja. También hay una gran cantidad de ejemplos que clarifican cómo son tratados los estados por la máquina de estados: estos ejemplos nos ayudarán a entenderlo todo de la manera más práctica posible.

4.1. Introducción

La máquina de estados es una parte especial de iptables que no debería llamarse así ("máquina de estados"), puesto que en realidad es una máquina de seguimiento de conexiones. Sin embargo, mucha gente la conoce por el primer nombre. A lo largo del capítulo utilizaré ambos nombres como si fueran equivalentes, aunque ésto no debería ocasionar demasiados problemas. El seguimiento de conexiones se efectúa para que la estructura de Netfilter sepa cuál es el estado de cada conexión específica. Los cortafuegos que trabajan de esta manera normalmente se denominan "stateful firewalls" (cortafuegos que consideran las peticiones y respuestas de una máquina como una única conexión de un mismo flujo de datos; podríamos traducirlo como "cortafuegos de flujos"), mientras que los que no lo hacen se denominan "non-stateful firewalls" (cada petición es independiente, aunque provenga de la misma máquina; podríamos traducirlo como "cortafuegos de conexiones"). Los cortafuegos de tipo "stateful" son mucho más seguros, pues nos permiten elaborar conjuntos de reglas mucho más precisos.

En iptables los paquetes se pueden relacionar con las conexiones mediante cuatro "estados" diferentes: NEW (nuevo), ESTABLISHED (establecido), RELATED (relacionado) e INVALID (inválido o no válido). Los trataremos en profundidad más adelante. Mediante la comparación --state podemos controlar fácilmente qué o quién tiene permiso para iniciar nuevas sesiones.

Todo el seguimiento de las conexiones la realiza una estructura especial del núcleo llamada "conntrack". El "conntrack" puede cargarse como módulo o como una parte más del núcleo, pero sea como sea la mayoría de las veces necesitaremos y pediremos un seguimiento de conexiones más específico que el que proporciona por defecto el motor del conntrack. Por éllo, hay unas partes específicas que se encargan de los protocolos TCP, UDP o ICMP, entre otros. Estos módulos captan información específica, única, de los paquetes, de forma que pueden mantener un seguimiento de cada flujo de datos. La información que recopilan los módulos se utiliza para indicarle al conntrack en qué estado se encuentra el flujo en cada momento. Por ejemplo, los flujos UDP normalmente se identifican y distinguen por su dirección IP de destino, su dirección IP de origen, su puerto de destino y su puerto de origen.

En anteriores núcleos teníamos la posibilidad de ejecutar o parar la desfragmentación de paquetes, sin embargo, desde que se introdujeron iptables y Netfilter y en particular desde que se introdujo el seguimiento de conexiones, esta opción fue eliminada. La razón es que el seguimiento de conexiones no funciona correctamente sin defragmentar los paquetes, por lo que se ha introducido en el conntrack y el proceso se realiza automáticamente. No se puede parar si no paramos también el seguimiento de conexiones. En otras palabras, desde el momento en que se emplea el seguimiento de conexiones, se emplea la desfragmentación de paquetes.

Todo el seguimiento de conexiones se efectúa en la cadena PREROUTING, excepto los paquetes generados localmente, que son controlados en la cadena OUTPUT. Ésto significa que iptables realizará todo el recálculo de estados en estas dos cadenas de la tabla Nat: si somos nosotros los que enviamos el paquete inicial del flujo, su estado se establece como NEW (nuevo) en la cadena OUTPUT, mientras que al recibir el paquete de retorno (el que "contesta" al paquete inicial) el estado del flujo se cambia a ESTABLISHED (establecido) en la cadena PREROUTING. Por el contrario, si el primer paquete no lo hemos originado nosotros, el estado NEW se establece en la cadena PREROUTING.