Evitar un ataque DDoS con iptables tiene muchas maneras de hacerse, por tamaño de paquetes, por límite de conexiones, etc. Aquí veremos cómo, de una manera fácil, intuitiva y bien explicada lograremos el objetivo, así como detener otros molestos ataques a nuestros servers.
# Iptables
IPT="/sbin/iptables"
ETH="eth0"
#Todo el tráfico syn
$IPT -P INPUT DROP
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -p tcp ! --syn -j REJECT --reject-with tcp-reset
$IPT -A INPUT -m state --state INVALID -j DROP
$IPT -P OUTPUT DROP
$IPT -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -p tcp ! --syn -j REJECT --reject-with tcp-reset
$IPT -A OUTPUT -m state --state INVALID -j DROP
$IPT -P FORWARD DROP
$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -p tcp ! --syn -j REJECT --reject-with tcp-reset
$IPT -A FORWARD -m state --state INVALID -j DROP
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
$IPT -A FORWARD -i lo -o lo -j ACCEPT
#Cuando sube la carga
$IPT -A INPUT -p tcp --syn -j REJECT --reject-with icmp-port-unreachable
#La que mejor va
$IPT -N syn-flood
$IPT -A syn-flood -m limit --limit 100/second --limit-burst 150 -j RETURN
$IPT -A syn-flood -j LOG --log-prefix "SYN flood: "
$IPT -A syn-flood -j DROP
#Igual que el de arriba pero muy raw
$IPT -N syn-flood
$IPT -A INPUT -i eth0:2 -p tcp --syn -j syn-flood
$IPT -A syn-flood -m limit --limit 1/s --limit-burst 4 -j RETURN
$IPT -A syn-flood -j DROP
$IPT -A INPUT -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit --limit 1/sec -j ACCEPT
$IPT -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK RST -m limit --limit 1/sec -j ACCEPT
#Descartar paquetes mal formados
$IPT -N PKT_FAKE
$IPT -A PKT_FAKE -m state --state INVALID -j DROP
$IPT -A PKT_FAKE -p tcp --dport 80 --tcp-flags ALL ACK,RST,SYN,FIN -j DROP
$IPT -A PKT_FAKE -p tcp --dport 80 --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPT -A PKT_FAKE -p tcp --dport 80 --tcp-flags SYN,RST SYN,RST -j DROP
$IPT -A PKT_FAKE -p tcp --dport 80 ! --syn -m state --state NEW -j DROP
$IPT -A PKT_FAKE -f -j DROP
$IPT -A PKT_FAKE -j RETURN
#Syn-flood
$IPT -N syn-flood
$IPT -A INPUT -i eth+ -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j syn-flood
$IPT -A FORWARD -i eth+ -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j syn-flood
$IPT -A syn-flood -m limit --limit 4/s --limit-burst 16 -j RETURN
$IPT -A syn-flood -m limit --limit 75/s --limit-burst 100 -j RETURN -A syn-flood -j LOG --log-prefix "SYN FLOOD " --log-tcp-sequence --log-tcp-options --log-ip-options -m limit --limit 1/second
$IPT -A syn-flood -j DROP
#Requiere módulo "recent"
modprobe ipt_recent
$IPT -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set
$IPT -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 10 --hitcount 10 -j DROP
# explicación:
# Se añade cada ip que se conecte a la tabla de recent
# Por por cada ip en la tabla de recent si hace mas de x hits en x segundos, se dropea.
$IPT -I INPUT -p tcp --syn -m recent --set
$IPT -I INPUT -p tcp --syn -m recent --update --seconds 10 --hitcount 30 -j DROP
#UDP Flood
$IPT -A OUTPUT -p udp -m state --state NEW -j ACCEPT
$IPT -A OUTPUT -p udp -m limit --limit 100/s -j ACCEPT
$IPT -A OUTPUT -p udp -j DROP
Lo que hace es contar el número de paquetes SYN (inicio de conexión TCP) para cada dirección IP en los últimos 10 segundos. Si llega a 30 descarta ese paquete por lo que no se establecerá la conexión (el TCP volverá a intentar varias veces, cuando baje del límite podrá establecerse).
#Evitando Layer7 DoS limitando a 80 la máxima cantidad de conexiones
$IPT -A INPUT -p tcp --dport 80 -m hashlimit --hashlimit-upto 50/min --hashlimit-burst 80 --hashlimit-mode srcip --hashlimit-name http -j ACCEPT
$IPT -A INPUT -p tcp --dport 80 -j DROP
#Permitir el ping, pero a 1 paquete por segundo, para evitar un ataque ICMP Flood
$IPT -A INPUT -p icmp -m state --state NEW --icmp-type echo-request -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPT -A INPUT -p icmp -j DROP
#Evitando que escaneen la máquina
$IPT -A INPUT -i $ETH -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE –j DROP
$IPT -A INPUT -i $ETH -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN –j DROP
$IPT -A INPUT -i $ETH -p tcp -m tcp --tcp-flags SYN,RST SYN,RST –j DROP
$IPT -A INPUT -i $ETH -p tcp -m tcp --tcp-flags FIN,RST FIN,RST –j DROP
$IPT -A INPUT -i $ETH -p tcp -m tcp --tcp-flags ACK,FIN FIN –j DROP
$IPT -A INPUT -i $ETH -p tcp -m tcp --tcp-flags ACK,URG URG –j DROP
Aquí tienen el script en nuestro Paste: Paste.DesdeLinux.net (Script anterior)
Referencias:
- Intentando detener un DDoS (Foro ElHacker.net)
- Como evitar un ataque DDoS y como experimentarlo en servidores reales? (Foro ElHacker.net)
- Script con condicionales (MaliByte.net)
- Un muy buen ejemplo (LinuxGuruz.org)
- Previniendo un ataque DDoS (LinuxSecurity.com)
- Endureciendo el Stack TCP/IP para evitar ataques (SecurityFocus.com)
Y este es el por qué puse un tutorial antes de ataques DDoS 😉
Para poner/explicar el motivo o problema (tutorial anterior), y además darle a ustedes la solución (este tutorial) 🙂
perfecto.
El caramelo de los niños…
Buen artículo.
Mis dos centavos:
En el caso de los paquetes UDP no existe el flag SYN porque es un protocolo sin control de estado. Sin embargo, paradójicamente sí existen los estados NEW y ESTABLISHED porque iptables lleva internamente unas tablas para este fin.
Por otra parte, en mi opinión es mejor utilizar un destino DROP en lugar de REJECT, por dos razones: en primer lugar, con un reject uno está dando información a un posible atacante, y además el equipo está utilizando parte de su conectividad para enviar la notificación al equipo atacante.
Otra cosa es que en el caso del protocolo ICMP (y en general) conviene regular tanto las solicitudes como las respuestas, porque probablemente nos interese en algun momento hacer un ping nosotros, y al habilitar dicha funcionalidad, alguien podría utilizar una botnet y falseando la dirección de origen hacer un ping interminable a muchas de estas PCs comprometidas, y las respuestas irían a parar a nuestro servidor, colapsándolo de no imponerse límites.
Yo suelo permitir los tipos ICMP 0,3,8,11 y 12 con un límite de entrada de uno por segundo y una ráfaga de dos o cuatro como máximo, y todo lo demás queda en DROP.
En realidad, salvo el protocolo TCP que se puede regular mejor, todos los demás conviene protegerlos con una medida anti DDoS mediante una coincidencia tipo recent. A propósito de esto, como curiosidad, al autor de dicho módulo le gusta colocar primero el update y luego el set.
Iptables realmente es muy flexible y potente, hasta ahora lo único que me he propuesto hacer y aun no lo he conseguido (aunque estoy cerca lograrlo), es habilitar el módulo psd para evitar los portscans, pero incluso con todo lo que he aprendido sobre esta herramienta, considero que ni siquiera he arañado la superficie aun. 😉
En fin, que en este mundillo siempre hay que estudiar.
Buenos puntos Hugo, archivado para nuestro glosario :D, como siempre, aprendiendo…
Por cierto, ya logré que me funcionara el módulo psd. El problema era que incialmente dependía de una funcionalidad del kernel que quedó obsoleta junto con patch-o-matic, por lo que lo quitaron de los módulos integrados en netfilter por defecto. De modo que ahora en Debian para usar la extensión psd, antes hay que hacer esto:
aptitude -RvW install iptables-dev xtables-addons-{common,source} module-assistant
module-assistant auto-install xtables-addons-source
Después puede utilizarse normalmente, según las instrucciones:
man xtables-addons
Hugo, porque no publicas un iptables.sh con las sugerencias tuyas para mejorar el script de este post (que es bueno) incluyendo psd
Gracias
Exelente artículo, exelente el iptables y exelente la explicación de @hugo. Cada vez me convenzo más que aún me falta muucho por aprender.
No eres tú solo, a mi por lo menos… Me falta un millon… 😀
Hola a todos, y gracias por el aporte, pero la verdad estamos desesperado no sabemos que hacer ya, y acudimos a ustedes por esto de las iptables que sabemos que sois expertos en sistemas.
Les comento soy lider de una comunidad de españa de counter strike source y somos unas de las pocas que seguimos a duras penas en pie, estamos recibiendo a la maquina ataques ddos constantes y por intervalos de tiempo otros ataques, el constante quita poco pero lagea el servidor un poco pero el que es de tiempo hace mas daño. Nuestra maquina esta montada en un centos 6.2
y tenemos el tcadmin para controlar los servidores. Ustedes podrian hacernos una confguracion que pudiese parar este tipo de ataques aunque sea un poco es que estamos desesperados ya,
y no sabemos a quien recurrir sabemos que son de dos botnet una casera y otra de pago por tiempo y fuerza. Llevamos asi casi un año aguantando ataques brutales de este tipo, si pudieran ayudarnos estariamos eternamente agradecidos porque es insostenible ya, a mi me encanta configurar servidores como hoobie, y no soy un niño eso se los aseguro pero esto es mucho para mi. Si quieren mi ts3 para hablar o cualquier cosa me encantaria que pudiesen ayudarnos asi posteariamos aqui los resultados y todo lo que fuesen resolviendo para el bien de muchisimas personas, seria el blog mas visitado del año eso se lo aseguro porque es increhible como fastidia estos ataques ddos. Ya que nosotros intentamos configurarlo por nuestra cuenta y bloqueamos el acceso a la maquina que tuvimos que formatearla desde la bios asi que imaginense como estamos.
Les envio un cordial saludo. Y mis felicitaciones por el blog que falta le hace a mucha gente uno que estuviese actualizado com este. –Miguel Angel–
Hola qué tal 🙂
Escríbeme a mi email, te ayudamos con mucho gusto 😀 -» kzkggaara[@]desdelinux[.]net
Hola chicos hasta hora que estoy chambeando ocupe este script, muy bueno por cierto … solo una duda : ¿El modulo «recent» no merma el rendimiento?
Saludos – Gracias / ¿Quién como ustedes?
Excelente aporte mi amigo, te pondre en las referencias de un video tuto que estamos montado, un abrazo desde Costa Rica
Hola,
No puedo usar el script en varios puertos?
Tengo un servidor deun juego y recibo atauqes tanto a la web como a los puertos del servidor del juego.
Un saludo.