Etiquetas
Hace un tiempo escribí un pequeño apunte para detectar bots agresivos. Pero con la cantidad de bots que hay por el Menéame, y la cantidad de gente que «juega» haciendo varias decenas de conexiones por segundo, ese script era ya prácticamente inservible. En este tiempo estuve probando varios módulos del Apache. El mod_evasive del Apache –el más usado, no entiendo por qué– no sirve para nada ya que sólo controla las conexiones para un sólo proceso –en el Menéame estamos en unos 150-200 procesos concurrente en cada uno de los dos servidores–.
Al final, probando varias opciones de las iptables, la que más me gustó es la del módulo «recent». Funciona muy bien, no consume casi nada y tampoco requiere el módulo conntrack –de nuevo, es muy «caro» en el Menéame por la cantidad de conexiones–
Esto es lo que tengo en reglas de las iptables en Menéame:
#Connection throttling
IF=eth_la_que_corresponda
...
iptables -i $IF -I INPUT -p tcp --syn -m recent --set
iptables -i $IF -I INPUT -p tcp --syn -m recent --update --seconds 10 --hitcount 30 -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). El valor de 30 es un valor que encontré iba muy bien para el Menéame. Podéis comenzar con eso y luego ajustarla.
Para poder mirar el número de conexiones simultáneas de cada IP hice un pequeño script en Python que las muestra ordenadas:
#! /usr/bin/env python
import re
ips = {}
r = re.compile(r’src=([\d\.]+).+ oldest_pkt: (\d)’)
f = open(«/proc/net/ipt_recent/DEFAULT»)
for line in f.readlines():
g = r.match(line).groups()
if int(g[1]) > 4:
# Store only in it has more than 4 conns.
ips[g[0]] = int(g[1])
tuples = ips.items()
tuples.sort(lambda (k1,v1),(k2,v2):cmp(v2,v1))
for ip, counter in tuples:
print ‘%-16s %-8d’ % (ip, counter)
En cada servidor del Menéame los máximos que suelo observar no superan las 8 ó 9 conexiones. Por ejemplo:
$ recent-ip.py
83.41.13.38 9
88.22.14.52 9
84.78.63.183 9
85.219.45.29 9
83.33.104.1 9
62.43.161.95 8
62.43.51.161 8
85.57.206.54 7
213.60.230.179 7
88.14.107.53 7
85.60.43.31 7
85.85.25.68 7
88.11.242.144 7
84.126.172.191 7
84.127.93.44 6
83.138.223.248 6
212.225.182.55 6
217.127.202.163 6
84.123.119.212 5
¿Como encuentras las constantes que te van bién para tus scripts? ¿Lo calculas previamente? ¿Lo calculas a partir de datos experimentales? ¿o simplemente no lo calculas y lo encuentras por ensayo y error? (No intento ser sarcástico ni borde, tengo curiosidad :p )
Wenaaaass! Que tal, gente!? Tengo una dudilla… cuantas noticias se pueden enviar al dia con una misma dirección de blog? No es por hacer Spam ni nada de eso XD. Gracias anticipadas para los que me respondan ;).
Muy interesante, muchas gracias por compartir esto. Me va a venir muy bien con nginx, que no tiene sustituo de mod_evasive hasta la fecha.
Sabes si el googlebot se resiente con estas reglas?
> Sabes si el googlebot se resiente con estas reglas?
Con los valores que puse, todavía no ví que tuviese ningún problema.
Por cierto, se han colado algunos guiones simples donde serían dobles guiones (ej –set) 😉
#5, sí, es el filtro de WP 😦
¿gallir puedes explicar un poco lo del conntrack? Yo llevo usandolo desde siempre en una web con mucho tráfico (3 servidores web) e ignoraba que fuera un lastre
En concreto utilizo varias reglas de este estilo:
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
#7 / #8 Alavaro, no es que el conntrack sea un lastre, pero necesita guardar el estado de cada conexión, para eso reserva memoria que depende de la cantidad de RAM que tengas.
Nosotros usábamos el conntrack, hasta que hubo los ataques DDoS. Aunque podíamos filtrar la gran mayoría de paquetes a nivel del proveedor, aún nos llegaban muchos que no llegaban a saturar la línea, pero sí a la tabla del conntrack porque lo que deba problemas para las nuevas conexiones. Las deshabilité e iba mejor. Así que desde ese momento no las usamos.
Para mostrar el código te recomiendo el plugin Wp-Codebox de WordPress, se puede ver en http://wordpress.org/extend/plugins/wp-codebox/ .
Yo tenía los mismos problemas en mi blog con el código (lo de las comillas), pero ahora se ve bastante bien (y respeta los saltos de línea, hace resaltado de sintaxis(para un montón de lenguajes), muestra los números de línea (si quieres, tiene bastantes opciones)… no sé, realmente va muy bien.
RE:#9
Gracias por la explicación, la verdad es que de ram no tengo problemas en los servidores web, aunque tuve que aumentar ip_conntrack_max pq se desbordaba la tabla. Quizá pruebe a cambiarlo en uno de los servidores a ver si se nota mejoría, ¿pero qué reglas usaste como alternativa en su momento?
#10
Andreu, gracias, pero mi blog está en WordPress.com, por lo que no tengo posibilidad de instalar plugins 😦
#11
> ¿pero qué reglas usaste como alternativa en su momento?
Como se hacía antes de que existiese el conntrack, con los SYN:
iptables -i $IF -A INPUT -p TCP –dport 80 -j ACCEPT
iptables -A INPUT -i $IF -p ICMP -j ACCEPT
iptables -A INPUT -i $IF -p TCP –syn -j DROP
Aunque ya es ser demasiado tiquismiquis, una apreciación: en la parte de la ordenación de las tuplas, es mejor usar el parámetro key= de sort, en lugar de cmp=:
import operator
tuples.sort(key=operator.itemgetter(1), reverse=True)
Más información en:
http://wiki.python.org/moin/PythonSpeed
Pero bueno, siendo un script tampoco importan demasiado estos detalles.
Da gusto que gente con notoriedad, por el motivo que sea (en este caso por ser creador y administrador de meneame), no tenga ningun problema en comentar y enseñar que cosas hace, que descubre y que le gusta.
Muchas gracias gallir.
Como siempre, un post con nada de desperdicio, Ricardo..
Saludos!
Y que pasaría si por ejemplo un proxy (ej. de una Universidad), se conecta con 15 usuarios en simultaneo a meneame?
Saludos
Pingback: El Blog de Loretahur
Hola Ricardo, vengo siguiendo tu blog, lo conocí por un link de Martin ‘apellidodificildeescribir’ Varsavsky ;).
Me llevé flor de sorpresa, grata, al ver que tus scripts estaban hechos en python.
Te invito, y a los que lean ésto, a pasar por la dirección que está en mi link y que te unas a la lista de python argentina, nos vamos a sentir complacidos de tenerte y que puedas aportar tus conocimientos. Descontá desde ya que cualquier duda que envíes se intentará resolver enseguida. Enlistate, mas de uno se llevó flor de sorpresa del movimiento que tiene, y de las ganas de los pythoneros de juntarse y tomar cervezas!
Saludos desde Paraná, Matías
Pingback: Servidores baratos, seguros y eficientes. | César D. Rodas