Publi

Implementación de filtros de contenido «después de la cola» en Postfix [Ejemplos en Bash y Python]

Filros de contenido en Postfix
Como hemos visto en anteriores artículos, Postfix nos da una gran flexibilidad a la hora de aplicar reglar y filtros a los mensajes que van llegando. Como ejemplo tenemos la implementación de Milters. Estos filtros se ejecutan antes de introducir los mensajes en la cola de entrega por lo que, a veces, puede no ser lo que buscamos. Cuando filtramos un correo con milters, el emisor del mensaje va a saber si se entrega o no. Esto puede ser un punto positivo, pero cuando se trata de combatir el SPAM no podemos dejar que alguien se ponga a hacer pruebas contra nuestro servidor hasta que descubra nuestras reglas. Por otro lado, podemos tener necesidades especiales, como desviar el proceso de entrega de un mensaje cuando cumple una serie de reglas. Imaginémonos que cuando el mensaje tenga un determinado destinatario debemos enviarlo conectando directamente con un servidor de correo determinado. Puede que esto parezca un capricho, pero en determinados entornos empresariales, por seguridad, se suelen filtrar a conciencia los correos y tenemos que ser los demás los que nos adaptemos a ellos.

¿Dónde entran los filtros de contenido «después de la cola»?

Este tipo de filtro, como su nombre indica, after-queue, o después de la cola, se llamarán cuando el mensaje ya está en la cola de entrega. Aún tienen que pasar por un proceso para ser entregados, pero el emisor, o el servidor que los ha dejado, ya los ha enviado y ha desconectado, por lo que el control está ahora en nuestro campo. Cuando utilizábamos los Milters, teníamos bibliotecas para varios lenguajes de programación que nos permitían controlar el proceso. De hecho, libmilter nos permitía implementar el protocolo y manejo de estos filtros de forma sencilla. En cambio, con este tipo de filtros, después de la cola, vamos a recibir el mensaje completo, en texto plano, y nosotros nos tenemos que encargar de parsear el contenido del mensaje, extraer las cabeceras, analizarlas y actuar en consecuencia. Es algo más artesano, pero muy útil.

Gracias a la flexibilidad que nos da Postfix podemos implementar los filtros de varias formas. Por un lado, si el filtro es muy rápido, no va a tardar mucho en analizar los correos, incluso si son muy grandes, podemos hacer un simple script en bash, perl, python, PHP, un programa en C o lo que queramos, que simplemente recibirá el mensaje y lo enviará al siguiente paso de nuestro proceso de envío de correos. Vamos, Postfix saca de la cola el mensaje y se lo manda a nuestro filtro, nuestro filtro lo procesa y lo meterá de nuevo en la cola. Así que, un simple script puede hacer las veces de filtro de contenido, muy fácil y rápido de implementar.

Por otro lado, si queremos complicarnos un poco la vida, y no sólo complicarnos la vida, sino pensar en la escalabilidad del sistema, hacer que nuestro filtro lo procese otra máquina, un programa dentro de un contenedor de docker o lo que se nos ocurra, debemos implementar el filtro de contenido en un interfaz por red. Para ello, tenemos que crear un pequeño servidor de correo que, cuando reciba un mensaje, lo procese, y tome decisiones. Si queremos que el mensaje se envíe a través de nuestro sistema, tenemos que devolverlo a nuestro Postfix de nuevo, enviando el mensaje a través de otro puerto de envío. Si no queremos enviarlo, no tenemos que hacer nada, una vez el mensaje se ha sacado de la cola, desaparece.

Algunas utilidades, algo menos resumido

Uno de los usos más extendido es implementar filtros AntiSpam. Aunque hay muchos servidores de correo que cuando alguien envía un correo basura rechazan el mensaje nada más entrar, podemos estar dando pistas a un posible spammer. Por otro lado, muchas veces, los filtros AntiSpam suelen ser más complicados, implican consultar con varios servicios online de listas blancas y negras, aparte del análisis de la información, por lo que puede retrasar mucho el envío de los mensajes. ¿Por qué no sacar los mensajes de la cola, procesarlos, tardar lo que tengamos que tardar y volver a encolarlos?
Otro uso muy extendido es el de la búsqueda de virus o malware. Aunque, uno de mis usos favoritos es el poder cambiar la trayectoria de los correos. Me refiero a que si mandamos los correos a una dirección de desarrollo, no pase por el sistema de correo, sino que llegue a una base de datos, o a un fichero, o incluso pase directamente a un programa de análisis, o que si el mensaje es para un cierto destinatario, podamos cambiar el remitente y enviarlo desde otro servidor diferente. En este último caso, sacamos el mensaje de la cola de envío y, si el mensaje cumple unas ciertas condiciones lo volveremos a enviar, a través de otro servidor de correo, si no las cumple, el mensaje seguirá su curso. Es muy divertido.

Eso sí, os recomiendo encarecidamente que, cuando implementéis vuestros filtros de correo, escribáis en un log el mensaje que ha llegado y lo que hacéis con él. Esto nos ayudará muchísimo para el diagnóstico de problemas. Porque es posible que nuestro filtro no funcione bien, o que el mensaje que ha llegado no cumpla bien las condiciones, o incluso que haya un problema al volver a meterlo en la cola.

Configurando un filtro de contenido con un script

Como ejemplo sencillo, vamos a empezar configurando un script como filtro de correo. Es más, un script para Bash, muy sencillo, con el que recibiremos el mensaje, lo procesaremos y se lo volveremos a enviar a Postfix. Podemos crear un directorio llamado /var/spool/filters e introducirlos ahí. Por ejemplo el siguiente (lo llamamos censurado.sh):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/sh

function error() {
  local CODE="$1"
  local MSG="$2"
  echo "$MSG (Code: $CODE)"
  exit $CODE
}

INSPECT_DIR=/tmp
SENDMAIL="/usr/sbin/sendmail -G -i"
TMPFILE="in.$$"

# Códigos de salida obtenidos de <sysexits.h>
EX_TEMPFAIL=75
EX_UNAVAILABLE=69

# Limpieza de archivos temporales
trap "rm -f $TMPFILE" 0 1 2 3 15
# Start processing.
cd $INSPECT_DIR || error $EX_TEMPFAIL "$INSPECT_DIR does not exist"
cat >$TMPFILE || error $EX_TEMPFAIL "Cannot save mail to file"

if [ -n "$(grep -i 'censurado' $TMPFILE)" ]; then
  error $EX_UNAVAILABLE "censurado found!!"
fi

$SENDMAIL "$@" <$TMPFILE
exit $?

Vale, este filtro es muy sencillo, solo busca la palabra «censurado» dentro del texto del mensaje. Si lo encuentra, tira el mensaje para atrás y si no, lo devuelve a la cola. Como veis, para devolverlo a la cola, volvemos a llamar a sendmail. Y, por supuesto, podemos utilizar este script para implementar otros filtros más complicados, filtros que llamen a otros programas como sed, awk, o incluso otros programas externos que hagamos en otros lenguajes, envíen el mensaje a un servidor para su posterior procesamiento, anotar en un log el mensaje, emitir notificaciones, como por ejemplo enviar un SMS al móvil o un mensaje por Telegram a una persona cuando le manden un e-mail con una cierta palabra, vamos, lo que se nos ocurra. Eso sí, es mala idea autocontestar los correos desde aquí, sobre todo porque muchas veces, hay virus o mensajes de SPAM cuyo remitente no es el que dice ser y podemos estar autocontestando mensajes generando SPAM al mismo tiempo.

Ahora, para que Postfix ejecute este pequeño script cada vez que envíe un e-mail editamos /etc/postfix/master.cf buscamos la línea de smtp y la modificamos de la siguiente forma:

1
2
3
4
5
6
  # =============================================================
  # service type  private unpriv  chroot  wakeup  maxproc command
  #               (yes)   (yes)   (yes)   (never) (100)
  # =============================================================
smtp    inet    n       -       n       -       -       smtpd
   -o content_filter=censurado:dummy

Eso sí, el texto que en mi ejemplo son n y – lo dejamos tal y como lo tengamos en nuestro servidor, porque podemos alterar el funcionamiento del servidor de correo. Puede que smtpd tenga más argumentos en su ejecución, deberíamos añadir -o content_filter=censurado:dummy al final de los argumentos. Dummy es una configuración que indica el destino de los mensajes y puede ser utilizado en otros métodos de transporte (distinto de smtpd), pero que, por compatibilidad con versiones antiguas, es buena idea dejarlo escrito. Una vez hecho esto, más abajo en /etC/postfix/master.cf (al final, por ejemplo), debemos configurar nuestro filtro de la siguiente manera:

1
2
3
4
5
6
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
censurado unix -       n       n       -       -       pipe
   flags=Rq user=mail argv=/var/spool/filters/censurado.sh -f ${sender} -- ${recipient}

Una vez hecho esto, podemos reiniciar Postfix y ver si todo funciona bien. Algo que me gusta hacer siempre, cuando un sistema no está en producción y estamos creando filtros es meter llamadas a logger «Paso XXX» donde XXX pueden ser números o una explicación de qué estamos haciendo dentro del fichero de script de filtro. Luego, cuando haga las llamadas pertinentes al servidor de correo, donde se supone que se ha llamado al filtro, miro /var/log/syslog a ver si esos mensajes aparecen. Solo por saber que todo se ejecuta bien. Luego esas trazas las podemos eliminar o desactivar para poder activarlas en cualquier momento y diagnosticar problemas.

Configurando un filtro de contenido a través de TCP

En esta segunda opción, vamos a implementar un filtro a través de un mini-servidor SMTP que vamos a crear en Python. El objetivo es que sea otra máquina diferente la que pueda procesar el filtro. Donde digo otra máquina, puedo decir un servicio en la misma máquina (que en el futuro me podré llevar a otro lado) o un contenedor. Pero el caso es que se ejecutará por separado. Ahora Postfix, llamará a nuestro servicio a través de un puerto TCP y nuestro servicio volverá a enviar el mensaje a través de otro puerto diferente para meterlo en la cola. Y, si no queremos meterlo en la cola, no hacemos nada y listo.

He elegido hacer el script en Python porque es más sencillo de hacer y de entender, pero podríamos elegir cualquier lenguaje de programación que queramos. Ahora, se enviarán comandos SMTP y nosotros enviaremos comandos SMTP. Nuestro script /var/spool/filters/censurado.py quedaría así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import smtpd
import asyncore

import smtplib

import traceback
from Milter.utils import parse_addr

class CustomSMTPServer(smtpd.SMTPServer):

    def process_message(self, peer, mailfrom, rcpttos, data):
       
        mailfrom.replace('\'', '')
        mailfrom.replace('"', '')
       
        for recipient in rcpttos:
            recipient.replace('\'', '')
            recipient.replace('"', '')
       
        print 'Recibo un mensaje desde:', peer
        print 'Remitente:', mailfrom
        print 'Destinatario  :', rcpttos
        print 'MSG >>'
        print data
        print '>> EOT'

                if 'censurado' in data:
            print 'E-mail censurado'
            return


        try:
            server = smtplib.SMTP('localhost', 10026)
            server.sendmail(mailfrom, rcpttos, data)
            server.quit()
            print 'send successful'
        except smtplib.SMTPException:
            print 'Exception SMTPException'
        except:
            print 'Undefined exception'
            print traceback.format_exc()

        return
       
server = CustomSMTPServer(('127.0.0.1', 10025), None)

asyncore.loop()

En este caso, nuestro filtro escuchará en el puerto 10025 y cuando un mensaje pase el filtro lo enviará por SMTP al puerto 10026. Ahora, como siempre, tenemos que decirle a Postfix todo esto. Para ello, editamos /etc/postfix/master.cf (al final, por ejemplo) con lo siguiente:

1
2
3
4
5
# Recibe los mensajes
censurado unix - - n - 10 smtp -o smtp_send_xforward_command=yes -o disable_mime_output_conversion=yes

# Mete los mensajes de nuevo en la cola
localhost:10026 inet n - n - 10 smtpd -o content_filter= -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks,no_milters -o smtpd_authorized_xforward_hosts=127.0.0.0/8

Ahora en /etc/postfix/main.cf añadimos estas línea:

1
content_filter = censurado:localhost:10025 receive_override_options = no_address_mappings

En este caso estamos haciendo todo en localhost, pero si tuviéramos el servicio en otra máquina, deberíamos cambiar todos los localhost y los 127.0.0.1. Yo recomiento siempre dar nombres de hosts, aunque estemos en una red pequeña con máquinas conocidas. Podemos asociar en /etc/hosts el nombre del host con la IP que corresponda dentro de la red local. En /var/spool/filters/censurado.py deberíamos cambiar, CustomSMTPServer((‘127.0.0.1’, 10025), None) por la IP o el host de la red local de la máquina donde está instalado el filtro; y en smtplib.SMTP(‘localhost’, 10026), localhost debería ser la IP o el host de la máquina donde está instalado Postfix. Luego en /etc/postfix/main.cf , deberíamos cambiar localhost por el host de la máquina que ejecuta los filtros y en /etc/postfix/master.cf, localhost:10026 será el host de la máquina que ejecuta Postfix, podremos cambiar también smtpd_authorized_xforward_hosts= por la red local donde estemos ejecutando Postfix y los filtros, por ejemplo 172.0.0.0/24.

Tras esto debemos reiniciar Postfix. Ahora ejecutamos el script de Python que ejecuta el filtro, lo dejamos ejecutando e intentamos enviar un mail con esta configuración. La ventana donde tenemos el script de Python en ejecución debería empezar a mostrar información sobre la información recibida.

Si todo funciona bien, deberíamos configurar nuestro servicio de filtro en Python como servicio de sistema, para ejecutarse en el inicio y para tener una gestión más cómoda. Podemos seguir estos pasos.

Foto principal: unsplash-logoTom Parsons

También podría interesarte....

There are 37 comments left Ir a comentario

  1. Mike Rooney /
    Usando Google Chrome Google Chrome 116.0.0.0 en Windows Windows NT

    This is such awesome content i got to read after lot of time. Its so interesting as well as informative. I am sure everyone who read it got a lot to learn from it.Harley davidson marlboro man jacket

    1. Seguidores De Tik Tok /
      Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

      Aqui puedes encontrar todo lo que buscas Mike! https://deanpgud74304.review-blogger.com/48131128/el-tiktok

  2. Snake game /
    Usando Google Chrome Google Chrome 116.0.0.0 en Windows Windows NT

    Do you feel like going back in time to play the first iteration of Snake?

    1. Anillo de compromiso Lugo /
      Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

      Hola vamos a leer algo sobre joyas y ver un catalogo de Joyas de 2024 en https://wopi.es/las-mejores-joyas/

  3. Bobby /
    Usando Google Chrome Google Chrome 116.0.0.0 en Windows Windows NT

    Definitely imagine what that you said. Your favourite reason appeared to be on the web the easiest thing to be mindful of. sell my house fast dallas

  4. 메이저사이트 /
    Usando Google Chrome Google Chrome 117.0.0.0 en Windows Windows NT

    After reading this write-up, I honestly think this excellent website needs a lot more consideration. I return frequently to learn more, thank you for this information.메이저사이트

  5. SPORTS BETTING /
    Usando Google Chrome Google Chrome 117.0.0.0 en Windows Windows NT

    I Like!! Really appreciate you sharing this blog post.Really thank you! Keep writing.
    nba betting

  6. 먹튀검증 /
    Usando Google Chrome Google Chrome 117.0.0.0 en Windows Windows NT

    A very interesting article, how to improve one’s living environment, and what are the methods? Thank you for reading the website I shared.먹튀검증

    1. Lj /
      Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

      I definitely agree! Really good! skip hire near me

  7. L. Martin /
    Usando Google Chrome Google Chrome 117.0.0.0 en Windows Windows NT

    I so really relate myself to this post. Thanks for the info then!
    web design tampa

  8. okbet /
    Usando Google Chrome Google Chrome 117.0.0.0 en Windows Windows NT

    It’s actually a nice and helpful piece of info. I’m happy that you shared this helpful information with us. Please stay us up to date like this.Thank’s for sharing.

    Here is My Homepage: [url=https://casino99mgm.com/esabong/]sabong online game[/url]

  9. L. Martin /
    Usando Google Chrome Google Chrome 118.0.0.0 en Windows Windows NT

    It’s difficult to find educated people for this topic, but you sound like you know what you’re talking about! Thanks paver contractors bradenton

  10. 토토사이트 /
    Usando Google Chrome Google Chrome 118.0.0.0 en Windows Windows NT

    if more people that write articles involved themselves with writing great content like you, more readers would be interested in their writings. I have learned too many things from your article.토토사이트

  11. Josh /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    Really nice blog! recovery leeds

  12. 토토사이트 /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    This is an awesome site and I will definitely prescribe to my friends. You actually understand how to bring a concern to light making it essential. Thank you and waiting for your new post. 토토사이트

  13. Letisha /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    REally great blog! Recovery Maidenhead

  14. Drew /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    Love blogs like this! Lots of info. car recovery plymouth

  15. Serena /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    Interesting blog! sandblasting

  16. Josh /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    Great blog. Thanks for this! Keep it up! pavers

  17. Karin /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    Thanks so much for this! Really really good. breakdown recovery luton

  18. 먹튀검증 /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    I wish more writers of this kind of content would take the time to research and write so well. I’m impressed by your vision and insight. 먹튀검증

  19. Butiffely /
    Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    This simple to understand.
    Painting Abbotsford

  20. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    The sheer size and selection of these web slots are mind-blowing. Great job. สล็อตเว็บใหญ่

  21. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    I’m interested in hearing about people’s experiences with long-lasting slots. เว็บสล็อต

  22. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Your websites facilitate all the more each else volume is so engaging further serviceable It chooses me occur for withdraw reprise. I will in a split second snatch your rss channel to remain educated of any updates. เว็บสล็อตทุกค่าย

  23. Pearland Concrete Contractors /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    It’s crucial to address potential drawbacks like revealing delivery status when combating SPAM.

  24. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    I utilize just astounding materials – you can see them at: สล็อตโรม่า

  25. jsimitseo /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    The best article I ran over various years, compose something about it on this page. ป๊อกเด้งออนไลน์

  26. Pasadena Concrete Company /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    The flexibility they offer is crucial, especially in addressing specific business needs and enhancing email security.

  27. UFAAUTO789 /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    ufa789bet เว็บพนันครบวงจร แทงบอล บาคาร่า สล็อต ครบจบที่เดียว

  28. Rank Xone /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    The live dealer games in online casinos are a game-changer. It adds a human touch to the experience and enhances the overall immersion. 우리카지노

  29. ยูฟ่าเบท168 /
    Usando Google Chrome Google Chrome 107.0.0.0 en Windows Windows NT

    You completed certain reliable points there. I did a search on the subject and found nearly all persons will agree with your blog. ยูฟ่าเบท168

  30. Brea /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Lovely website. For efficient recovery liverpool, call Car Recovery Liverpool.

  31. jsimitseo /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    These you will then observe the most vital thing, the application gives you a site an effective critical web page: best concierge doctor

  32. WilliamSEO /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    These you will then observe the most vital thing, the application gives you a site an effective critical web page: จำนำรถจอด

  33. Rank Xone /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    Composing with style and getting great compliments on the article is very hard, to be honest.But you’ve done it so serenely and with so cool feeling and you’ve nailed the activity. This article is had with style and I am giving great compliment. Best! รับจำนำรถจอด

  34. BETFLIXSUPERVIP /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    After reading your article I was amazed. I know that you explain it very well. And I hope that other readers will also experience how I feel after reading your article. Feel free to visit my website; ทางเข้า betflix

Leave a Reply