Combatiendo el SPAM - ataques de diccionario
El spam es uno de los males que está plagando la Internet. Si tienes tu propio servidor de e-mail para uso personal o administras uno en el trabajo, lidiar con ellos es un verdadero dolor de cabezas. Existen varios tipos de ataques, en este artículo muestro como combatir y bloquear a los spammers que realizan el ataque de diccionario.
El ataque de diccionario, es el ataque más tonto que un pseudo-spammer puede hacer, y ya que es un ataque tonto, tiene una solución bastante sencilla. El ataque consiste en lo siguiente.
- Toman un e-mail real (Ejemplo: crodas@foo-bar.com)
- Luego se le agregan letras randomicas al inicio al final
La solución se simple, hay que seleccionar todos lo mails que fueron enviados a destinatarios no existentes, luego agrupar por IP, y comparar a ver si los destinatarios son similares, si son es un ataque de diccionario. Este script funciona con el output del Log del sendmail.
#!/usr/bin/php -q
<?php
# Dedicado para los que piensan que PHP es solo para páginas webs
# y para las personas tontas que comparan un framework cualquiera
# con un lenguaje de programación.
#
if ( isset($argv[1]) && $argv[1] == "--debug")
define("DEBUG",1);
function x_readline()
{
return trim(fgets(STDIN));
}
function asum($x,$y)
{
$x += $y;
return $x;
}
$ip=array();
$dst=array();
while ($line=x_readline())
{
$line = strtolower($line);
preg_match("/\]\: ([a-zA-Z0-9]+):.*from\=.*relay=.*\[([0-9\.]+)\]/i",$line,$result);
if ( count($result) > 0) $ip[$result[1]] = $result[2];
if ( strpos($line,"user unknown") !== false )
{
preg_match("/]\: ([a-zA-Z0-9]+):.*to=<?([^\@]+)>?/i",$line,$result);
if ( count($result) > 0 && isset($ip[$result[1]]) )
$dst[ $ip[$result[1]] ][] = $result[2];
}
}
$result=array();
#ahora a buscar los posibles candidatos
foreach($dst as $ip => $mail)
{
$tmp=array();
$t = count($mail);
if ( $t < 5) continue; /* una regla mia, un mínimo de 5 mails fallidos para el control */
for($i=0; $i < $t-1; $i++)
{
$threshold = (strlen($mail[$i]) + strlen($mail[$i]))/2 * 0.3;
$weight = levenshtein($mail[$i],$mail[$i+1]);
$tmp[] = $weight < $threshold && $weight!=0 ? 1 : -1;
}
$result[$ip] = array_reduce($tmp,"asum");
}
foreach($result as $ip => $weight)
{
if ( $weight < 0) continue;
print "$ip\n";
if (defined("DEBUG")) print_r($dst[$ip]);
}
?>
El script devuelve una lista de IPs que realizan ataques de SPAM. Esta lista es suficiente para poder combatirlo, ejemplo ejecutar periodicamente (crontab) a cada 3 (es un ejemplo) horas y agregar en la lista de bloqueos del sendmail. Aquí un script bash que hace el trabajo “duro” de darle forma a el “output” del php.
#!/bin/bash
#configuracion
LOG=/var/log/maillog
SENDMAIL=/etc/mail/
DB=/etc/mail/access
DATE=`date`
TEXT="550 We don't accept mail from spammers # Auto added $DATE"
#el programa en sí
if [ `whoami` != "root" ]
then
echo "Only root can run this script"
exit
fi
find_in_access() {
VALUE=$1
local ACCESSIP
for ACCESSIP in $( cat $DB | awk '{print $1}' );
do
if [ "$ACCESSIP" = "$VALUE" ];
then
return 0
fi
done
return 1
}
for SPAMMER in `cat $LOG | php php_dict_attack.php`
do
find_in_access $IP
if [ $? -eq 1 ];
then
echo "$SPAMMER $TEXT" >> $DB
fi
done
cd $SENDMAIL
make








mmmm.. medio que al Qmail no le gusta el script
con tu permiso voy a tocar tu script man
por cierto muy bueno
Claro que sí, todos mis códigos en mi blog son libres… “Public domain”.
Y la verdad que no creo que funcione con el Qmail, porque yo me base en los logs del sendmail, pero podes enviarme el log del Qmail si queres ( tiene que ser relativamente grande ~20M) a mi correo electrónico, así puedo divertirme este fin de semana.
Hola:
Llegaste a modificar el script para su uso con Qmail?.
Gracias.
Nunca tuve la necesidad de hacerlo, aunque no sería muy complicado.