Filtrage du contenu après mise en file d'attente


Introduction

Ce document nécessite une version 2.1 ou supérieure de Postfix.

Normalement, Postfix reçoit le courrier, le stocke en file d'attente puis le livre. Avec le filtrage du contenu externalisé décrit ici, le courrier est filtré APRÈS sa mise en file d'attente. Cette approche découple les processus de reception et de filtrage et vous donne un contrôle maximum sur le nombre de processus que vous êtes disposés à lancer en parallèle.

Le filtre de contenu après mise en file d'attente est censé être utilisé comme suit :

Réseau ou
utilisateurs locaux
-> File d'attente
Postfix
-> Filtre de
contenu
-> File d'attente
Postfix
-> Réseau ou
utilisateurs locaux

Ce document décrit les implémentations qui utilisent une instance unique de Postfix for tout : recevoir, filtrer et livrer le courrier. Les applications qui utilisent deux instances séparées de Postfix seront couvertes par une prochaîne version de ce document.

Le filtre de contenu après mise en file d'attente ne doit pas être confondu avec l'approche décrite à la page SMTPD_PROXY_README où les messages SMTP entrants sont filtrés AVANT leur stockage en file d'attente.

Ce document décrit deux approches pour filtrer tout le courrier comme pour filtrer selectivement :

Principes d'opération

Un filtre de contenu externe reçoit les messages non filtrés de Postfix (comme décrit plus loin ci-dessous) et fait l'une des actions suivantes :

  1. Re-injecte le message dans Postfix éventuellement en ayant changé le contenu et/ou la destination.

  2. Rejette le message (en renvoyant un code de status à Postfix). Postfix le renvoie alors à l'expéditeur.

NOTE : à cette époque de vers et de messages de spam forgés, c'est une TRÈS MAUVAISE IDÉE de renvoyer le virus à l'expéditeur dont il n'est probablement pas l'initiateur. Il vaut mieux éliminer les virus connus et mettre en quarantaine les éléments suspects afin qu'un humain puisse décider quoi faire.

Exemple de filtrage simple de contenu

Le premier exemple est simple à mettre en œuvre. Postfix reçoit le courrier du réseau via le serveur smtpd(8) et livre les messages non filtrés à un filtre de contenu avec l'agent de livraison pipe(8) de Postfix. Le filtre de contenu ré-injecte les messages filtrés dans Postfix avec la commande sendmail(1), ainsi Postfix peut le livrer à la destination finale.

Ceci signifie que le courrier soumis par la commande sendmail(1) de Postfix ne peut être filtré sur son contenu.

Dans le schéma ci-dessous, les noms suivis par un numéro représentent des commandes ou démons Postfix. Reportez-vous à la page OVERVIEW pour une présentation de l'architecture de Postfix.

Non-filtré

->

smtpd(8)

pickup(8)
>- cleanup(8) -> qmgr(8)
File d'attente
Postfix
-< local(8)
smtp(8)
pipe(8)
->
->
Filtré
Filtré
^
|
|
v
file d'attente
maildrop
<- postdrop(1)
Postfix
<- sendmail(1)
Postfix
<- Filtre de
contenu

Le filtre de contenu peut être un simple script shell comme suit :

 1 #!/bin/sh
 2 
 3 # Filtre shell simple. Il doit être appelé comme suit:
 4 #       /path/to/script -f expéditeur destinataire...
 5 
 6 # Répertoires
 7 INSPECT_DIR=/var/spool/filter
 8 SENDMAIL="/usr/sbin/sendmail -G -i" # n'employer JAMAIS "-t" ici
 9 
10 # Codes de retour issus de <sysexits.h>
11 EX_TEMPFAIL=75
12 EX_UNAVAILABLE=69
13 
14 # Nettoyage lors en sortant ou lors d'une interruption
15 trap "rm -f in.$$" 0 1 2 3 15
16 
17 # Démarrage du processus.
18 cd $INSPECT_DIR || {
19     echo $INSPECT_DIR n'existe pas; exit $EX_TEMPFAIL; }
20 
21 cat >in.$$ || { 
22     echo Impossible de saugarder le message dans un fichier; exit $EX_TEMPFAIL; }
23 
24 # Ecrivez votre filtrage de contenu ici.
25 # filter <in.$$ || {
26 #   echo Contenu de message content rejeté; exit $EX_UNAVAILABLE; }
27 
28 $SENDMAIL "$@" <in.$$
29 
30 exit $?

Notes :

Je vous suggère de lancer d'abord ce script à la main avec un vrai message (en-têtes+contenu) jusqu'à ce que vous soyez satisfait des résultats :

% /chemin/du/script -f sender recipient... <message-file

Une fois les résultats du filtrage satisfaisant :

Performances du filtrage simple de contenu

Avec le script shell script montré ci-dessus vous diminuerez les performances d'un facteur quatre pour les messages en transit arrivant et partant par SMTP. Vous diminuerez encore ces performances pour chaque fichier temporaire créé ou effacé par le processus de filtrage de contenu. Cet impact est moindre pour le courrier livré ou soumis localement car ces livraisons sont déjà plus lentes que le transit SMTP.

Limites du filtrage simple de contenu

Le problème avec les filtres de contenus tels le script présenté ci-avant est qu'ils ne sont pas très robustes. La principale raison est que le logiciel ne parle pas un protocole bien défini avec Postfix. Si le script shell de filtrage s'interrompt car le shell rencontre des problèmes d'allocation mémoire, le script ne produira pas un code d'erreur conforme au fichier /usr/include/sysexits.h. Au lieu d'être mis en file d'attente retardée, le message sera retourné. Le même défaut peut apparaître si le logiciel de filtrage rencontre lui même un problème de ressources.

La méthode simple de filtrage de contenu ne peut être invoquée par les résultats des consultations header_checks ou body_checks. Ces expressions seront appliquées de nouveau après la ré-injection avec la commande sendmail de Postfix créant une boucle de message. La méthode avancée de filtrage de contenu (voir ci-dessous) permet de désactiver les consultations header_checks ou body_checks pour les messages filtrés.

Désactiver le filtrage simple de contenu

Pour désactiver le filtrage de contenu :

Exemple de filtrage avancé de contenu

Le second exemple est plus complexe, mais peut donner de meilleures performances et risque moins de retourner le courrier pour des problèmes de ressources. Le filtre de contenu reçoit le courrier par le protocole SMTP sur le port 10025 de la machine locale et renvoie les messages filtrés sur le port 10026.

Pour les logiciels de filtrage de contenu ne pouvant utiliser SMTP, le proxy Bennett Todd's implémente un bon framework de filtrage de contenu SMTP/PERL. Voire http://bent.latency.net/smtpprox/.

Dans le schéma ci-dessous, les noms suivis d'un nombre représentent des commandes ou des démons de Postfix. Reportez-vous à la page OVERVIEW pour une présentation de l'architecture de Postfix.

Non-filtré

Non-filtré
->

->
smtpd(8)

pickup(8)
>- cleanup(8) -> qmgr(8)
File d'attente
Postfix
-< smtp(8)

local(8)
->

->
Filtré

Filtré
^
|
|
v
smtpd(8)
10026
smtp(8)
^
|
|
v
filtre de contenu 10025

Cet exemple filtre tout le courrier, y compris celui arrivant via SMTP ou soumis localement par la commande sendmail de Postfix. Reportez-vous aux exemples de la fin de ce document pour voir comment configurer le filtre en fonction des arrivées.

Les performances peuvent être réduite d'un facteur deux pour les messages arrivés et livrés par SMTP en supposant que le filtre ne crée pas de fichiers temporaires. Chaque création de fichier par le filtre rajoute un facteur de diminution des performances.

Filtrage avancé de contenu : demander que tout le courrier soit filtré

Pour activer le filtrage avancé de contenu pour tout le courrier, indiquez dans le fichier main.cf :

/etc/postfix/main.cf :
    content_filter = scan:localhost:10025
    receive_override_options = no_address_mappings

Filtrage avancé de contenu : envoyer les messages non filtrés au filtre de contenu

Dans cet exemple, "scan" est une instance de client SMTP de Postfix avec quelques paramètres de configuration différents. C'est pourquoi il est lancé ainsi dans le fichier master.cf de Postfix :

/etc/postfix/master.cf :
    # =============================================================
    # service type  private unpriv  chroot  wakeup  maxproc command
    #               (yes)   (yes)   (yes)   (never) (100)
    # =============================================================
    scan      unix  -       -       n       -       10      smtp
        -o smtp_send_xforward_command=yes

Filtrage avancé de contenu : lancer le filtre de contenu

Le filtre de contenu peut être activé par le service spawn de Postfix qui est l'équivalent de inetd. Per exemple, pour lancer 10 processus de filtrage de contenu sur le port local 10025 :

/etc/postfix/master.cf :
    # ===================================================================
    # service       type  private unpriv  chroot  wakeup  maxproc command
    #                     (yes)   (yes)   (yes)   (never) (100)
    # ===================================================================
    localhost:10025 inet  n       n       n       -       10      spawn
        user=filter argv=/chemin/vers/le/filtre localhost 10026

Si votre filtre inclus des fonctionnalités réseau SMTP (telles les passerelles anti-virus), vous pouvez le lancer en mode autonome et ne pas utiliser le service spawn de Postfix.

Filtrage avancé de contenu : ré-injecter les messages dans Postfix

Le travail du filtre de contenu est soit de renvoyer le message avec un suivi du diagnostique, soit de le ré-injecter dans Postfix sur le port local 10026.

Le plus simple des filtres de contenu se contente de recopier en sortie les commandes SMTP et les données reçues en entrée. S'il y a un problème, tout ce qu'il a à faire est de répondre au `.' de Postfix (commande de fin de DATA) avec `550 content rejected' et se deconnecter sans envoyer le `.' sur la connexion qui ré-injecte le message dans Postfix.

/etc/postfix/master.cf :
    # ===================================================================
    # service       type  private unpriv  chroot  wakeup  maxproc command
    #                     (yes)   (yes)   (yes)   (never) (100)
    # ===================================================================
    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_helo_restrictions=
        -o smtpd_client_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o mynetworks=127.0.0.0/8
        -o smtpd_authorized_xforward_hosts=127.0.0.0/8

Performance du filtrage avancé de contenu

Avec l'approche "sandwich" de filtrage de contenu décrite ici, il est important de faire correspondre le nombre de filtres concurrentiels à la CPU, la mémoire et les ressources entrées/sorties disponibles. Trop peu de processus filtres encombre la file d'attente active même avec peu de volume de trafic ; à l'inverse, trop de processus filtres risque d'interrompre la livraison au filtre à cause d'un manque de ressources.

Actuellement, l'optimisation des performances de filtrage est un processus difficile et générateur d'erreurs ; l'analyse est faussée car les messages filtrés et non filtrés partagent la même file d'attente. Comme indiqué dans l'introduction, le filtrage de contenu avec de multiples instances de Postfix sera décrit dans une prochaîne version de ce document.

Désactiver le filtrage avancé de contenu

Pour désactiver le filtrage de contenu :

Filtrer le courrier des utilisateurs extérieurs seulement

L'approche la plus simple est de configurer UNE instance de Postfix avec de multiples adresses IP de serveurs SMTP dans le fichier master.cf :

Avec cette configuration, vous pouvez suivre la même procédure que présentée dans les exemples de filtrage "simple" ou "avancé" si ce n'est que vous ne devez pas renseigner les paramètres "content_filter" et "receive_override_options" dans le fichier main.cf.

Filtres différents par domaine

Si vous êtes un fournisseur MX et voulez appliquer différents filtres suivant les domaines, vous pouvez configurer UNE instance de Postfix avec de multiples adresses IP de serveur SMTP dans le fichier master.cf. Chaque adresse fournit un service de filtrage différent.

/etc/postfix/master.cf :
    # =================================================================
    # service     type  private unpriv  chroot  wakeup  maxproc command
    #                   (yes)   (yes)   (yes)   (never) (100)
    # =================================================================
    # service SMTP pour les domaines filtrés par xxx:yyy
    1.2.3.4:smtp  inet  n       -       n       -       -       smtpd
        -o content_filter=xxx:yyy 
        -o receive_override_options=no_address_mappings

    # service SMTP pour les domaines filtrés par zzz:www
    1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
        -o content_filter=zzz:www 
        -o receive_override_options=no_address_mappings

Avec cette configuration, vous pouvez suivre la même procédure que présentée dans les exemples de filtrage "simple" ou "avancé" si ce n'est que vous ne devez pas renseigner les paramètres "content_filter" et "receive_override_options" dans le fichier main.cf.

Configurez les enregistrements MX du service DNS pour router chaque domaine sur sa propre instance de serveur SMTP.

Actions FILTER dans les tables d'accès ou d'en-tête/contenu

Les configurations de filtrages présentées jusqu'ici sont statiques. Les messages suivant un chemin donné sont soit toujours filtrés soit jamais. Depuis la version 2.0 de Postfix, vous pouvez activer le filtrage de contenu au fil de l'eau.

Pour activer le filtrage de contenu avec une table de règles d'accès(5) :

/etc/postfix/access:
    whatever       FILTER xxx:yyy

Pour activer le filtrage de contenu avec une table de correspondances header_checks(5) ou body_checks(5) :

/etc/postfix/header_checks:
    /whatever/     FILTER xxx:yyy

Vous également renseigner ainsi toutes les tables d'accès du serveur smtpd et les tables d'examen d'en-têtes/de contenu du serveur cleanup. Cette fonctionnalité doit être utilisée avec soin : vous devez désactiver toutes les fonctionnalités anti-spam dans les serveurs smtpd et cleanup après-filtrage, sinon vous créerez une boucle de message.

Limites :

Valid HTML 4.01! traduction par Xavier Guimard - Retour au menu