En el artículo Ataquest TCP Comunes expliqué algunos de los ataques más comunes, en este post explico como configurar linux para protegerse de esos ataques, y alguno más.

Ataque SYN Flood

SYN Cookies

Linux implementa un metodo llamado SYN Cookies para la protección contra este ataque, la técnica se consiste en elegir el numero de secuencia del paquete SYN+ACK de manera que el servidor no necesite guardar el estado de la conexión, y pueda usas el numero de secuencia de la respuesta ACK del cliente, para reconstruir la entrada en la tabla de conexiones.

Desde la versión del kernel 2.6.33, donde el sistema se modificó para soportar window scaling, esta opción está activada por defecto. Puedes comprobarlo usando:

cat /proc/sys/net/ipv4/tcp_syncookies
sysctl -n net.ipv4.tcp_syncookies

Si no está activado, puedes editar el archivo de configuración /etc/sysctl.conf y añadir:

net.ipv4.tcp_syncookies = 1

Despues de salvar el archivo, puedes activarlo usando:

sudo sysctl -p

Un servidor con tcp_syncookies activado se comporta de forma normal, hasta que la cola de conexiones pendientes está llena, a partir de ese momento comienza a enviar SYN cookies hasta que la congestión se alivie.

Si el servidor esta soportando mucha carga, puede ocurrir que tcp_syncookies se active y cierre conexiones legítimas. En esos casos es importante tener en cuenta que aunque puede ser un alivio temporal, SYN Cookies está diseñado para proteger el sistema de ataques SYN Flood, y que usarlo para solucionar problemas de congestión reiterados es contraproducente.

Iptables

La segunda opción es usar iptables para limitar el número de paquetes SYN, que son aceptados para cada dirección IP en un intervalo de tiempo. Para ello usamos el patch recent de iptables.

iptables -A INPUT -p tcp -m state --state NEW -m recent --set --name sattack
iptables -A INPUT -p tcp -m state --state NEW -m recent --rcheck --name sattack --seconds 60 --hitcount 20 -j DROP

La primera regla añade la dirección de origen de los paquetes SYN a una tabla llamada sattack, la segunda regla comprueba si en los últimos 60 segundos ha habido más de 20 paquetes SYN, desde la dirección de origen del paquete, de ser así el paquete es descartado.

En caso de que se esté usando IP Spoofing junto a SYN Flood, la única opción restante es intenta detectar alguna particularidad de la cabecera, que permita diferenciar los paquetes del atacante del resto, por ejemplo si MSS no tiene un valor correcto:

iptables -t mangle -I PREROUTING -p tcp -m tcp --dport 80 -m state --state NEW -m tcpmss ! --mss 536:65535 -j DROP

Estas reglas pueden interferir con proxies, y con clientes detrás de un NAT, así que no es recomendable usarlas en un sistema que no esté bajo ataque.

TCP Scans

El sistema más sencillo y general para detectar/detener un scan, es usar puertos cerrados como centinelas, de manera que si detectamos un paquete que llega a alguno de esos puertos, podamos asumir que el paquete es parte de un scan, y bloquear el acceso de la ip de origen temporalmente.

Es probable que el scan se centre únicamente en los puertos de servicios más comunes, por lo que es recomendable usar como centinelas puertos reservados por algún servicio, pero que no estén abiertos en ese servidor, por ejemplo SMTP(25), DNS(53), NETBIOS(139). Ademas de esos puertos deberemos añadir cuantos sean necesarios, para intentar detectar un scan, antes de que el atacante consiga escanear un puerto abierto.

Por ejemplo si se ha cambiado el puerto por defecto de ssh es muy recomendable añadir el puerto 22. Ten cuidado de NO usar como centinela un puerto abierto.

# Añadimos los puertos ftp, telnet, smtp, netbios-ssn
iptables -A INPUT -p tcp --dport 21   -m recent --name portscan --set
iptables -A INPUT -p tcp --dport 23   -m recent --name portscan --set
iptables -A INPUT -p tcp --dport 25   -m recent --name portscan --set
iptables -A INPUT -p tcp --dport 139  -m recent --name portscan --set

# Usar como centinelas el puerto ssh y su substituto más común
iptables -A INPUT -p tcp --dport 22   -m recent --name portscan --set
iptables -A INPUT -p tcp --dport 2222 -m recent --name portscan --set

# Bloquear IP por 12 horas si el paquete esta en la tabla portscan
iptables -A INPUT -m recent --name portscan --rchek --seconds 43200 -j DROP

Algunos tipos de scan, usan paquetes construidos de manera que son fáciles de diferenciar del tráfico legítimo, en ese caso es posible descartarlos directamente:

# XMAS Scan
iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP

# NULL Scan
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

# SYN/RST Scan
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

# SYN/FIN Scan
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP

IP Spoofing

Ip spoofing consiste en falsificar la dirección de origen de los paquetes, en conjunción con algún ataque (pej SYN Flood), hace más dificil detectar su origen, complica el filtrado de los paquetes, y según la configuración pueden permitir saltarse algún firewall.

La única posibilidad es eliminar los paquetes que lleguen a un interface de red, con una dirección de origen que no esten en el rango de direcciones validas para ese interface:

iptables -A INPUT -i eth0 -s 0.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP
iptables -A INPUT -i eth0 -s 224.0.0.0/3 -j DROP

Tambien se puede activar la verificación de direcciones de origen del kernel, que proporciona protección anti spoofing. Para comprobar si está activo:

sysctl -n net.ipv4.conf.all.rp_filter

Si no lo esta edita /etc/sysctl.conf y añade:

# Proteccion contra IP Spoofing
net.ipv4.conf.all.rp_filter = 1

Ataque Smurf

Consiste en enviar paquetes de broadcast ICMP con la dirección de origen falseada, de manera que la respuesta al paquete por parte de todos los equipos en la red, genere una denegación de servicio en el equipo cuya direccion fue suplantada en los paquetes.

La solución es no responde a los paquetes ICMP de broadcast. El kernel se puede configurar para que ignore estos paquetes, así que iptables no son necesarias. Si por defecto no esta activado, añade a /etc/sysctl.cof:

# Ignorar peticiones echo broadcast para evitar ataque smurf
net.ipv4.icmp_echo_ignore_broadcasts = 1

Hoy en día es un ataque poco usado.

Ver comentarios


Acabo de configurar un VPS como servidor web, y estas son las reglas iptables con las que empiezo todo firewall, a partir de aquí voy añadiendo todos los servicios adicionales que se necesiten.

#!/bin/bash

# Limpiar todas las reglas.
iptables -F
iptables -t nat -F
iptables -t mangle -F

# Creamos tabla para reglas de seguridad eth0
iptables -N security_eth0
iptables -F security_eth0
iptables -A INPUT -i eth0 -j security_eth0

# Admitimos todos los paquetes en interface loopback.
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Aceptamos todos los paquetes de conexiones ya establecidas
iptables -A INPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Permitir todas conexiones HTTP entrantes
iptables -A INPUT  -i eth0 -p tcp --dport 80 -m state --state NEW -j ACCEPT

# Permitir todas conexiones SSH entrantes
iptables -A INPUT  -i eth0 -p tcp --dport 22 -m state --state NEW -j ACCEPT

# Permitir conexiones SSH salientes (DESACTIVADO)
# iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW -j ACCEPT

# Permitir icmp (ping,....)
iptables -A INPUT  -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT

# Permitir acceso DNS saliente
iptables -A OUTPUT -p udp -o eth0 --dport 53 --sport 1024:65535 -j ACCEPT
iptables -A INPUT  -p udp -i eth0 --sport 53 --dport 1024:65535 -j ACCEPT

# Por defecto descartamos los paquetes no aceptados explicitamente
iptables -P INPUT   DROP
iptables -P FORWARD DROP
iptables -P OUTPUT  DROP


#
# Medidas de seguridad para paquetes entrantes eth0
#

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

# Descomentar la siguiente linea para desactivar la tabla security_eth0
# iptables -A security_eth0 -j RETURN

# Ignoramos paquetes nuevos que no tengan flag SYN activado
iptables -A security_eth0 -p tcp ! --syn -m state --state NEW -j DROP

# Ignoramos paquetes invalidos
iptables -A security_eth0 -m state --state INVALID -j DROP

# Descartar paqueter fragmentados
iptables -A security_eth0 -f -j DROP

# Descartar paquetes XMAS
iptables -A security_eth0 -p tcp --tcp-flags ALL ALL -j DROP

# Descartart paquetes NULL
iptables -A security_eth0 -p tcp --tcp-flags ALL NONE -j DROP

# Descartar ip falsas (spoofing)
iptables -A security_eth0 -s 0.0.0.0/8 -j DROP
iptables -A security_eth0 -s 127.0.0.0/8 -j DROP
iptables -A security_eth0 -s 10.0.0.0/8 -j DROP
iptables -A security_eth0 -s 172.16.0.0/12 -j DROP
iptables -A security_eth0 -s 192.168.0.0/16 -j DROP
iptables -A security_eth0 -s 224.0.0.0/3 -j DROP

Descargar

Este script bloquea todo tráfico entrante y saliente, excepto conexiones entrantes a los puertos html y ssh, el protocolo icmp, y las consultas DNS salientes. También crea la tabla security_eth0, donde se filtran todos los paquetes entrantes por eth0, para realizar algunos chequeos de seguridad.

Si no quieres añadir el script directamente a init.d, puedes introducir las reglas manualmente en el shell, y luego usar iptables-persistent para salvarlas.

$ sudo apt-get install iptables-persistent

Durante la instalación preguntará si quieres salvar las reglas de iptables, responde si, y serán salvadas en /etc/iptables/rules.v4 para ipv4, y /etc/iptables/rules.v6 para ipv6. Por último iniciamos el servicio:

$ sudo service iptables-persistent start

Ver comentarios