Control de UCE (y malware) en Postfix (II)

Unos meses después de escribir la primera parte de un artículo sobre control de correo no deseado utilizando Postfix, tuve que diseñar e implementar un servicio integral de control de correo no deseado y malware en un entorno corporativo. Previamente se utilizaba una solución propietaria que funcionaba bien aunque había mucha incertidumbre en la gestión de rebotes, listas negras y mensajes denegados.

Esta solución está implementada en el MX de un dominio para el que se estiman entre 400 y 500 mil conexiones por día, con un 95% de incidencia de correo no deseado o malware. El plan inicial involucra hacer mucha denegación de correos a nivel SMTP, utilizar listas grises y sólo hacer el escaneo de contenido (con un filtro de contenidos y no con spamc, por ejemplo) al final de la depuración.

Componentes

  • Postfix, un MTA seguro, robusto y muy fácil de mantener. Lo utiliza mucha gente y hay bastante documentación, escrita por el propio Wietse, y muchos usuarios hispanoparlantes diespuestos a ayudar.
  • Postgrey, una implementación de greylists para Postfix que utiliza Berkeley DB.
  • SpamAssassin, el filtro anti-spam de código abierto más popular y probablemente el más avanzado también.
  • ClamAV, un escáner anti-virus con firmas actualizadas frecuentemente y capacidad de trabajar con archivadores.
  • Amavis, un filtro de contenidos escrito en Perl que puede ser visto como un wrapper sobre filtros anti-spam (i.e., SpamAssassin) y anti-virus (ClamAV et. al.)
  • MailZu, un gestor de la cuarentena de Amavis (vía SQL) que permite la autenticación con directorios LDAP, y permite que un usuario auto-gestione su cuarentena.

Configuración

Amavis requiere configurar dos servicios en master.cf, uno que será el filtro de contenidos (todos los correos se enviarán allí excepto si las restricciones tienen un permit antes del reject predeterminado) y otro que servirá para reinyectar correos a Postfix luego de que Amavis los procese, sin pasar de nuevo por las verificaciones.

amavis-smtp     unix    -       -       y       -       10      smtp
  -o smtp_data_done_timeout=1200s -o smtp_never_send_ehlo=yes -o disable_dns_lookups=yes

localhost:10025 inet    n       -       y       -       -       smtpd
  -o content_filter= -o local_recipient_maps= -o smtpd_helo_restrictions=
  -o smtpd_client_restrictions= -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks=127.0.0.0/8

En este caso se crea un servicio SMTP llamado amavis-smtp, cuyo límite de procesos (maxproc) debe ser igual o menor al número de procesos amavisd que se estén ejecutando. Muchas de las configuraciones y recetas que se consiguen en Internet dejan el servicio amavis-smtp con solo dos procesos, lo que convierte al filtro de contenido en un cuello de botella, y en un servidor muy cargado provocará que los correos se encolen catastróficamente.

El servicio de reinyección de correos a Postfix tiene un límite predeterminado (100 procesos) y no tiene restricciones ya que no se va a gastar en volver a hacer verificaciones SMTP que se hicieron al recibir el correo por primera vez. Por seguridad, también se restringe el acceso a este servicio solo a localhost. Luego de reiniciar Postfix, telnet a ambos puertos con Amavis arriba ayuda a entender la situación.

Postfix recibirá los correos por el tradicional puerto TCP 25 y aplicará sus propias restricciones (incluyendo el servicio de listas grises, que en el caso de postgrey escucha en el puerto TCP 60000) para luego entregar el correo vía SMTP a Amavis por el puerto 10024.

smtpd_recipient_restrictions =
...
check_policy_service inet:127.0.0.1:60000
...

content_filter = amavis-smtp:localhost:10024

Amavis procesa el correo según su propia configuración: usa SpamAssassin y ClamAV; en Debian es muy fácil activar ClamAV en el archivo 15-av_scanners del directorio /etc/amavis/conf.d. También queremos tener ClamAV y SpamAssassin actualizados usando freshclam y sa-update, y utilizando Debian siempre es conveniente instalar desde el servicio volatile.

La configuración local debe ir en el archivo 50-user. Aquí nos interesan varios valores para configurar el comportamiento del filtro, entre ellos el nombre del dominio, el número de procesos, el mecanismo de reinyección, las políticas predeterminadas, el tamaño máximo del correo y las puntuaciones requeridas para actuar sobre un correo.

$mydomain = 'usd.sl.com.ve';

$max_servers=10;

$forward_method = 'smtp:127.0.0.1:10025'; 

$final_virus_destiny = D_DISCARD;
$final_spam_destiny = D_DISCARD;

$sa_mail_body_size_limit = 64*1024;

$sa_tag_level_deflt = 1.0;
$sa_tag2_level_deflt = 5.0;
$sa_kill_level_deflt = $sa_tag2_level_deflt;

De acuerdo a este snippet, Amavis descartará (es decir, guardará en cuarentena sin mayor notificación al remitente o al destinatario) aquellos correos que detecte como virus y spam. Reinyectará correos al puerto 10025 usando SMTP, correrá 10 procesos y solo utilizará SpamAssassin para revisar correos de menos de 64 KB, previendo que los spammers no suelen enviar UCE de gran tamaño.

También es importante saber que Amavis tiene dos umbrales de trabajo con SpamAssassin, el primero es la puntuación mínima que debe recibir el correo para escribir las cabeceras del anti-spam y el segundo es la puntuación mínima que debe tener el correo para que sea marcado como spam. El primero puede ser bajado sin problemas a un valor negativo si se desean cabeceras informativas en todos los correos.

Teniendo filtros de contenido de alto rendimiento como amavisd-new que pueden manejar staging de correos, pareciera lógico delegar las DNSBL al filtro de contenido y no hacerlo en el MTA, como recomendé en la primera parte. Esto evita gastar recursos en correo que puedes denegar con restricciones SMTP o con un breve análisis de contenidos.

Amavis puede reportar a bases de datos remotas que luego pueden ser utilizadas por aplicaciones como MailZu para delegar la gestión de cuarentena al usuario. Sin embargo, el reporte SQL de Amavis puede ser un cuello de botella, así que solo lo recomendaría si Amavis y Postfix están en máquinas distintas y el uso de recursos de Amavis no provocará un colapso de Postfix.

Estos pedazos de configuración no están de ninguna manera completos. Son referencias para ayudar al administrador de Postfix a implementar una solución de control de correo funcional. Es necesario ajustar todos estos valores dependiendo de los requerimientos de la organización, ya que no hay una solución única para todos los casos (AFAICT, Debian usa 4.0, CANTV usa 3.0 y CNTI usa 2.0)

¿Y luego?

Hay más tecnologías que explorar. Una de ellas es la denegación de correos a bloques de direcciones correspondientes a usuarios finales (S25R, en mi opinión demasiado injusto, pero que puede acercar teóricamente a una solución de 99.9% de eficiencia) y SPF, que ya había comentado en el primer post sobre el tema. En SpamAssassin hay algunas cosas más que tocar, sobre todo CRM114. SA, sin embargo, requiere mucho mantenimiento en comparación con el resto de las herramientas presentadas en esta solución.

Para poner en funcionamiento esta solución eché mano de la documentación de Postfix y la de Amavis, que está disponible en Internet, pero hay un documento en castellano publicado por CERT-UNAM que puede ayudar a entender muchas cosas sobre Postfix: Instalación de Postfix, Amavis y Spamassassin.

Performance

Con 2 GB. de RAM, el equipo puede levantar unos 25 procesos del filtro de contenidos, los 100 procesos SMTP de Postfix, postgrey, clamd y las herramientas de gestión del servicio. Note que Martinec afirma que tener más de 10 procesos de Amavis corriendo es overkill. Normalmente, incluso este servidor no tiene más de 10 correos en las colas incoming o active al mismo tiempo, y si los tuviera no quisiéramos agotar la memoria del equipo atendiendo más correos paralelamente cuando se puede escribir en disco y atender la cola más tarde.

Hay dos cuellos de botellas en esta solución, y ninguno es Postfix, o al menos no comunmente. El primero es la red, por un mal diseño de la conectividad cuando se instaló el servicio; lo recomendable es tener un canal dedicado para el ISP y otro para la red local. Es esencial tener un DNS-caché en el mismo equipo, y particularmente no me parece conveniente utilizar OpenDNS como forwarder (este servicio siempre devuelve un registro A aunque no exista el nombre)

También pueden ayudar unas reglas de iptables que limiten la tasa de conexiones por unidad de tiempo, quizás algo como (YMMV):

iptables -I INPUT -p tcp --dport 25 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 25 -m state --state NEW -m recent --update --seconds 60 --hitcount 10 -j DROP

El otro cuello de botella es el disco duro. Si bien se evita que Postfix trabaje con sus colas (normalmente este equipo puede manejar entre 200 y 500 correos en deferred) no hay forma de evitar (excepto eliminando los correos) que Amavis escriba varios miles de correos al día a la cuarentena en disco (peor aún, con reportes SQL a un equipo remoto) en el peor de los casos hasta 10 a la vez. Discos rápidos o RAID 0 podrían ayudar.

Outcome

Algunos números obtenidos en un período de 24 horas: de 430 mil conexiones SMTP recibidas por el servidor, unas 200 mil (~47%) son eliminadas por listas grises (es decir, nunca vuelven = spam), y otras 200 mil son eliminadas por Postfix (usuarios no existentes o dominio del remitente inexistente = spam o correo problemático) por lo cual solo 30 mil correos diarios se entregan a Amavis para su verificación con ClamAV y SpamAssassin.

Unos 4 mil correos al día son descartados por Amavis, y solo 26 mil correos (~6%) son distribuidos entre los MTA internos o hacia MXs externos. De estos, realmente muy pocos son UCE (en quince días unas cinco incidencias reportadas) y muy pocos son falsos positivos (cero incidencias reportadas) con ningún reporte de virus hasta el momento.

Control de UCE en Postfix

Hay tres formas de combatir el correo no deseado que pasa a través de un MTA Postfix. Una daña las uñas (y aún se recibe mucho spam), y las otras no tanto. El primer servidor de correo que instalé con controles de UCE corría Sendmail y utilizaba SpamAssassin a través de procmail, probablemente la forma más sencilla de implementar un control de spam en la actualidad. Pasé casi dos años acomodando detalles en SA, incluyendo los valores de las reglas, las listas blancas y negras y pare usted de contar, y pronto se da uno cuenta de que está invirtiendo demasiados recursos en evaluar si un correo recibido es legítimo o no.

Allí entra el segundo método, revisar un correo antes de recibirlo. Casi todo MTA Postfix que venga en una distribución de Linux ya trae algo de eso, para evitar que el MTA sea usado como un relay abierto. Pero siempre se puede ir más allá, utilizando listas negras que otros mantienen. Si tu objetivo en la vida no es mantener una lista negra, entonces no lo hagas, ya hay muchas que puedes usar, con políticas para todos los gustos. Yo uso DSBL y SpamHaus, y además tengo un caché DNS entre el MTA y OpenDNS.

smtpd_recipient_restrictions =
  ...
  reject_rbl_client list.dsbl.org,
  reject_rbl_client sbl-xbl.spamhaus.org,
  ...

Hay un punto intermedio, en el cual te aprovechas de características de Postfix que refuerzan la verificación de comportamiento de los clientes SMTP que hablan con él. Por increíble que parezca, cosas como reject_non_fqdn_hostname y reject_invalid_hostname en Postfix eliminan una gran cantidad de UCE antes de que los recibas y tengas que pasarlos por SpamAssassin con el uso de recursos correspondiente. Y es gratis.

smtpd_delay_reject = yes
smtpd_helo_required = yes
smtpd_helo_restrictions =
   ...
   reject_non_fqdn_hostname,
   reject_invalid_hostname,
   ...
smtpd_sender_restrictions =
   ...
   reject_non_fqdn_sender,
   reject_unknown_sender_domain,
   ...
smtpd_recipient_restrictions =
  ...
  reject_unauth_pipelining,
  reject_non_fqdn_recipient,
  reject_unknown_recipient_domain,
  reject_unauth_destination,
  ...

La tendencia actual apunta a detener el spam no cuando lo recibes, ni cuando te lo envían, sino en el origen o cerca de él. La más accesible de esas tecnologías es SPF, y es bastante fácil ponerla a funcionar en Postfix. Se trata de llevar registros DNS de los MTA autorizados para el envío de correo electrónico de un dominio en particular. Así evitas que un desktop Windows en Tailandia te diga que steve@apple.com quiere venderte Viagra.

Finalmente hay un mecanismo muy sencillo de control de UCE que se basa en el punto 4.5.4.1 del RFC 2821 y es greylisting. En Postfix es muy fácil usar postgrey para establecer un sencillo mecanismo de listas grises que reduce en un 80% las incidencias de UCE en un servidor típico.

El MTA de g33k.com.ve le da servicio a varias cuentas y listas de correo de proyectos F/OSS y cultura libre con estas sencillas reglas. La administración es nula, no hay listas negras que mantener (ni en SQL ni nada) y sobre todo, la incidencia de correo basura es de 0%. Sin usar SpamAssassin, en un VPS de 15 VEF al mes. Gracias a ${DEIDAD} por el F/OSS.

Este blog refleja única y exclusivamente mis opiniones, y no las de mis empleadores, las de las organizaciones de las que formo parte ni las de ninguna otra persona natural o jurídica, pública o privada, nacional o extranjera.