Simple stateful firewall (Español)

From ArchWiki
Jump to: navigation, search



Estado de la traducción: este artículo es una versión traducida de Simple stateful firewall. Fecha de la última traducción/revisión: 2014-12-26. Puedes ayudar a actualizar la traducción, si adviertes que la versión inglesa ha cambiado: ver cambios.
Según Wikipedia (en inglés)
Firewall Stateful es «en informática, un cortafuegos de estado (cualquier cortafuegos que realiza la inspección del estado de los paquetes (SPI) o la inspección de estado) es un cortafuegos que realiza un seguimiento del estado de las conexiones de red (por ejemplo, flujos TCP, comunicación UDP) que viajan a través de ella. El cortafuegos está programado para distinguir paquetes legítimos para diferentes tipos de conexiones. Solo los paquetes que coincidan con una conexión activa conocida serán permitidos por el cortafuegos; el resto serán rechazados».

Esta página explica cómo configurar un cortafuegos stateful usando iptables. También explica lo que significan las reglas y por qué son necesarias. Para simplificar, se divide en dos secciones principales. La primera sección trata sobre la configuración de un cortafuegos para una sola máquina, la segunda establece la configuración de una puerta de enlace NAT además de la del cortafuegos de la primera sección.

Advertencia: Las reglas se dan en el orden en que se ejecutan. Si está conectado a una máquina remota, es posible que se cierre el acceso a la máquina, mientras crea las reglas. Solo debe seguir los siguientes pasos mientras se está conectado en el sistema local.

El ejemplo de archivo de configuración se puede utilizar para solucionar este problema.

Requisitos previos

Nota: Su kernel debe ser compilado con soporte para iptables. Todos los kernels de stock de Arch Linux tienen soporte para iptables.

En primer lugar, instale las herramientas iptables en el espacio de usuario o verifique que ya están instaladas.

Este artículo supone que no hay reglas iptables establecidas en su sistema. Para comprobar el conjunto de reglas vigentes y cerciorarse que no existen actualmente reglas, ejecute lo siguiente:

# iptables-save
# Generated by iptables-save v1.4.19.1 on Thu Aug  1 19:28:53 2013
*filter
:INPUT ACCEPT [50:3763]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [30:3472]
COMMIT
# Completed on Thu Aug  1 19:28:53 2013

o

# iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 156 packets, 12541 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 82 packets, 8672 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Si hay reglas, podrá ser capaz de restablecerlas, cargando el conjunto de reglas por defecto:

# iptables-restore < /etc/iptables/empty.rules

De lo contrario, ver Iptables (Español)#Restablecer las reglas.

Cortafuegos para una sola máquina

Nota: Puesto que las reglas de iptables siguen procesos en orden lineal, de arriba a abajo dentro de una cadena, se aconseja poner las reglas más frecuentemente afectadas al principio de la cadena. Por supuesto que hay un límite, en función de la lógica que se está implementando. Además, las reglas tienen un costo de tiempo de ejecución asociado, por lo que las reglas no deben ser reordenadas basandose únicamente en observaciones empíricas de los recuentos de bytes/paquetes.

Crear las cadenas necesarias

Para esta configuración básica, vamos a crear dos cadenas, definidas por el usuario, que utilizaremos para abrir puertos en el cortafuegos.

# iptables -N TCP
# iptables -N UDP

Las cadenas pueden tener, por supuesto, nombres arbitrarios. Elegimos estos nombres solo para que coincidan con los protocolos que queremos manejar con ellos en las reglas posteriores, que se especifican con las opciones del protocolo, por ejemplo, -p tcp, siempre.

La cadena FORWARD

Si desea configurar el equipo como una puerta de enlace NAT, vaya a #Configurar una puerta de enlace NAT. Para una sola máquina, sin embargo, simplemente establecemos la política de la cadena FORWARD en DROP y continuamos con la configuración:

# iptables -P FORWARD DROP

La cadena OUTPUT

No tenemos ninguna intención de filtrar todo el tráfico saliente, ya que esto haría la configuración mucho más complicada y requeriría alguna reflexión adicional. Para el caso simple que nos ocupa, ponemos la política OUTPUT en ACCEPT.

# iptables -P OUTPUT ACCEPT

La cadena INPUT

De manera similar a las cadenas anteriores, fijamos la política predeterminada para la cadena INPUT en DROP como medida preventiva para evitar que se nos deslice algún error en nuestras reglas. Cerrar todo el tráfico y especificar luego qué tráfico entrante está permitido es la mejor manera de hacer un cortafuegos seguro.

Advertencia: Si está conectado a través de SSH, lo siguiente hará que se desconecte inmediatamente la sesión SSH. Para evitarlo: (1) añada la primera regla de la cadena INPUT de abajo (que mantendrá la sesión abierta), (2) añada una regla normal para permitir la entrada de SSH (para poder volver a reconectar en caso de una caída de la conexión) y (3) establezca la política de la cadena.
# iptables -P INPUT DROP

Cada paquete que se recibe por cualquier interfaz de red pasará primero por la cadena INPUT, si está destinado a nuestra máquina. Con esta cadena, nos aseguraremos de que solo los paquetes que queremos sean aceptados.

La primera regla añadida a la cadena INPUT permitirá el tráfico perteneciente a las conexiones ya establecidas, o para el nuevo tráfico válido relacionado con estas conexiones, como los errores ICMP, o las respuestas de Echo (los paquetes que retornan al equipo cuando se hace ping —«(...) es un servicio de red que repite aquel comando que se le envía (como el eco). Es útil para hacer comprobaciones sobre el estado de la conectividad de una red» [fuente: Wikipedia]—). ICMP (siglas en inglés de Internet Control Message Protocol) significa Protocolo de Mensajes de Control de Internet. Algunos mensajes ICMP son muy importantes y ayudan a gestionar la congestión y MTU, y son aceptados por esta regla.

El estado de conexión ESTABLISHED implica que, o bien otra regla anteriormente permitió la conexión inicial (--ctstate NEW) intentada o bien la conexión ya estaba activa (por ejemplo, una conexión SSH remota activa) al tiempo de establecer esta regla:

# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

La segunda regla aceptará todo el tráfico de la interfaz (lo) «loopback», que es necesario para muchas aplicaciones y servicios.

Nota: Se pueden agregar las interfaces más fiables aquí como «eth1» si no quiere/necesita que el cortafuegos filtre el tráfico, pero tenga presente que si tiene una configuración NAT que redirige cualquier tipo de tráfico a esta interfaz desde otro lugar de la red (digamos un router), va a conseguir lo mismo a través de ello, independientemente de cualquier otra configuración que pueda tener.
# iptables -A INPUT -i lo -j ACCEPT

La tercera regla descartará todo el tráfico que coincida con el estado «INVALID». El tráfico puede agruparse en una de las cuatro categorías de «estado»: NEW, ESTABLISHED, RELATED o INVALID, y esto es lo que hace de este sea un cortafuegos «stateful» (podríamos definirlo como un cortafuegos de filtrado dinámico de paquetes), en lugar de un cortafuegos «stateless» (filtrado de paquetes sin estado) que es menos seguro. Los estados hacen un seguimiento usando los módulos del kernel «nf_conntrack_*» que se cargan automáticamente por el kernel a medida que se añaden las reglas.

Nota:
  • Esta regla descartará todos los paquetes con cabeceras o sumas de comprobación no válidas, indicadores TCP no válidos, mensajes ICMP no válidos (como un puerto inaccesible cuando no enviamos nada para el equipo), y descarta los paquetes secuenciados que pueden ser causados por la predicción de secuencia u otros ataques similares. El objetivo de «DROP» es descartar un paquete sin dar ninguna respuesta, contrariamente a REJECT que rechaza el paquete. Utilizamos DROP porque no hay una respuesta adecuada a los paquetes que no son válidos, y no queremos reconocer que hemos recibido esos paquetes.
  • Los paquetes Neighbor Discovery de ICMPv6 permanecen sin seguimiento, y siempre se clasifican «INVALID» aunque no estén dañados o similares. Tenga esto presente, y acepte dicha situación antes de esta regla: iptables -A INPUT -p 41 -j ACCEPT
# iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

La siguiente regla aceptará todos las nuevas peticiones de ICMP echo requests, también conocidas como pings. Solo el primer paquete contará como NUEVO, el resto estará a cargo de la regla RELATED,ESTABLISHED. Dado que el equipo no es un router, ningún otro tráfico ICMP con el estado NEW necesita ser permitido.

# iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT

Ahora asociamos las cadenas TCP y UDP a la cadena INPUT para manejar todas las nuevas conexiones entrantes. Una vez que una conexión es aceptada por la cadena TCP o UDP, la misma es manejada por la regla de tráfico RELATED/ESTABLISHED. Las cadenas TCP y UDP bien aceptan las nuevas conexiones entrantes, o bien las rechazan. Las nuevas conexiones TCP deben comenzar con paquetes SYN.

Nota: NEW pero no SYN es la única etiqueta TCP no válida no cubierta por el estado INVALID. La razón es porque raramente son paquetes maliciosos, y esto no basta para descartarlos. En su lugar, simplemente no los aceptamos, por lo que se rechazan con un RST de TCP por la siguiente regla.
# iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
# iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP

Rechazamos las conexiones TCP con paquetes RST de TCP y flujos de UDP con mensaje de puerto ICMP inalcanzable, si no se abren los puertos. Esto imita el comportamiento predeterminado de Linux (RFC), y que permite al remitente cerrar rápidamente la conexión y limpiarla.

# iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p tcp -j REJECT --reject-with tcp-rst

Para otros protocolos, añadimos una regla final para la cadena INPUT para rechazar todo el tráfico entrante restante con protocolo ICMP de mensajes inaccesibles. Esto imita el comportamiento por defecto de Linux.

# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

Ejemplo de archivo iptables.rules

He aquí un ejemplo de archivo iptables.rules que se obtendría después de ejecutar todas las órdenes anteriores:

/etc/iptables/iptables.rules
# Generated by iptables-save v1.4.18 on Sun Mar 17 14:21:12 2013
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:TCP - [0:0]
:UDP - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
COMMIT
# Completed on Sun Mar 17 14:21:12 2013

Este archivo se puede generar con:

# iptables-save > /etc/iptables/iptables.rules

y se puede utilizar como base para continuar con las siguientes secciones. Si va a configurar un cortafuegos de forma remota a través de SSH, añada la siguiente regla para permitir nuevas conexiones SSH antes de continuar (ajustar el puerto si es necesario):

-A TCP -p tcp --dport 22 -j ACCEPT

Las cadenas TCP y UDP

Las cadenas TCP y UDP contienen reglas para la aceptación de nuevas conexiones TCP y flujos UDP entrantes para puertos específicos.

Nota: Aquí es donde necesita añadir reglas para aceptar conexiones entrantes, como SSH, HTTP u otros servicios a los que desee acceder de forma remota.

Apertura de puertos para conexiones entrantes

Para aceptar conexiones TCP entrantes en el puerto 80 para un servidor web:

# iptables -A TCP -p tcp --dport 80 -j ACCEPT

Para aceptar conexiones TCP entrantes en el puerto 443 para un servidor web (HTTPS):

# iptables -A TCP -p tcp --dport 443 -j ACCEPT

Para permitir conexiones remotas a través de SSH (en el puerto 22):

# iptables -A TCP -p tcp --dport 22 -j ACCEPT

Para aceptar transmisiones UDP entrantes en el puerto 53 para un servidor DNS:

# iptables -A UDP -p udp --dport 53 -j ACCEPT

Vea iptables(8) para conocer reglas más avanzadas, como equipar múltiples puertos.

Golpear puertos

El golpeo de puertos es un método para abrir puertos externamente que, por defecto, el cortafuegos mantiene cerrado. Funciona al demandar intentos de conexión a una serie de puertos cerrados de forma predefinida. Cuando la secuencia correcta del puerto al que se «golpea» (intentos de conexión) es recibida, el cortafuegos abre determinado puerto(s) para permitir una conexión. Ver Port knocking para más información.

Protección contra ataques de suplantación

Nota: rp_filter es ajustado actualmente a 1 por defecto en /usr/lib/sysctl.d/50-default.conf, por lo que el siguiente paso no es necesario..

El bloqueo de las direcciones locales reservadas entrantes desde Internet o red local se realiza normalmente a través de la configuración de rp_filter (Reverse Path Filter) en sysctl ajustándola a 1. Para ello, añada la siguiente línea al archivo /etc/sysctl.d/90-firewall.conf (ver sysctl para más detalles) para permitir la verificación de la dirección IP de origen que está integrado en el mismo kernel de Linux. La verificación por parte del kernel se encargará de la suplantación de identidad o spoofing mejor que las reglas de iptables individuales para cada caso.

net.ipv4.conf.all.rp_filter=1

Solo cuando el enrutamiento es asíncrono o se utiliza rp_filter=0, son necesarios chequeos adicionales:

# iptables -I INPUT ! -i lo -s 127.0.0.0/8 -j DROP

«Ocultar» el ordenador

Si está ejecutando una máquina de escritorio, esto podría ser una buena idea para bloquear algunas peticiones entrantes.

Bloquear solicitudes de ping

Una petición 'Ping' es un paquete ICMP enviado a la dirección IP de destino para garantizar la conectividad entre los dispositivos. Si la red funciona bien, puede bloquear de forma segura todas las solicitudes de ping. Es importante señalar que esto en realidad «no» oculta su ordenador —cualquier paquete que se le envíe será rechazado, por lo que aún se mostrará en un nmap simple de «escaneo de ping» de un conjunto de IP—.

Esta es una «protección» rudimentaria y hace más difícil la depuración de problemas en el futuro. Solo debe hacer esto para propósitos educativos.

Para bloquear las peticiones de Echo, añada la siguiente línea a su archivo /etc/sysctl.d/90-firewall.conf (ver sysctl para más detalles):

net.ipv4.icmp_echo_ignore_all = 1

Limitar la ratio es una mejor manera de controlar los posibles abusos. Este primer método implementa un límite global (es decir, solo se admiten X paquetes por minuto para todas las direcciones IP de origen):

# iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 30/min --limit-burst 8 -j ACCEPT
# iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

O, se puede utilizar el módulo 'recent', puede imponer un límite por dirección IP de origen:

# iptables -A INPUT -p icmp --icmp-type echo-request -m recent --name ping_limiter --set
# iptables -A INPUT -p icmp --icmp-type echo-request -m recent --name ping_limiter --update --hitcount 6 --seconds 4 -j DROP
# iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

Si decide utilizar la regla para la limitación de la ratio o para la limitación de la IP de origen, la regla PING que ya existe en la cadena INPUT debe ser borrada. Esto se puede hacer como se muestra a continuación, o, alternativamente, no la utilice en la primera posición.

# iptables -D INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT

A continuación, tiene que decidir dónde desea colocar la regla de la limitación de ratio o de la limitación de la IP de origen. Si coloca las reglas por debajo de la regla RELATED,ESTABLISHED entonces se hará el recuento y la limitación de las nuevas conexiones de ping, no de cada uno de los ping enviados a su máquina. Si se colocan antes de la regla RELATED,ESTABLISHED, entonces se contarán y limitarán cada ping enviado a su máquina, no cada conexión de ping hecha.

Puede encontrar más información en la página del manual de iptables, o leyendo la documentación y ejemplos en la página web http://snowman.net/projects/ipt_recent/

Engañar a los analizadores de puertos

Nota: Esto le abre a una forma de DoS (siglas en inglés de Denial of Service —ataque de denegación de servicios—). Un ataque puede enviar paquetes con direcciones IP falsas, y hacer que los recursos o servicios sean bloqueados para conectarse a los mismos por los usuarios legítimos.

Los escaneadores de puertos son utilizados por los atacantes para identificar los puertos abiertos en su equipo. Esto les permite identificar y analizar las huellas de sus servicios en ejecución y, posiblemente, lanzar exploits contra ellos.

La regla de estado INVALID se hará cargo de todos los tipos de escaneo de puertos, excepto para los escaneo de UDP, ACK y SYN (-sU, -sA y -sS en nmap, respectivamente).

Los escaneos ACK no se utilizan para identificar los puertos abiertos, pero si para identificar los puertos filtrados por un cortafuegos. Debido a la comprobación de SYN para todas las conexiones TCP con el estado NEW, cada paquete individual enviado por una exploración ACK será rechazado correctamente por un paquete TCP RST. Algunos cortafuegos bloquean estos paquetes en su lugar, y esto permite que un atacante pueda trazar las reglas del cortafuegos.

El módulo recent puede ser utilizado para engañar a los otros dos tipos de escaneos de puertos restantes. El módulo recent puede agregar equipos a una lista «recent» que se puede utilizar para los analizadores de huellas y detener ciertos tipos de ataques. Las listas recent actuales se pueden ver en /proc/net/xt_recent/.

Escaneos de SYN

En un escaneo SYN, el analizador de puertos envía paquetes SYN a cada puerto. Los puertos cerrados devuelven un paquete TCP RST, o son bloqueados por un cortafuegos estricto. Los puertos abiertos devuelven un paquete SYN ACK independientemente de la presencia o no de un cortafuegos.

El módulo recent se puede utilizar para realizar un seguimiento de los equipos con intentos rechazados y devolverles un TCP RST para cualquier paquete SYN que envían a puertos abiertos como si el puerto estuviera cerrado. Si un puerto abierto es el primero en ser escaneado, será devuelto un paquete SYN ACK pese a ello, por lo que las aplicaciones en ejecución, requieren que funcionen en puertos no esperados para que esto sea coherente, como ssh que debe ejecutarse en puertos no estándar.

En primer lugar, insertar una regla en la parte superior de la cadena TCP. Esta regla responde con un RST TCP a cualquier equipo añadido a la lista TCP PortScan en los últimos sesenta segundos. El parámetro --update hace que la lista recent se actualice, lo que hace que el contador de 60 segundo se restablezca.

# iptables -I TCP -p tcp -m recent --update --seconds 60 --name TCP-PORTSCAN -j REJECT --reject-with tcp-rst

A continuación, la regla para rechazar los paquetes TCP necesita ser modificada para incluir los equipos con paquetes rechazados en la lista TCP-PORTSCAN.

# iptables -D INPUT -p tcp -j REJECT --reject-with tcp-rst
# iptables -A INPUT -p tcp -m recent --set --name TCP-PORTSCAN -j REJECT --reject-with tcp-rst
Escaneos de UDP

Los escaneos de puertos UDP son similares a las exploraciones TCP SYN, excepto que UDP es un protocolo «sin conexión (previamente establecida)». No hay contacto ni reconocimiento. En cambio, el escáner envía paquetes UDP a cada puerto UDP. Los puertos cerrados devuelven mensajes ICMP de puertos inaccesibles, y los puertos abiertos no devuelven respuesta. Dado que UDP no es un protocolo «confiable», el escáner no tiene manera de saber si los paquetes se perdieron, y tiene que hacer varias comprobaciones para cada puerto que no devuelve una respuesta.

El kernel de Linux envía mensajes ICMP de puerto inaccesible muy lentamente, por lo que un escaneo UDP completo contra una máquina Linux podría durar más de 10 horas. Sin embargo, los puertos comunes todavía pudieron ser identificados, por lo que la aplicación de las mismas medidas contra escaneos de SYN para UDP es una buena idea.

En primer lugar, añada una regla para rechazar los paquetes de los equipos incluidos en la lista UDP-PortScan al inicio de la cadena de UDP.

# iptables -I UDP -p udp -m recent --update --seconds 60 --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable

A continuación, modifique la regla de rechazo de paquetes para UDP:

# iptables -D INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p udp -m recent --set --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
Restaurar la regla final

Si se utilizaron uno o ambas de los reglas de escaneo de puertos descritos, estas se colocarán por encima de la última regla por defecto, con lo cual esta última ya no será la regla final en la cadena INPUT. La regla por defecto tiene que ser la última regla, de lo contrario interferirá en las reglas del escaneo de puertos que acaba de agregar y nunca se utilizarán. Solo tiene que eliminar la regla (D) y, a continuación, añadirla (-A) de nuevo, lo que hará que la regla por defecto se coloque al final de la cadena.

# iptables -D INPUT -j REJECT --reject-with icmp-proto-unreachable
# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

Protección contra otros ataques

Consulte sysctl#TCP/IP stack hardening para conocer los parámetros del kernel más relevantes.

Ataques de fuerza bruta

Desafortunadamente, los ataques de fuerza bruta sobre los servicios accesibles a través de una dirección IP expuesta públicamente son comunes. Una razón para esto es que los ataques son fáciles de hacer con las muchas herramientas disponibles. Afortunadamente, hay varias formas de proteger los servicios contra ellos. Una de ellas es el uso de reglas apropiadas iptables que activen e incluyan en una lista negra las direcciones IP después de que estas hayan intentado iniciar una conexión de forma infructuosa con un número determinado de paquetes. Otro es el uso de demonios especializados que controlen los archivos del registro de intentos fallidos y la lista negra en consecuencia.

Advertencia: El uso de una lista negra de IP detendrá ataques triviales pero la misma se apoya en un demonio adicional y un registro de éxito (la partición que contiene /var puede llegar a saturarse, especialmente si un atacante late con fuerza en el servidor). Además, si el atacante conoce su dirección IP, puede enviar paquetes con un encabezado de origen falso y conseguir bloquearle el servidor. SSH keys proporciona una solución elegante al problema de la fuerza bruta sin estos problemas.

Dos aplicaciones que prohíben direcciones IP después de demasiados fracasos con la contraseña son Fail2ban o, para sshd, en particular, Sshguard. Estas dos aplicaciones actualizan las reglas de iptables para rechazar futuras conexiones desde direcciones IP incluidas en la lista negra.

Las siguientes reglas se dan como un ejemplo de configuración para mitigar los ataques de fuerza bruta contra SSH utilizando iptables.

# iptables -N IN_SSH
# iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j DROP
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j DROP 
# iptables -A IN_SSH -m recent --name sshbf --set -j ACCEPT

La mayoría de las opciones pueden explicarse por sí mismas, así las reglas precedentes permiten tres paquetes de conexión cada diez segundos. El resto de intentos en ese lapso de tiempo incluyen la IP en la lista negra. La siguiente regla añade una peculiaridad, al permitir un total de cuatro intentos en 30 minutos. Esto se hace porque algunos ataques de fuerza bruta que se realizan son realmente lentos y no en un estallido de intentos. Las reglas emplean una serie de opciones adicionales. Para leer más acerca de ellas, revise la referencia original para este ejemplo: compilefailure.blogspot.com

Una vez fijadas las reglas anteriores, ahora debe asegurarse que:

# iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH

están en una posición adecuada en el archivo iptables.rules.

Esta organización funciona para la regla IN_SSH si ha seguido todas las indicaciones de esta página hasta el momento:

*
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j IN_SSH
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
*

Las reglas anteriores pueden, por supuesto, ser utilizadas para proteger cualquier servicio, a pesar de que la protección del demonio SSH es, probablemente, el que más lo necesita.

Sugerencia: Para autodiagnosticar las reglas después de su configuración, la gestión de la lista negra vigente puede ralentizar la prueba, lo que dificultará afinar los parámetros. Se pueden ver los intentos de entrada a través de cat /proc/net/xt_recent/sshbf. Para desbloquear la propia IP durante las pruebas, se necesita root # echo / > /proc/net/xt_recent/sshbf

Guardar las reglas

El conjunto de reglas ya está terminado y se debe guardar en el disco duro para que pueda ser cargado en cada arranque.

Indique los puntos de localización de los archivos de unidad de systemd donde se guardarán la configuraciones de las reglas:

iptables=/etc/iptables/iptables.rules
ip6tables=/etc/iptables/ip6tables.rules

Guarde las reglas con esta orden:

# iptables-save > /etc/iptables/iptables.rules

y asegúrese de que sus reglas se cargan en el arranque, activando el demonio iptables.

Compruebe que la carga de las reglas se ha realizado correctamente, utilizando:

# systemctl start iptables.service && systemctl status iptables.service

IPv6

Si no utiliza IPv6 (la mayoría de los ISP no lo soportan), debe desactivarlo.

De lo contrario, debe activar las reglas del cortafuegos para IPv6. Después de copiar las reglas IPv4 como base:

# cp /etc/iptables/iptables.rules /etc/iptables/ip6tables.rules

el primer paso es cambiar las direcciones IP a las que se hacen referencia en las reglas de formato IPv4 a IPv6.

A continuación, algunas de las reglas (configuradas como ejemplo en este artículo para IPv4) tienen que ser adaptadas. IPv6 obtuvo un nuevo protocolo ICMPv6, en sustitución de ICMP. Por lo tanto, los códigos de retorno de error de rechazo --reject-with icmp-port-unreachable y --reject-with icmp-proto-unreachable tienen que ser convertidos en códigos ICMPv6.

Los códigos de error de ICMPv6 disponibles se enumeran en RFC 4443, que especifica que una regla de cortafuegos para bloquear los intentos de conexión debe utilizar --reject-with icmp6-adm-prohibited. Si lo bloquea, básicamente informa al sistema remoto que la conexión fue rechazada por el cortafuegos, en lugar de informar que un servicio fue escuchado.

Si se prefiere no informar explícitamente acerca de la existencia de un filtro en el cortafuegos, el paquete también puede ser rechazado sin el mensaje:

 -A INPUT -j REJECT

Lo anterior va a rechazar con la devolución de error por defecto --reject-with-icmp6-port-unreachable. Debe tener en cuenta, sin embargo, que la identificación de un cortafuegos es una característica básica de las aplicaciones de escaneo de puertos y la mayoría va a identificarlo a pesar de todo.

El siguiente paso es asegurarse de que el protocolo y la extensión se cambian al apropiado para IPv6 en la regla de todas las nuevas peticiones de echo ICMP entrantes (pings):

# ip6tables -A INPUT -p icmpv6 --icmpv6-type 8 -m conntrack --ctstate NEW -j ACCEPT

conntrack de netfilter no parece hacer el seguimiento del Protocolo Neighbor Discovery de ICMPv6 (el IPv6 equivalente de ARP), así que tenemos que permitir el tráfico ICMPv6 sin importar el estado para todas las subredes conectadas directamente. Lo siguiente debe insertarse después de descartar --ctstate INVALID, pero antes de cualquier otro objetivo DROP o REJECT, junto con la línea correspondiente de cada subred conectada directamente:

# ip6tables -A INPUT -s fe80::/10 -p icmpv6 -j ACCEPT

Puesto que no hay filtro de ruta inversa del kernel para IPv6, es posible que desee activar uno para ip6tables con las reglas que siguen, donde la primera regla es necesaria para conservar, por lo general, la dirección de enlace local unicasts de ICMPv6 requerida:

# ip6tables -t raw -A PREROUTING -p icmpv6 -s fe80::/10 -j ACCEPT
# ip6tables -t raw -A PREROUTING -m rpfilter -j ACCEPT
# ip6tables -t raw -A PREROUTING -j DROP

Después de realizar la configuración, active el servicio ip6tables, que está destinado para funcionar en paralelo a iptables.

Configurar una puerta de enlace NAT

Esta sección de la guía trata sobre la configuración de una puerta de enlace NAT (siglas en inglés de Network Address Translation —conversión de direcciones de red—). Se supone que ya ha leído la primera parte de la guía y configurado las cadenas INPUT, OUTPUT, TCP y UDP como se ha descrito anteriormente. Todas las reglas hasta ahora se han creado en la tabla filter. En esta sección, también vamos a tener que utilizar la tabla nat.

Configurar la tabla filter

Crear las cadenas necesarias

En nuestra configuración, utilizaremos otras dos cadenas en la tabla de filtros, las cadenas fw-interfaces y fw-open que crearemos con las siguientes órdenes:

# iptables -N fw-interfaces
# iptables -N fw-open

Configurar la cadena FORWARD

La creación de la cadena FORWARD es similar a la cadena INPUT de la primera parte de esta guía.

Ahora establecemos una regla con conntrack, idéntica a la de la cadena INPUT:

# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

El siguiente paso es activar el reenvío para las interfaces de confianza y hacer que todos los paquetes pasen por la cadena fw-open.

# iptables -A FORWARD -j fw-interfaces 
# iptables -A FORWARD -j fw-open 

A los paquetes restantes se les niega con un mensaje ICMP:

# iptables -A FORWARD -j REJECT --reject-with icmp-host-unreach
# iptables -P FORWARD DROP

Configurar las cadenas fw-interfaces y fw-open

El significado de las cadenas fw-interfaces y fw-open se explica más adelante, cuando nos ocupemos de las cadenas POSTROUTING y PREROUTING en la tabla nat, respectivamente.

Configurar la tabla nat

En toda esta sección, se supone que la interfaz de salida (la que tiene la IP expuesta públicamente a internet) es ppp0. Tenga en cuenta que tiene que cambiar el nombre en todas las reglas siguientes si su interfaz de salida tiene otro nombre.

Configurar la cadena POSTROUTING

Ahora, tenemos que definir quién tiene permisos para conectarse a Internet. Supongamos que tenemos la subred 192.168.0.0/24 (que significa que todas las direcciones tienen el formato 192.168.0.*) en eth0. Primero tenemos que aceptar las máquinas en esta interfaz en la tabla FORWARD, es por eso que hemos creado la cadena fw-interfaces anterior:

# iptables -A fw-interfaces -i eth0 -j ACCEPT

Ahora, tenemos que modificar todos los paquetes salientes de manera que tengan nuestra dirección IP pública como la dirección IP de origen, en lugar de la dirección LAN local. Para ello, utilizamos el objetivo MASQUERADE:

# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ppp0 -j MASQUERADE

No se olvide el parámetro -o ppp0 anterior. Si lo omite, su red no funcionará.

Supongamos que tenemos otra subred, 10.3.0.0/16 (que comprende todas las direcciones 10.3.*.*), en la interfaz eth1. Añadimos las mismas reglas que antes, además de:

# iptables -A fw-interfaces -i eth1 -j ACCEPT
# iptables -t nat -A POSTROUTING -s 10.3.0.0/16 -o ppp0 -j MASQUERADE

El último paso es activar el reenvío IP (si no está ya activado):

# echo 1 > /proc/sys/net/ipv4/ip_forward

A continuación, edite la línea relevante en /etc/sysctl.d/90-firewall.conf para que permanezca en el reinicio (vea sysctl para más detalles):

net.ipv4.ip_forward = 1

Las máquinas de estas subredes pueden ahora utilizar su nueva máquina NAT como su puerta de enlace. Tenga en cuenta que es posible que desee configurar un servidor DNS y DHCP como dnsmasq o una combinación de bind y dhcpd para simplificar la configuración de red en la resolución de DNS en los equipos clientes. Este no es el tema de esta guía.

Configurar la cadena PREROUTING

A veces, queremos cambiar la dirección de un paquete entrante de la puerta de entrada a una máquina de la LAN. Para ello, utilizamos la cadena fw-open definida antes, así como la cadena PREROUTING de la tabla nat.

Daremos dos ejemplos sencillos: en primer lugar, queremos cambiar todos los paquetes entrantes SSH (puerto 22) al servidor ssh en la máquina 192.168.0.5:

# iptables -A fw-open -d 192.168.0.5 -p tcp --dport 22 -j ACCEPT
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 22 -j DNAT --to 192.168.0.5

El segundo ejemplo le mostrará cómo cambiar los paquetes a un puerto diferente del puerto de entrada. Queremos cambiar cualquier conexión entrante en el puerto 8000 en nuestro servidor web 192.168.0.6, al puerto 80:

# iptables -A fw-open -d 192.168.0.6 -p tcp --dport 80 -j ACCEPT
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to 192.168.0.6:80

La misma configuración también funciona con los paquetes UDP.

Guardar las reglas

Guarde las reglas con:

# iptables-save > /etc/iptables/iptables.rules

y asegúrese de que sus reglas se cargan al arranque, activando el demonio iptables.

Véase también