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 :
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 :
Re-injecte le message dans Postfix éventuellement en ayant changé le contenu et/ou la destination.
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.
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é
^
||
vfile 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 :
Ligne 8 : l'option -G n'a aucun effet avant Postfix 2.3 et depuis, désactive la réécriture des adresses dans les en-têtes de messages.
Ligne 8 : l'option -i indique de ne pas interrompre la lecture lorsqu'un ligne ne contient que ".".
Ligne 8 : n'employer JAMAIS l'option "-t" ici. Ceci empêcherait la livraison comme si on envoiyait un message de liste de diffusionde nouveau à la liste.
Ligne 21 : la première action consiste à cenregistrer le message dans un fichier et ensuite seulement le filtrer via un programme tiers.
Ligne 22 : si le message n'a pas pu être enregistré, la livraison est retardée en renvoyant un code d'erreur 75 (EX_TEMPFAIL). Postfix place alors le message dans la file d'attente des messages retardés et tente une nouvelle livraison ultérieurement.
Ligne 25 : vous devrez indiquer ici un réel programme de filtrage qui reçoit le contenu par l'entrée standard.
Ligne 26 : si le filtre de contenu trouve un prloblème, le message est renvoyé en renvoyant un code d'erreur status 69 (EX_UNAVAILABLE). Postfix retournera le message à l'expéditeur comme non-livrable.
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.
Ligne 28 : si le contenu est accepté, il est passé à la commande sendmail de Postfix et le status de sortie du script est celui de cette commande. Postfix livrera le message comme d'habitude.
Ligne 30 : le script retourne le status de la commande sendmail de Postfix.
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 :
Créez un compte utilisateur dédié nommé par exemple "filter". Cet utilisateur transporte tous les contenus de message potentiellement dangereux - c'est pourquoi on utilise un compte séparé. N'utilisez pas "nobody", et surtout pas "root" ou "postfix".
Créez un répertoire /var/spool/filter accessible uniquement à l'utitisateur "filter" dans lequel le script est supposé stocker ses fichiers temporaires.
Configurez Postfix pour livrer le courrier au filtre de contenu avec l'agent de livraison pipe(8).
/etc/postfix/master.cf : # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= filter unix - n n - 10 pipe flags=Rq user=filter argv=/path/to/script -f ${sender} -- ${recipient}
L'exemple de configuration ci-dessus lance au plus 10 filtres en parallèle. Au lieu de 10 processus concurrents, utilisez le nombre adapté à votre machine. Les logiciels d'inspection de contenu peuvent consommer beaucoup de ressources, c'est pourquoi vous devez indiquer une limite de processus concurrents.
Pour activer le filtrage de contenu pour le courrier arrivant via SMTP seulement, ajoutez "-o content_filter=filter:dummy" à l'entrée du fichier master.cf qui définit le serveur SMTP de Postfix :
/etc/postfix/master.cf : # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= smtp inet ...other stuff here, do not change... smtpd -o content_filter=filter:dummy
La ligne "content_filter" oblige Postfix à ajouter une requête de filtrage à chaque message entrant, avec un contenu "filter:dummy". Cet enregistrement surcharge le routage normal du message pour le rediriger vers le filtre.
Le paramètre de configuration content_filter accepte la même syntaxe que la partie droite d'une table de transport.
Lancez "postfix reload" pour activer ces changements.
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.
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.
Pour désactiver le filtrage de contenu :
éditez le fichier master.cf file, effacez le texte "-o content_filter=filter:dummy" de l'entrée définissant le serveur SMTP de Postfix.
lancez "postsuper -r ALL" pour supprimer les informations de filtrage de contenu des fichiers déjà en file d'attente.
relancez "postfix reload".
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é^
||
vsmtpd(8)
10026smtp(8)
^
||
vfiltre 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.
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
La ligne "content_filter" oblige Postfix à ajouter un enregistrement de requête de contenu à chaque message entrant avec le contenu "scan:localhost:10025". Ces enregistrements sont ajoutés par les serveurs smtpd(8) et pickup(8) (et qmqpd(8) si vous avez activé ce service).
Les requêtes de filtrage de contenu sont stockées dans les files d'attente, c'est ainsi que Postfix garde trace des messages qui doivent être filtrés. Lorsqu'une file d'attente contient une requête de filtrage de contenu, le gestionnaire des files d'attente (qmgr(8)) livre le message au filtre indiqué sans tenir compte de sa destination finale.
La ligne "receive_override_options" désactive les manipulations d'adresses avant le filtrage permettant ainsi au filtre de voir l'adresse originale au lieu du résultat de la substitution des alias virtuels, des translations canoniques, de l'ajout automatique d'un destinataire caché (bcc), du masquage d'adresse, etc.
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
Ceci lance au plus 10 filtres de contenu en parallèle. Remplacez cette limite par une plus adaptée à votre système. Les logiciels d'inspection de contenu peuvent consommer beaucoup de ressources, c'est pourquoi il faut en limiter le nombre.
Avec "-o smtp_send_xforward_command=yes", le transport "scan" essayera de transférer le nom du client d'origine et l'adresse IP au processus smtpd après filtrage, ainsi les messages filtrés seront enregistrés avec l'adresse IP réelle du client. Reportez-vous aux pages smtp(8) et XFORWARD_README pour plus d'informations.
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
"filter" est un compte utilisateur local dédié. Cet utilisateur ne se loguera jamais et peut recevoir un mot de passe "*", un shell et un répertoire utilisateur inexistant. Cet utilisateur manipulera tous les contenus de messages potentiellement dangereux - c'est pourquoi il doit s'agir d'un compte séparé.
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.
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
Note : n'utilisez pas d'espaces autour des caractères "=" ou ",".
Note : le serveur SMTP ne doit pas avoir une limite de processus inférieure à l'entrée "filter" du fichier master.cf.
"-o content_filter=" surcharge le paramètre du fichier main.cf et indique de ne pas filtrer le contenu des messages arrivant du filtre. Sans ce paramètre, vous créerez une boucle de message.
"-o receive_override_options" surcharge le paramètre du fichier main.cf pour éviter de doubler le travail déjà réalisé par le filtre de contenu. Il est complémentaire des options spécifiées dans le fichier main.cf :
Nous indiquons "no_unknown_recipient_checks" pour désactiver les recherches si le destinataire est inconnu.
Nous indiquons "no_header_body_checks" pour désactiver les examens d'en-têtes/de contenu.
Nous indiquons "no_milters" pour désactiver les applications Milter (cette option n'est disponible que sur les versions 2.3 et supérieures de Postfix).
Nous n'indiquons pas "no_address_mapping" ici. Ceci active les réécritures d'adresses après le filtre de contenu. La paramètre "receive_override_options" du fichier main.cf désactive ces réécritures avant le filtre de contenu.
Ces options de reception surchargées sont implémentées sur le serveur SMTP lui-même ou passées au serveur cleanup.
"-o smtpd_xxx_restrictions" et "-o mynetworks=127.0.0.0/8" surchargent les paramètres du fichier main.cf. Ils désactivent les contrôles anti-spam inutiles ici.
Avec "-o smtpd_authorized_xforward_hosts=127.0.0.0/8", le transport "scan" essayera de transférer le nom et l'adresse originaux du client, ainsi les messages filtrés seront logués avec les réels caractéristiques du client. Reportez-vous aux pages XFORWARD_README et smtpd(8) pour plus d'informations.
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.
Pour désactiver le filtrage de contenu :
Effacez les deux lignes suivantes du fichier main.cf. Les autres changements fait pour activer le filtrage seront sans effet après.
/etc/postfix/main.cf : content_filter = scan:localhost:10025 receive_override_options = no_address_mappings
lancez "postsuper -r ALL" pour supprimer les informations de filtrage de contenu des fichiers déjà en file d'attente.
relancez "postfix reload".
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 :
Deux adresses IP de serveru SMTP pour le courrier interne uniquement avec le filtrage de contenu désactivé.
/etc/postfix/master.cf : # ================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================== 1.2.3.4:smtp inet n - n - - smtpd -o smtpd_client_restrictions=permit_mynetworks,reject 127.0.0.1:smtp inet n - n - - smtpd -o smtpd_client_restrictions=permit_mynetworks,reject
Une adresse de serveur SMTP pour le courrier venant de l'extérieur uniquement avec filtrage actif.
/etc/postfix/master.cf : # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= 1.2.3.5:smtp inet n - n - - smtpd -o content_filter=xxx:yyy -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.
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.
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 :
Les actions FILTER des tables d'accès et d'examen d'en-têtes/de contenu ont la préférence sur les filtres définis dans le paramètre content_filter du fichier main.cf.
Si un message déclenche plusieurs actions de filtrage, seule la dernière sera prise en compte.
Le même filtrage est appliqué à tous les destinataires du même message.
traduction par Xavier Guimard - Retour au menu