Este artículo presenta los fundamentos de los firewalls y el proceso de manejo de paquetes en sistemas Linux, además explica cómo utilizar iptables para gestionar el firewall.
¿Por qué necesitamos firewalls?
En una red sin firewall, cualquier paquete enviado desde el Host A al Host B será recibido sin importar su contenido, incluso si contiene virus o malware. Aunque la intención maliciosa no debería existir, en redes es crucial tener medidas preventivas. Los firewalls proporcionan esta protección al inspeccionar el tráfico de red.
Con un firewall básico, los paquetes de datos pasan por un "control de entrada" donde solo aquellos que cumplen ciertos criterios continúan su transmisión, mientras que los demás son bloqueados o descartados.
Un firewall funcional requiere al menos dos interfaces de red: una para controlar los paquetes entrantes y otra para los paquetes salientes. Esto aplica tanto a firewalls de software como de hardware.
Un firewall funciona como un "muro contra el fuego": bloquea lo potencialmente dañino ("fuego") y permite lo seguro. La definición de qué constituye un riesgo es personalizable y se basa generalmente en el modelo OSI, simplificado en cuatro capas: aplicación (HTTP/FTP/SMTP), transporte (TCP/UDP), red e enlace.
Flujo de Transmisión de Datos
Proceso de Transmisión de Datos en Red
El flujo básico de transmisión de datos en red sigue estos pasos:
- Los datos ingresan a la capa de transporte donde se les añaden puertos origen y destino, convirtiéndose en segmentos (o datagramas para UDP).
- En la capa de red se añaden direcciones IP origen y destino, convirtiéndose en paquetes.
- En la capa de enlace se añaden direcciones MAC origen y destino, convirtiéndose en tramas.
Este proceso es una encapsulación de datos. Al llegar al destino, los paquetes se desencapsulan capa por capa hasta recuperar los datos originales.
Toma de Decisiones de Ruteo en el Equipo Local
Los procesos pueden comunicarse mediante varios métodos: memoria compartida, tuberías con nombre, sockets, colas de mensajes, semáforos, etc. El modelo OSI de comunicación es específico para la comunicación basada en sockets (IP+puerto), aplicándose tanto a comunicación entre hosts como a procesos locales dentro del mismo equipo.
En cualquier caso, los datos de red siempre fluyen hacia adentro y hacia afuera. Incluso en la comunicación entre procesos locales del mismo equipo, los datos deben pasar a través de sockets, aunque sin necesidad de ruteo o interfaces físicas (usando LoopBack).
Al recibir datos externos, después de ingresar por la interfaz de red, se debe tomar una decisión de ruteo para determinar si los datos son para el equipo local o deben ser reenviados a otros hosts. Si son para el equipo local, pasan del espacio del kernel al espacio de usuario (donde son recibidos y procesados por las aplicaciones). Cuando el espacio de usuario responde (generando nuevos paquetes), estos nuevos paquetes deben pasar por una decisión de ruteo antes de salir por alguna interfaz de red.
Si los datos no son para el equipo local sino que deben ser reenviados, inevitablemente involucrarán otra interfaz de salida, requiriendo que el equipo Linux pueda realizar este reenvío. Sin embargo, Linux tiene la función ip_forward desactivada por defecto, lo que impide el reenvío de paquetes. A diferencia de los routers, que están diseñados específicamente para reenviar paquetes entre interfaces, los equipos Linux no lo hacen por defecto.
Protocolo TCP: Tres Pasos de Conexión, Cuatro de Desconexión y Ataques SYN
Tres Pasos para Establecer Conexión TCP
- Cliente y servidor están en estado CLOSED.
- El servidor abre su puerto de servicio y entra en estado LISTEN.
- El cliente inicia una conexión enviando un paquete SYN al servidor, esperando una respuesta ACK. El cliente entra en estado SYN-SENT.
- El servidor recibe el SYN y responde con un ACK, enviando también su propio SYN. El servidor entra en estado SYN-RECV.
- El cleinte recibe el ACK del servidor y envía otro ACK, entrando en estado ESTABLISHED.
- El servidor recibe el ACK final y también entra en estado ESTABLISHED.
Cuatro Pasos para Cerrar Conexión TCP
Antes de desconectar, ambos están en estado ESTABLISHED. Supongamos que el cliente inicia el cierre:
- El cliente envía un paquete FIN, entrando en estado FIN-WAIT-1.
- El servidor recibe el FIN y responde con ACK, entrando en estado CLOSE-WAIT. La conexión del cliente al servidor está cerrada.
- El cliente recibe el ACK y entra en estado FIN-WAIT-2, esperando el FIN del servidor.
- El servidor envía su FIN al cliente, entrando en estado LAST-ACK.
- El cliente recibe el FIN del servidor y responde con ACK, entrando en estado TIME-WAIT.
- El servidor recibe el ACK final y entra en estado CLOSED.
Ataques SYN Flood
El ataque SYN flood es una forma común de DDoS donde el atacante envía gran cantidad de solicitudes de conexión TCP con direcciones IP falsas en poco tiempo. El servidor responde a cada solicitud pero nunca recibe la confirmación final, manteniendo conexiones parciales que consumen recursos.
Para detectar este ataque, se pueden usar herramientas como netstat para identificar conexiones en estado SYN_RECV con múltiples fuentes IP diferentes.
Alcances de Evaluación del Firewall
Los firewalls se clasifican según el dispositivo (software, hardware, a nivel de chip) y según la tecnología (filtrdao de paquetes, proxy de aplicación).
Evaluación desde la Capa de Enlace
Los firewalls basados en la capa de enlace controlan direcciones MAC. Por ejemplo, se podrían restringir las direcciones MAC de los empleados para limitar su acceso a Internet externo. Sin embargo, este método es poco flexible y difícil de mantener.
Evaluación desde la Capa de Red
La capa de se centra en direcciones IP (y protocolos como ICMP). Se pueden crear reglas basadas en IP origen/destino, protocolos específicos, etc.
Evaluación desde la Capa de Transporte
Se pueden filtrar conexiones basadas en protocolos TCP o UDP y puertos específicos. Por ejemplo, bloquear el puerto 22 impediría conexiones SSH.
Evaluación desde la Capa de Aplicación
Los firewalls que operan en esta capa son proxies de aplicación que desencapsulan los paquetes para inspeccionar su contenido. Son más efectivos pero consumen más recursos.
Evaluaciones Especiales
- Por contenido del paquete: Inspeccionar el contenido de los paquetes para detectar patrones específicos.
- Por estado de conexión: Permitir paquetes relacionados con conexiones ya establecidas, permitiendo respuestas mientras se bloquean nuevas conexiones no solicitadas.
Filtrado de Paquetes
El mecanismo subyacente del protocolo TCP/IP funciona de manera que los paquetes deben pasar por puntos de control específicos antes de ser procesados. En Linux, estos puntos de control son implementados por netfilter en el kernel, con los siguientes puntos clave:
- PREROUTING: Paquetes entrantes antes de la toma de decisiones de ruteo.
- INPUT: Paquetes destinados al equipo local.
- FORWARD: Paquetes que deben ser reenviados.
- OUTPUT: Paquetes generados localmente.
- POSTROUTING: Paquetes salientes después de la toma de decisiones de ruteo.
Relación entre iptables y Netfilter
Netfilter es el componente en el kernel que realmente implementa las funciones del firewall. iptables es la herramienta de espacio de usuario que gestiona las reglas de netfilter. iptables permite definir reglas y acciones, mientras que netfilter las ejecuta.
Fundamentos del Firewall en Linux
Estructura de Netfilter
Netfilter mantiene tablas en memoria para almacenar reglas. Las principales tablas son:
- filter: La más importante, responsable del filtrado de paquetes.
- NAT: Para traducción de direcciones de red.
- mangle: Para modificar paquetes.
- raw: Para optimizar el rendimiento.
Cada tabla contiene cadenas (chains) que son contenedores de reglas. Las cadenas principales son INPUT, OUTPUT y FORWARD.
Cadenas INPUT, OUTPUT y FORWARD
- INPUT: Protege el equipo local. Reglas aquí controlan paquetes destinados al equipo.
- OUTPUT: Controla el tráfico saliente del equipo local.
- FORWARD: Protege equipos "backend" cuando el firewall actúa como intermediario.
Ejemplo de Configuración de Firewall
Una configuración típica podría incluir:
- Reglas específicas para servicios permitidos (SSH, HTTP, etc.)
- Política por defecto de DROP en INPUT y FORWARD
- Permitir tráfico en bucle (loopback)
- Permitir respuestas a conexiones establecidas
Comandos de iptables
La sintaxis básica de iptables es:
iptables [-t TABLA] COMANDO CADENA [expresiones -j destino]
Comandos Principales
- -A: Añadir regla al final de una cadena
- -I: Insertar regla en una posición específica
- -D: Eliminar regla
- -L: Listar reglas
- -F: Limpiar reglas
- -Z: Reiniciar contadores
- -P: Establecer política por defecto
Opciones Comunes
- -p: Especificar protocolo
- -s: Dirección origen
- -d: Dirección destino
- -i: Interfaz de entrada
- -o: Interfaz de salida
- -j: Acción a tomar (ACCEPT, DROP, REJECT, etc.)
Extensiones Comunes
- -m state: Para evaluar el estado de la conexión (NEW, ESTABLISHED, RELATED, INVALID)
- -m multiport: Para especificar múltiples puertos
- -m limit: Para limitar la tasa de paquetes
- -m connlimit: Para limitar conexiones por cliente
Ejemplos de Reglas
# Permitir SSH desde una red específica
iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT
# Permitir respuestas a conexiones establecidas
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Bloquear ping al equipo
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# Permitir tráfico en bucle
iptables -A INPUT -i lo -j ACCEPT
Gestión de Reglas
Las reglas de iptables se almacenan en memoria y se pierden al reiniciar. Para persistir las reglas:
- Guardar en archivo:
service iptables save
- Cargar desde archivo:
iptables-restore < /etc/sysconfig/iptables
Es recomendable crear scripts de shell para gestionar las reglas, permitiendo:
- Modificación centralizada
- Uso de variables
- Facilidad de lectura con comentarios
- Backup sencillo
- Carga automática al inicio
Cadenas Personalizadas
Las cadenas personalizadas permiten crear conjuntos de reglas reutilizables:
# Crear cadena personalizada
iptables -N mi_cadena_seguridad
# Añadir reglas a la cadena personalizada
iptables -A mi_cadena_seguridad -p tcp ! --syn -m state --state NEW -j DROP
# Referenciar la cadena personalizada desde una cadena principal
iptables -A INPUT -j mi_cadena_seguridad
NAT (Traducción de Direcciones de Red)
NAT permite modificar direcciones IP y puertos, útil para:
- Compartir acceso a Internet desde redes privadas
- Proteger servidores internos
- Mapear puertos
SNAT (Traducción de Fuente)
Modifica la dirección origen de paquetes salientes:
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j SNAT --to-source 203.0.113.10
DNAT (Traducción de Destino)
Modifica la dirección destino de paquetes entrantes:
iptables -t nat -A PREROUTING -i eth1 -d 203.0.113.10 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:8080
Configuración de Gateway y Reenvío
Para que un equipo Linux actú como gateway, primero se debe habilitar el reenvío de paquetes:
echo 1 > /proc/sys/net/ipv4/ip_forward
Luego se pueden configurar reglas en la cadena FORWARD del filter table para controlar el tráfico entre redes.