Este blog lo cree con el fin de compartir algunos de mis avances en la creación de scritps en bash y espero que le pueda servir a alguien como también que me ayuden a mejorarlos y aprender más.
domingo, 5 de mayo de 2013
Filtrado de IPs "unknown" para Zimbra
Para iniciar la creación de un script lo que primero debemos tener es una necesidad, pues este era mi caso, yo necesitaba mejorar el filtrado de spam en el servidor de correo de la compañía... "El filtrado que trae Zimbra CS es bastante bueno, pero yo quería hacer lo mucho mejor".
Realmente lo que quería hacer era bloquear todo origen de correo que no se pudiera resolver correctamente por medio de los PTR, cuando un MTA no logra hacer una buena resolución inversa del origen de correo lo marca como "unknown", suponemos entonces que NO es un origen confiable de correo ó que el servicio de correo no esta bien configurado.
Como este no es un blog para hablar de Zimbra, postfix, ni correo en general, no entrare en detalles de la configuración, solo voy a mostrar como por medio de bashscript cree no solo la lista de IPs a bloquear, si no que también como cree otro script para limpiar los falsos positivos.
Nota: El script "spammers.sh" como yo lo llamo, esta basado en una solución propuesta por Riaan Pretorius colaborador de zimbra.com, yo solo lo adapte a mi necesidad.
Primer Script: spammers.sh
export LANG=C # Adds execution speed
LOG="/var/log/maillog"
TMP_SPAMMERS="/opt/zimbra/conf/postfix_rbl_ip_spammers.tmp"
TMP_LOG1="/opt/zimbra/conf/postfix_rbl_ip_spammers.log1"
TMP_LOG2="/opt/zimbra/conf/postfix_rbl_ip_spammers.log2"
SPAMMERS="/opt/zimbra/conf/postfix_rbl_ip_spammers"
WHITELIST="/opt/zimbra/conf/postfix_rbl_ip_whitelist"
awk '/ connect from/ {print $8}' $LOG | \
grep unknown | \
awk '{print $1}' | \
cut -d[ -f2 | cut -d] -f1 | \
while read ip ; do
host $ip > /dev/null 2>&1;\
if [ $? -ne 0 ] ; echo "$ip REJECT" >> $TMP_SPAMMERS; then
echo "$ip";
fi;
done
cat $TMP_SPAMMERS | sort | uniq | grep -v -f $WHITELIST > $TMP_LOG1
cat $TMP_LOG1 $SPAMMERS > $TMP_LOG2
cat $TMP_LOG2 | sort | uniq | grep -v -f $WHITELIST > $SPAMMERS
rm -f $TMP_LOG1 $TMP_LOG2 $TMP_SPAMMERS
su - -c "postmap $SPAMMERS" zimbra
su - -c "zmmtactl restart" zimbra
En este script se hace uso de variables, awk (pattern scanning and processing language), grep (print lines matching a pattern), sort (sort lines of text files), uniq (report or omit repeated lines) y cut (remove sections from each line of files) para obtener la IP a bloquear, todo esto por medio de un bucle con "while". Luego de determinar la IP procedemos a registrarla en los diferentes archivos de configuración.
Este proceso tienen una falencia y es que muchos servidores de correo no están bien configurados o por lo menos sus registros DNS, así que llegamos al punto de los falsos positivos. Aquí era necesario tener un procedimiento para limpiar de los db de postfix las IPs que eran orígenes correctos y agregarlos a listas blancas, así empece con "whitelist.sh" en colaboración con +Víctor Daniel .
Segundo Script: whitelist.sh
# Usage: whitelist [options]
#
# Options:
# <arg> DOMINIO ó MAIL
# --help This help message
EXPECTED_MIN_ARGS=1
EXPECTED_MAX_ARGS=1
E_BADARGS=65
E_NOROOT=1
BASE_NAME=`basename $0`
if [[ $# -gt $EXPECTED_MAX_ARGS ]] ||
[[ $# -lt $EXPECTED_MIN_ARGS ]] ||
[[ $1 == "--help" ]] ; then
echo "Usage: $BASE_NAME <arg>" 1>&2
echo "Usage: $BASE_NAME --help" 1>&2
exit $E_BADARGS
fi
if [ "$(id -u)" != "0" ]; then
echo "$BASE_NAME: This script must be run as root." 1>&2
exit $E_NOROOT
fi
LOCK_FILE="/var/lock/whitelist"
ULIMIT_N=`ulimit -n`
let "FLOCK_FD = ULIMIT_N - 1"
START_DATE=`date`
ERROR_EXIT="1"
(
eval "exec $FLOCK_FD<> $LOCK_FILE"
if flock -n $FLOCK_FD ; then
# flock START
Slog="/var/log/maillog"
PostPath="/opt/zimbra/conf"
DBSpammers="postfix_rbl_ip_spammers.db"
FSpammers="postfix_rbl_ip_spammers"
FWhitelist="postfix_rbl_ip_whitelist"
IP=`grep $1 $Slog | grep -m 1 -E 'rejected: Access denied' | awk '{print $10}' | cut -d[ -f2 | cut -d] -f1`
# 1. buscar bloqueado - recibe parametro "arg" (email ó dominio).
# Ejemplo de log:
# Mar 8 06:22:32 mail postfix/smtpd[12196]: NOQUEUE: reject:
# RCPT from unknown[201.230.203.167]: 554 5.7.1 <unknown[201.230.203.167]>:
# Client host rejected: Access denied; from=<diplomadosprogramas8@yahoo.es>
# to=<info@summan.com> proto=SMTP helo=<192.168.1.20>
function SearchArgument(){
if [[ $IP != "" ]]; then
echo $IP
return 0
else
echo "Argumento no encontrado!"
fi
return 1
}
# 2. busca la ip correspondiente al domino encontrado en la base de datos
# de spammers. "/opt/zimbra/conf/postfix_rbl_ip_spammers", y la borra.
function DeleteIPFSpammers() {
sed '/^'$IP'/d' $PostPath/$FSpammers > $PostPath/fspam.tmp
cat $PostPath/fspam.tmp > $PostPath/$FSpammers
rm -f $PostPath/fspam.tmp
}
# 3. agrega la ip en la base de datos postfix_rbl_whitelist.
function AddIPWhitelist() {
echo $IP >> $PostPath/$FWhitelist
}
# 4. regenera la base de datos de spammers
# "postmap /opt/zimbra/conf/postfix_rbl_ip_spammers".
function ReloadDBSpammers() {
su - zimbra -c "rm -f $PostPath/$DBSpammers"
su - zimbra -c "postmap $PostPath/$FSpammers"
}
# 5. recargar la base de datos "zmmtactl restart"
function RestartMta() {
su - zimbra -c "zmmtactl restart"
}
function DeleteLock() {
rm -f $LOCK_FILE
}
if SearchArgument ; then
echo "Procesando dominio $1 con la IP: $IP"
DeleteIPFSpammers
AddIPWhitelist
ReloadDBSpammers
RestartMta
DeleteLock
else
echo "Argumento $1 no encontrado!"
fi
# flock END
else
echo "$BASE_NAME: Another instance is currently running."
fi
)
Código fuente: spammers.sh whitelist.sh
En este script utilice un poco de expresiones regulares, funciones como le llama mi compañero +Víctor Daniel "El segundo nivel de bash", condicionales etc. La forma de utilizarlo es ejecutando y entregando el argumento a utilizar, como por ejemplo dominio ó email.
Espero que a alguien le sirva estos scripts o le ayuden a construir otros, si tiene alguna sugerencia de como mejorarlos por favor dejen sus comentarios.
Ubicación:
Medellín, Antioquia, Colombia
Suscribirse a:
Comentarios de la entrada (Atom)
No hay comentarios.:
Publicar un comentario