Iptables: ejemplo para proteger un servidor web. Como Firewall

Uno de los Ataques al que será objeto un servidor web son aquellos como los de direcciones IP Enmascaradas o inválidas que intentan engañar al servidor para que entienda que los paquetes que recibe llegan desde la red interna o de una red confiable. Otro de los eventos al que es expuesto es al escaneo de puertos de comunicación que tiene como objetivo ver que puertos de comunicación tiene abierto el equipo y así determinar los servicios que está corriendo y utilizar esa información como base a un posible ataque.

El script de abajo, lo he estado provando mis servidores web y las reglas han mostrado ser efectivas. El script consiste en reglas de iptables para detener los paquetes inválidos y que llegan desde direcciones enmascaradas, intenta además detener el escaneo de puertos bloqueando por un tiempo determinado la dirección ip desde donde se origina. Otra de las mejores prácticas que se siguen aquí es la de descartar las conexiones a todos los puertos de comunicación y solo crear reglas con los puertos que realmente vamos a necesitar.

En este script permito las conexiones a los puertos HTTP (80), SSH (22), HTTPS (443), SMTP (25) y descarto cualquier otro. Se puede modificar según las necesidades. Por Ejemplo, el script permite solo los puertos 80 ya que es un servidor web sin certificado Digital y el 22 para las tareas de administración.

El Script para Firewall

# firewall.sh
#Limpiar Reglas Existentes
iptables -F

# INPUT
# Aceptar loopback input
iptables -A INPUT -i lo -p all -j ACCEPT

#Permitir Handshake de tres vias<
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#Detener Ataques Enmascarados<
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m icmp -m limit --limit 1/second -j ACCEPT

#Descartar Paquetes Inválidos
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP

#Descartar paquetes RST Excesivos para Evitar Ataques Enmascarados
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT

#Cualquier IP que intente un Escaneo de Puertos sera Bloqueada por 24 Horas.
iptables -A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
iptables -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP

#Pasadas las 24 Horas, remover la IP Bloqueada por Escaneo de Puertos
iptables -A INPUT -m recent --name portscan --remove
iptables -A FORWARD -m recent --name portscan --remove

#Esta Regla agrega el Escaner de Puertos a la Lista de PortScan y Registra el Evento.
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP

iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP

#Permitir estos puertos desde Fuera
# smtp
iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
# http
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
# https
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
# ssh & sftp
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT

#Descartar cualquier otra Entrada
iptables -A INPUT -j REJECT

#Permitir el Ping
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

#OUTPUT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#Permitir estos puertos desde Fuera
# smtp
iptables -A OUTPUT -p tcp -m tcp --dport 25 -j ACCEPT
# http
iptables -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
# https
iptables -A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT
# ssh & sftp
iptables -A OUTPUT -p tcp -m tcp --dport 22 -j ACCEPT

#Permitir Pings
iptables -A OUTPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

#Descartar cualquier otra Salida
iptables -A OUTPUT -j REJECT

#No Permitir Forward
iptables -A FORWARD -j REJECT

Medidas de seguridad para un servidor web con iptables

Iptables es un firewall que viene incluido en la mayoría de distribuciones basadas en GNU/Linux recientes, como cualquier otro firewall, su principal objetivo es filtrar paquetes entrantes y salientes de la maquina, este objetivo es cumplido con las reglas de configuración definidas en el firewall que delimitan puertos, protocolos, estados de conexiones, direcciones IP, entre otras cosas.

Para ver un manejo más sencillo de bloqueo con iptables leer : Como Bloquear con Iptables
Como podrá imaginar el lector, la “piedra angular” de esta potente herramienta es precisamente la correcta definición de las reglas establecidas, dado que una mala configuración de iptables, puede convertir un sistema operativo GNU/Linux es un objetivo fácil y casi tan inseguro como cualquier plataforma Windows (bueno, vale, he exagerado un poco…) no obstante, la correcta definición de las reglas definidas en el firewall permiten tener un sistema robusto contra intentos de penetración desde un sistema remoto, así que se trata de una practica vital en la seguridad en las comunicaciones entrantes y salientes que no debe de ser tomada nunca a la ligera y por el contrario, debería de ser una de las tareas mas importantes que desempeña un administrador y/o equipo en seguridad en redes y telecomunicaciones.

El uso de un conjunto de reglas bien definido, evita que cualquier escaner de puertos pueda enumerar todos los servicios que se ejecutan en el servidor, aunque es cierto que un escaner como Nmap puede generar “predicciones” sobre el sistema objetivo para brindar mas informacion a un atacante, utilizar reglas iptables correctamente establecidas, reduce considerablemente la precisión de un escaneo y de un posible ataque restringiendo el acceso a servicios sensibles tales como SSH, de este modo puede indicarse que solamente las direcciones IP definidas puedan acceder a dicho servicio, no obstante, esto no es a prueba de tontos, ya que un atacante puede realizar un ataque de “spoofing” utilizando como objetivo las direcciones IP que tienen acceso a dichos servicios, pero sin lugar a dudas, plantea dificultades a la hora de llevar a cabo un ataque

A continuacion se lista un ejemplo del uso de Iptables para permitir la conectividad de un servidor de paquetes entrantes solamente a los puertos 80/TCP y 443/TCP (Servidor Web) y por otro lado restringiendo el acceso de todos los paquetes entrantes al puerto 22/TCP (Donde se encuentra el servicio SSH) excepto para una dirección IP determinada (que puede ser una maquina de administración remota)

  1. En primera instancia, Limpiar todas las reglas actualmente establecidas en el servidor:
    iptables -F
    iptables -X
  2. Establecer la política de filtros, para Denegar por defecto todo
    iptables -P INPUT DROP
    iptables -P OUTPUT DROP
    iptables -P FORWARD DROP
  3. Aceptar todas las peticiones entrantes por HTTP al servidor web por el puerto 80 desde cualquier sitio
    iptables -A INPUT -p tcp -s 0/0 –sport 1024:65535 -d 192.168.1.33 –dport 80 -m state –state NEW,ESTABLISHED -j ACCEPT
  4. Aceptar todas las respuestas salientes por HTTP desde el servidor web por el puerto 80 a cualquier sitio
    iptables -A OUTPUT -p tcp -s 192.168.1.33 –sport 80 -d 0/0 –dport 1024:65535 -m state –state ESTABLISHED -j ACCEPT
  5. Aceptar todas las peticiones entrantes por HTTPS al servidor web por el puerto 443 desde cualquier sitio
    iptables -A INPUT -p TCP -s 0/0 –sport 1024:65535 -d 192.168.1.33 –dport 443 -m state –state NEW,ESTABLISHED -j ACCEPT
  6. Aceptar todas las respuestas salientes por HTTPS desde el servidor web por el puerto 443 a cualquier sitio
    iptables -A OUTPUT -p tcp -s 192.168.1.33 –sport 443 -d 0/0 –dport 1024:65535 -m state –state ESTABLISHED -j ACCEPT
  7. Aceptar conexiones entrantes SSH SOLAMENTE desde la dirección IP de administración (192.168.1.34) al servidor web en el puerto 22 TCP
    iptables -A INPUT -p tcp -s 192.168.1.34 –sport 1024:65535 -d 192.168.1.33 –dport 22 -m state –state NEW,ESTABLISHED -j ACCEPT
  8. Aceptar todo el trafico SSH saliente SOLAMENTE desde el servidor web en el puerto 22/TCP la dirección IP de administración
    iptables -A OUTPUT -p tcp -s 192.168.1.33 –sport 22 -d 192.168.1.34 –dport 1024:65535 -m state –state ESTABLISHED -j ACCEPT
  9. Finalmente, de forma explicita definir que todo el trafico entrante y/o saliente que no coincida con los criterios anteriormente declarados, deben ser borrados
    iptables -A INPUT -j DROP
    iptables -A OUTPUT -j DROP

Esta configuración se enfoca, principalmente en la capa de enlace y de transporte sobre el protocolo TCP/IP, permitiendo solamente aquellos paquetes interesantes y descartando cualquier otro tipo de paquete, de esta forma las peticiones y respuestas viajan de forma “segura” desde y hacia el servidor web. Este seriá un buen punto de partida que lleve hacia una configuración optima (es decir, un poco menos insegura o incitativa, sin embargo… en el mundo en el que vivimos todo es cada vez, menos seguro.)