Usando la directiva “limit_conn_zone” del servidor web Nginx se puede configurar para que no permita más de N conexiones simultaneas por IP. Una conexión se cuenta solo si tiene una solicitud procesada por el servidor y el encabezado completo de la solicitud ya se ha leído.
La directiva “limit_req_zone” y sus opciones nos permitirán establecer un número de solicitudes por segundo / minuto y definir cuantas veces puede ser violada dicha directiva antes de mostrar un error 503 (burst). De no tratarse de contener posibles ataques, también sería posible realizar un delay de la tramitación de la consulta, una especia de control de carga. Lo primero que se debe hacer es definir las zonas y posteriormente aplicarlas.
Definir las zonas para limitar solicitudes y conexiones simultaneas. Por norma se configura en el fichero nginx.conf dentro del contexto “http”. Para el ejemplo se reservan 10M de memoria para gestionar dichas restricciones y se define el límite de peticiones por segundo a 1.
http { limit_conn_zone $binary_remote_addr zone=ipcon:10m; limit_req_zone $binary_remote_addr zone=reqcon:10m rate=1r/s; ...
Aplicar las zonas puede hacerse dentro de los host virtuales (contexto server) o bien en directorios (contexto location). Si se quiere se puede ofrecer una página de error o advertencia cuando se superen dichos márgenes.
server { limit_conn ipcon 5; limit_req zone=reqcon burst=5 nodelay; ... # Web de error / advertencia (Opcional) # limit_conn_status 429; # limit_req_status 429; # error_page 429 /429x.html; # location = /429x.html { # root html; # }
Con estas directivas se contienen las solicitudes a nivel de Nginx, por lo que todo lo que quede detrás del servidor web no se verá afectado (PHP, Python, Ruby, MySQL, etc).
Los bloqueos se registran dentro del fichero error.log definido en Nginx.
Estas instrucciones son independientes del servidor web en uso y pueden ser aplicadas a otros puertos / servicios. La configuración propuesta bloquea por IP si hay una media de más de 20 conexiones nuevas en 30 segundos a los puertos 80 o 443.
iptables -A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -m recent --set --name DEFAULT --rsource iptables -A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -m recent --update --seconds 30 --hitcount 20 --name DEFAULT --rsource -j DROP
Si queremos registrar en un fichero de logs los bloqueos de presuntos ataques DOS / DDOS con iptables se pueden seguir estos pasos (Debian).
Configuración de Rsyslog: crear el fichero /etc/rsyslog.d/iptables.conf con el siguiente contenido.
:msg, contains, "iptables DOS: " -/var/log/iptables & ~
touch /var/log/iptables && chown root:adm /var/log/iptables && chmod 600 /var/log/iptables
iptables -A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -m recent --set --name DEFAULT --rsource iptables -A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -m recent --update --seconds 30 --hitcount 20 --name DEFAULT --rsource --tcp-flags FIN,SYN,RST,ACK SYN -j LOG --log-prefix "iptables DOS: " iptables -A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -m recent --update --seconds 30 --hitcount 20 --name DEFAULT --rsource -j DROP
Ejemplo de logs registrados.
Sep 9 14:20:35 amazon kernel: [14158174.524119] iptables: IN=venet0 OUT= MAC= SRC=212.33.81.20 DST=205.185.116.111 LEN=60 TOS=0x00 PREC=0x00 TTL=46 ID=13835 DF PROTO=TCP SPT=30159 DPT=443 WINDOW=14600 RES=0x00 SYN URGP=0 Sep 9 14:20:35 amazon kernel: [14158174.524817] iptables: IN=venet0 OUT= MAC= SRC=212.33.81.20 DST=205.185.116.111 LEN=60 TOS=0x00 PREC=0x00 TTL=46 ID=49733 DF PROTO=TCP SPT=30161 DPT=443 WINDOW=14600 RES=0x00 SYN URGP=0 Sep 9 14:20:35 amazon kernel: [14158174.578084] iptables: IN=venet0 OUT= MAC= SRC=212.33.81.20 DST=205.185.116.111 LEN=60 TOS=0x00 PREC=0x00 TTL=47 ID=46254 DF PROTO=TCP SPT=30017 DPT=443 WINDOW=14600 RES=0x00 SYN URGP=0
NOTA: No se recomienda en producción registrar mediante logs la actividad de iptables ya que una denegación de servicio generaría mucho uso de CPU en el proceso syslog / rsyslog y elevaría las operaciones de entrada a disco.