Protección DDoS Mediante iptables
Y precisamente una de las amenazas más tangibles de esta década son los famosos ataques de denegación de servicio distribuidos (DDoS) que vemos tanto en los medios y que provocan a las empresas pérdidas millonarias con sólo afectar a la disponibilidad de sus sistemas durante un breve (o no) periodo de tiempo.
Para contrarrestar estos ataques, iptables y en general el kernel de Linux nos ofrece ciertas protecciones que debemos tener en cuenta. El genial artículo de Constantin Oesterling en Javapipe da buena cuenta de ello, así que repasaremos algunas de sus medidas para mitigar DDoS.
Tuneando el kernel
Lo primero que tenemos que hacer antes de abordar las reglas como tal es optimizar el kernel para mitigar los efectos de los ataques DDoS. El siguiente ejemplo se basa en CentOS 7 ya que esta distro incluye una versión reciente de iptables y soporta synproxy. Sólo hay que ponerla en /etc/sysctl.conf y aplicar la configuración con sysctl -p:
kernel.printk = 4 4 1 7
kernel.panic = 10
kernel.sysrq = 0
kernel.shmmax = 4294967296
kernel.shmall = 4194304
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
vm.swappiness = 20
vm.dirty_ratio = 80
vm.dirty_background_ratio = 5
fs.file-max = 2097152
net.core.netdev_max_backlog = 262144
net.core.rmem_default = 31457280
net.core.rmem_max = 67108864
net.core.wmem_default = 31457280
net.core.wmem_max = 67108864
net.core.somaxconn = 65535
net.core.optmem_max = 25165824
net.ipv4.neigh.default.gc_thresh1 = 4096
net.ipv4.neigh.default.gc_thresh2 = 8192
net.ipv4.neigh.default.gc_thresh3 = 16384
net.ipv4.neigh.default.gc_interval = 5
net.ipv4.neigh.default.gc_stale_time = 120
net.netfilter.nf_conntrack_max = 10000000
net.netfilter.nf_conntrack_tcp_loose = 0
net.netfilter.nf_conntrack_tcp_timeout_established = 1800
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 20
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 20
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 20
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 20
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 10
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.ip_no_pmtu_disc = 1
net.ipv4.route.flush = 1
net.ipv4.route.max_size = 8048576
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_congestion_control = htcp
net.ipv4.tcp_mem = 65536 131072 262144
net.ipv4.udp_mem = 65536 131072 262144
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.udp_rmem_min = 16384
net.ipv4.tcp_wmem = 4096 87380 33554432
net.ipv4.udp_wmem_min = 16384
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 400000
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rfc1337 = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 10
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.ip_forward = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.rp_filter = 1
Estos ajustes en sysctl.conf ayudan a maximizar el rendimiento de un servidor bajo un ataque DDoS, así como la eficacia de las reglas de iptables que veremos a continuación.
Filtrar lo máximo posible en la tabla mangle y la cadena PREROUTING
Lo segundo que hay que tener en cuenta que el rendimiento de las reglas de iptables es extremadamente importante. La mayoría de los ataques DDoS basados en TCP se realizan con una alta tasa de transferencia de paquetes, es decir, con un gran número de paquetes por segundo lo que hace que el servidor se caiga. Es por eso que hay que asegurarse de que se pueda procesar y bloquear la mayor cantidad de paquetes por segundo como sea posible.
Muchas guías sobre cómo bloquear los ataques DDoS usando iptables utilizan la tabla de filtros y la cadena INPUT para las reglas anti-DDoS. El problema con este enfoque es que la cadena de INPUT sólo se procesa después de las cadenas PREROUTING y FORWARD y, por lo tanto, sólo se aplica si el paquete no coincide con ninguna de estas dos cadenas. Esto provoca un retraso en el filtrado de los paquetes que consume recursos.
Por ello, para hacer las reglas más eficaces, tenemos que hacer que nuestro anti-DDoS utilice el menor número de cadenas posible. La primera cadena que puede aplicarse a un paquete es la cadena PREROUTING, por lo que lo ideal es filtrar el máximo de paquetes en esa cadena. Sin embargo, la tabla de filtros o filter no es compatible con la cadena PREROUTING. Para solucionar este problema, podemos simplemente utilizar la tabla mangle en lugar de la tabla de filtros para nuestras reglas de iptables anti-DDoS ya que es compatible con la mayoría, si no todas, las reglas.
En resumen, la mejor solución para aumentar drásticamente el rendimiento de las reglas de iptables y por lo tanto la cantidad de ataques DDoS (TCP) que pueden filtrar es utilizar la tabla mangle y la cadena PREROUTING.
Siguiendo las conexiones
Ahora bien, los ataques DDoS son complejos. Hay muchos tipos diferentes de DDoS y es casi imposible mantener reglas basadas en firmas contra todos ellos. Pero por suerte hay algo llamado seguimiento de conexiones (el módulo del kernel nf_conntrack) que nos puede ayudar a mitigar casi cualquier ataque DDoS basado en TCP que no utilizan paquetes SYN que parecen legítimos. Esto incluye todos los tipos de ataques DDoS ACK y SYN-ACK, así como ataques DDoS que utilizan flags TCP falsos.
Vamos a empezar sólo con cinco reglas de iptables sencillas que detendrán muchos ataques DDoS basados en TCP.
1.- Bloquear paquetes no válidos: Esta regla bloquea todos los paquetes que no son un paquete SYN y no pertenecen a una conexión TCP establecida.
iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
2.- Bloquear nuevos paquetes que no son SYN: Esto bloquea todos los paquetes que son nuevos (no pertenecen a una conexión establecida) y no utilizan el indicador SYN, complementa la regla anterior.
iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
3.- Bloquear valores MSS poco frecuentes: bloquea nuevos paquetes (después de aplicar las dos reglas anteriores sólo podrán ser SYN) que utilizan un valor TCP MSS que no es común. Esto ayuda a bloquear inundaciones SYN sencillas.
iptables -t mangle -A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
4.- Bloquear paquetes con flags TCP falsos: el siguiente conjunto de reglas bloquea paquetes que utilizan indicadores TCP falsos, es decir, flags TCP que los paquetes legítimos no usarían.
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP
iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
5.- Bloquear paquetes desde subredes privadas (spoofing): estas reglas bloquean los paquetes falsificados procedentes de subredes privadas (locales). En un interfaz de red público por lo general no debemos recibir paquetes IP de origen privado. Estas reglas asumen que el interfaz de loopback utiliza el espacio IP 127.0.0.0/8.
iptables -t mangle -A PREROUTING -s 224.0.0.0/3 -j DROP
iptables -t mangle -A PREROUTING -s 169.254.0.0/16 -j DROP
iptables -t mangle -A PREROUTING -s 172.16.0.0/12 -j DROP
iptables -t mangle -A PREROUTING -s 192.0.2.0/24 -j DROP
iptables -t mangle -A PREROUTING -s 192.168.0.0/16 -j DROP
iptables -t mangle -A PREROUTING -s 10.0.0.0/8 -j DROP
iptables -t mangle -A PREROUTING -s 0.0.0.0/8 -j DROP
iptables -t mangle -A PREROUTING -s 240.0.0.0/5 -j DROP
iptables -t mangle -A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP
Reglas adicionales
1.- Bloquear de ICMP: Esto descarta todos los paquetes ICMP. ICMP se utiliza sobretodo para hacer ping a un host para averiguar si todavía está vivo. Se suele utilizar para troubleshooting pero representa una vulnerabilidad que los atacantes pueden explotar, así que es recomendable bloquear todos los paquetes ICMP para mitigar Ping de la Muerte (ping flood), ICMP flood y ICMP fragmentation flood.
iptables -t mangle -A PREROUTING -p icmp -j DROP
2.- Bloquear ataques de conexiones masivas: esta regla rechaza las conexiones desde equipos que tienen más de 80 conexiones establecidas. Se puede elevar el límite ya que podría causar problemas con los clientes legítimos que establecen un gran número de conexiones TCP.
iptables -A INPUT -p tcp -m connlimit --connlimit-above 80 -j REJECT --reject-with tcp-reset
3.- Limitar las nuevas conexiones TCP que un cliente puede establecer por segundo: esto puede ser útil contra los ataques de conexión, pero no tanto contra inundaciones SYN porque suelen usar un sinfín de direcciones IP diferentes.
iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT
iptables -A INPUT -p tcp -m conntrack --ctstate NEW -j DROP
4.- Bloquear paquetes fragmentados: esto podría mitigar la inundación UDP pero la mayoría de las veces utilizan una gran cantidad de ancho de banda que agota la capacidad de la tarjeta de red, por lo que hace que esta regla sea opcional y probablemente no la más útil.
iptables -t mangle -A PREROUTING -f -j DROP
5.- Limitar los paquetes TCP RST entrantes: podría mitigar este tipo de inundaciones pero su efectividad es cuestionable.
iptables -A INPUT -p tcp --tcp-flags RST RST -m limit --limit 2/s --limit-burst 2 -j ACCEPT
iptables -A INPUT -p tcp --tcp-flags RST RST -j DROP
Mitigando SYN floods con SYNPROXY
Synproxy es un nuevo target de iptables que se ha añadido en Linux en la versión 3.12 de kernel y en la 1.4.21 de iptables. CentOS 7 lo incluye incluso antes, por defecto desde la versión 3.10 del kernel.
El propósito de synproxy es comprobar si el host que envió el paquete SYN en realidad establece una conexión TCP completa o, simplemente, no hace nada después de que enviara el paquete SYN. Si no hace nada, se descarta el paquete con un impacto mínimo en el rendimiento.
Mientras que las reglas de iptables que se proporcionan más arriba bloquean la mayoría de los ataques basados en TCP, el tipo de ataque que todavía puede evadirlos, si es lo suficientemente sofisticado, es un SYN flood. Es importante tener en cuenta que el rendimiento de las reglas siempre será mejor si nos encontramos con un cierto patrón o la firma de bloqueo, tales como la longitud del paquete (-m length), TOS (-m tos), TTL (-m ttl) o cadenas y valores hexadecimales (-m string y -m u32 para los usuarios más avanzados). Sin embargo, en algunos casos raros ésto no es posible o al menos no es fácil de conseguir. Por lo tanto, en estos casos, se puede hacer uso de synproxy.
Aquí están las reglas de iptables synproxy que ayudan a mitigar las inundaciones SYN que omiten las otras reglas:
iptables -t raw -D PREROUTING -p tcp -m tcp --syn -j CT --notrack
iptables -D INPUT -p tcp -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
iptables -D INPUT -m conntrack --ctstate INVALID -j DROP
Estas reglas se aplican a todos los puertos. Si deseas utilizar synproxy sólo en determinados puertos TCP (es recomendable también bloquear todos los puertos TCP que no estén en uso utilizando la tabla mangle y la cadena PREROUTING), puedes por ejemplo simplemente añadir --dport 80 a cada una de las reglas si quieres utilizar synproxy en el puerto 80 solamente.
Para verificar que synproxy está funcionando puedes hacer 'watch -n1 cat /proc/net/stat/synproxy'. Si los valores cambian cuando se establece una nueva conexión TCP con el puerto que utiliza el synproxy, funciona.
El conjunto de reglas IPtables completo
Si no quieres copiar y pegar cada regla expuesta en esta entrada, puedes utilizar el conjunto de reglas de a continuación para una protección básica DDoS de tu servidor Linux.
### 1: Drop invalid packets ###
/sbin/iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
### 2: Drop TCP packets that are new and are not SYN ###
/sbin/iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
### 3: Drop SYN packets with suspicious MSS value ###
/sbin/iptables -t mangle -A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
### 4: Block packets with bogus TCP flags ###
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP
/sbin/iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
### 5: Block spoofed packets ###
/sbin/iptables -t mangle -A PREROUTING -s 224.0.0.0/3 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 169.254.0.0/16 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 172.16.0.0/12 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 192.0.2.0/24 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 192.168.0.0/16 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 10.0.0.0/8 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 0.0.0.0/8 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 240.0.0.0/5 -j DROP
/sbin/iptables -t mangle -A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP
### 6: Drop ICMP (useless protocol) ###
/sbin/iptables -t mangle -A PREROUTING -p icmp -j DROP
### 7: Drop fragments in all chains ###
/sbin/iptables -t mangle -A PREROUTING -f -j DROP
### 8: Limit connections per source IP ###
/sbin/iptables -A INPUT -p tcp -m connlimit --connlimit-above 111 -j REJECT --reject-with tcp-reset
### 9: Limit RST packets ###
/sbin/iptables -A INPUT -p tcp --tcp-flags RST RST -m limit --limit 2/s --limit-burst 2 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --tcp-flags RST RST -j DROP
### 10: Limit new TCP connections per second per source IP ###
/sbin/iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT
/sbin/iptables -A INPUT -p tcp -m conntrack --ctstate NEW -j DROP
### 11: Use SYNPROXY on all ports (disables connection limiting rule) ###
#/sbin/iptables -t raw -D PREROUTING -p tcp -m tcp --syn -j CT --notrack
#/sbin/iptables -D INPUT -p tcp -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
#/sbin/iptables -D INPUT -m conntrack --ctstate INVALID -j DROP
Bonus: reglas adicionales
Las siguientes reglas de iptables son útiles para aumentar la seguridad global de un servidor Linux.
### SSH brute-force protection ###
/sbin/iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --set
/sbin/iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 -j DROP
### Protection against port scanning ###
/sbin/iptables -N port-scanning
/sbin/iptables -A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN
/sbin/iptables -A port-scanning -j DROP
Conclusión
Las guía de Constantin Oesterling muestra algunos de los métodos más eficaces para detener los ataques DDoS usando iptables. De hecho, dicen haber mitigado con éxito ataques de DDoS que han alcanzado incluso varios millones de paquetes por segundo utilizando estas reglas de iptables.
Como bien dicen, si se utiliza correctamente, iptables es una herramienta extremadamente poderosa que es capaz de bloquear diferentes tipos de ataques DDoS hacia una tarjeta de 1 GbE, e incluso casi de 10 GbE.
¡No hay que subestimar el poder de iptables!
Via: www.hackplayers.com
Protección DDoS Mediante iptables
Reviewed by Zion3R
on
19:49
Rating: