Le serveur SMTP de Postfix dispose de différents mécanismes intégrés pour bloquer ou accepter le courrier à différentes étapes du protocole SMTP. Depuis la version 2.1, Postfix peut déléguer ces décisions à un serveur extérieur à Postfix.
Avec ce mécanisme, une simple liste grise peut être implementée avec seulement une douzaine de lignes de Perl comme proposé à la fin de ce document. Un autre exemple de délégation de politique est le serveur SPF de Meng Wong disponible à l'adresse http://spf.pobox.com/. Des exemples de politiques peuvent être trouvées dans les sources de Postfix dans le répertoire examples/smtpd-policy.
La délégation de politique est maintenant la méthode préférée pour ajouter des politiques à Postfix. Il est plus aisé de développer une nouvelle fonctionnalité avec quelques lignes de Perl que d'essayer de faire la même chose en C. La différence en performance est imperceptible sauf dans les environnements les plus chargés.
Ce document couvre les sujets suivants :
Le protocole de délégation de Postfix est vraiment simple. La requête client est une série de nom=valeur séparées par une nouvelle ligne et terminée par une ligne vide. La réponse du serveur est une ligne nom=valeur terminée elle aussi par une ligne vide.
Ci-dessous un exemple de tous les attributs que le serveur SMTP de Postfix envoie dans une requête de politique d'accès déléguée :
request=smtpd_access_policy protocol_state=RCPT protocol_name=SMTP helo_name=un.domaine queue_id=8045F2AB23 sender=foo@bar.tld recipient=bar@foo.tld recipient_count=0 client_address=1.2.3.4 client_name=un.autre.domaine.tld reverse_client_name=un.autre.domaine.tld instance=123.456.7 Postfix versions 2.2 et supérieures : sasl_method=plain sasl_username=vous sasl_sender= size=12345 ccert_subject=solaris9.porcupine.org ccert_issuer=Wietse Venema ccert_fingerprint=C2:9D:F4:87:71:73:73:D9:18:E7:C2:F3:C1:DA:6E:04 Postfix versions 2.3 et supérieures : encryption_protocol=TLSv1/SSLv3 encryption_cipher=DHE-RSA-AES256-SHA encryption_keysize=256 etrn_domain= [ligne vide]
Notes :
L'attribut "request" est obligatoire. Dans cet exemple, le type de requête est "smtpd_access_policy".
L'ordre des attribut est sans importance. Le serveur de politique devrait ignorer celles qu'il ne comprend pas.
Lorsqu'un même attribut est transmit plusieurs fois, le serveur ne devrait garder que la première ou la dernière valeur.
Lorsqu'un attribut n'est pas disponible, le client ne l'envoie pas ou l'envoie avec une valeur vide ("name="), ou l'envoie avec une valeur 0 ("name=0") pour les attributs numériques.
L'attribut "recipient" n'est disponible qu'à l'étape "RCPT TO", et aux étapes "DATA" et "END-OF-MESSAGE" lorsque Postfix n'accepte qu'un seul destinataire au message.
L'attribut "recipient_count" (Postfix 2.3 et supérieurs) est non nul seulement aux étapes "DATA" et "END-OF-MESSAGE". Il indique le nombre de destinataires que Postfix a accepté pour le message en cours.
L'adresse du client se présente sous la forme pointée IPv4 (1.2.3.4) ou sous la forme d'une adresse IPv6 (1:2:3::4:5:6).
Pour les explications sur les différences entre les informations client_name inverse et vérifiée, reportez-vous au paragraphe reject_unknown_client_hostname de la page postconf(5).
Un nom d'attribut ne doit pas contenir les signes "=", null ou "nouvelle ligne" et la valeur associée ne doit pas contenir le signe null ou "nouvelle ligne"
La valeur de l'attribut "instance" peut être utilisé pour correler différentes requêtes concernant la même livraison de message.
La valeur de l'attribut "size" indique la taille du message que le client a indiqué dans la commande MAIL FROM command (zéro si rien n'est indiqué). Avec Postfix 2.2 et supérieurs, il indique la taille réelle du message lorsque le client envoie la commande END-OF-DATA.
Les attributs "sasl_*" (Postfix 2.2 et supérieurs) présentent les informations sur la façon dont le client a été authentifié via SASL. Ces attributs sont vides s'il n'y a pas d'authentification SASL.
Les attributs "ccert_*" (Postfix 2.2 et supérieurs) présentent les informations sur la façon dont le client a été authentifié via TLS. Ces attributs sont vides s'il n'y a pas d'authentification TLS.
Les attributs "encryption_*" (Postfix 2.3 et supérieurs) présentent les informations sur la façon dont la connexion est chiffrée. Dans le cas des connexions en clair, les attributs concernant le protocole et le chiffrement sont vides et la taille de clef est fixée à 0.
L'attribut "etrn_domain" n'est défini que dans le contexte d'une commande ETRN et indique le paramètre de la commande ETRN.
Ce qui suit est spécifique aux requêtes de politique déléguées SMTPD
Les noms de protocole (protocole_name) sont ESMTP ou SMTP.
Les états du protocole (protocol_state) sont CONNECT, EHLO, HELO, MAIL, RCPT, DATA, VRFY ou ETRN; ce sont les différents états dans lesquels le serveur SMTP de Postfix prend des décisions OK/REJECT/HOLD/etc.
Le serveur de politique répond par une action autorisée dans une table access(5) du serveur SMTPD de Postfix. Exemple :
action=defer_if_permit Service temporarily unavailable [ligne vide]
Ceci entraîne le rejet de la requête avec un code d'erreur 450 et la mention"Service temporarily unavailable", si le serveur SMTP ne trouve aucune raison de rejeter la requête à titre permanent.
En cas de problème, le serveur ne doit pas renvoyer de réponse mais logger un avertissement et se déconnecter. Postfix retentera la requête ultérieurement.<
Le client de délégation de la politique de Postfix peut se connecter à une socket TCP ou UNIX. Exemples :
inet:127.0.0.1:9998 unix:/chemin/absolu unix:chemin/relatif
Le premier exemple indique que le serveur écoute sur le port TCP 9998 de la boucle locale, le second sur une socket UNIX et le troisième sur une socket UNIX située dans le répertoire des files d'attentes de Postfix (/var/spool/postfix en général). Utilisez ce dernier pour les serveurs de politiques contrôlés par le démon master de Postfix.
Pour créer un service de politique qui écoute une socket UNIX appelée "policy" et fonctionne sous le contrôle du démon spawn(8) de Postfix, vous pouvez configurer Postfix comme suit :
1 /etc/postfix/master.cf: 2 policy unix - n n - - spawn 3 user=nobody argv=/chemin/vers/le/serveur/de/politique 4 5 /etc/postfix/main.cf: 6 smtpd_recipient_restrictions = 7 ... 8 reject_unauth_destination 9 check_policy_service unix:private/policy 10 ... 11 policy_time_limit = 3600
NOTES :
Lignes 2 et 11 : le démon spawn(8) tue par défaut les processus après 1000 secondes. C'est trop court pour un démon qui doit fonctionner aussi longtemps que le client SMTP est connecté au serveur SMTP. Cette valeur par défaut est surchargée dans le fichier main.cf avec le paramètre "policy_time_limit". Le nom du paramètre est le nom de l'entrée du fichier master.cf ("policy") avec le suffixe "_time_limit".
Lignes 8 et 9 : indiquez toujours "check_policy_service" APRÈS "reject_unauth_destination" sinon votre système peut devenir un relais ouvert.
Les sockets UNIX Solaris ne sont pas fiables. Utilisez plutôt des sockets TCP :
1 /etc/postfix/master.cf: 2 127.0.0.1:9998 inet n n n - - spawn 3 user=nobody argv=/some/where/policy-server 4 5 /etc/postfix/main.cf: 6 smtpd_recipient_restrictions = 7 ... 8 reject_unauth_destination 9 check_policy_service inet:127.0.0.1:9998 10 ... 11 127.0.0.1:9998_time_limit = 3600
Les autres paramètres de configuration qui contrôlent le coté client du protocole de délégation de politique sont :
smtpd_policy_service_max_idle (défaut: 300s) : le temps au bout duquel le serveur SMTP ferme une connexion inutilisée sur le serveur délégataire.
smtpd_policy_service_max_ttl (défaut: 1000s) : le temps minimum avant que le serveur SMTP de Postfix ne ferme une connexion active au serveur délégataire.
smtpd_policy_service_timeout (défaut: 100s) : le temps limite pour se connecter, envoyer ou recevoir d'un serveur délégataire.
Les listes grises sont une défense contre les courriers publicitaires non sollicités décrite à l'adresse http://www.greylisting.org/. Cette idée a été discutée sue la liste de diffusion postfix-users un an avant qu'elle ne soit popularisée.
Le fichier exemples/smtpd-policy/greylist.pl des sources de Postfix implémente un serveur simple de politique de liste grise. Il enregistre une marque de temps pour chaque tuple (client, expéditeur, destinataire). Par défaut, le message n'est accepté que si la marque de temps a plus de 60 secondes. Ceci arrête le pourriel venant d'adresses aléatoires et les messages envoyés et celui envoyé par un proxy ouvert sélectionné aléatoirement, ainsi que celui envoyé par des spammers qui changent leur adresse fréquemment.
Copiez exemples/smtpd-policy/greylist.pl dans le répertoire /usr/libexec/postfix ou un autre emplacement plus approprié à votre système.
Vous devez indiquer la l'emplacement du fichier de base de données de la liste grise dans le fichier greylist.pl, et combien de temps les messages doivent être retardés avant d'être acceptés. Les valeurs par défaut sont :
$database_name="/var/mta/greylist.db"; $greylist_delay=60;
Le répertoire /var/mta (ou celui que cous choisirez) doivent avoir les droits en écriture pour "nobody" ou pour l'utilisateur utilsé dans le fichier master.cf pour le service de politique.
Exemple :
# mkdir /var/mta # chown nobody /var/mta
Note: ne créez PAS la base de données de la liste grise dans un répertoire positionné en écriture pour tout le monde tell /tmp ou /var/tmp et ne la créez PAS dans un système de fichiers susceptible d'être saturé. Postfix peut survivre dans des conditions de saturation de file d'attente ou de stockage des boîtes-aux-lettres mais pas avec une base corrompue. Dans ce dernier cas vous ne recevrez du courrier que lorsque vous aurez effacé ce fichier à la main.
Le script Perl greylist.pl peut être lancé sous le contrôle du démon master.cf. Par exemple pour le lancer sous le compte "nobody" en utilisant une socket UNIX accessible à Postfix, inscrivez simplement :
1 /etc/postfix/master.cf: 2 policy unix - n n - - spawn 3 user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl 4 5 /etc/postfix/main.cf: 6 policy_time_limit = 3600
Notes :
Ligne 3 : utilisez "greylist.pl -v" pour avoir des logs plus bavards pour chaque requête ou réponse.
Lignes 2 et 6 : le démon spawn(8) de Postfix tue par défaut tous les processus après 1000 secondes. C'est trop court pour un démon de politique qui doit fonctionner aussi longtemps qu'un client est connecté à un processus du serveur SMTP. Cette limite peut être outrepassée en renseignant le paramètre "policy_time_limit" du fichier main.cf. Le nom du paramètre est le nom de l'entrée dans le fichier master.cf ("policy") accolée au suffixe "_time_limit".
Sur Solaris vous devez utiliser des sockets TCP au lieu des sockets UNIX comme indiqué au paragraphe "Policy client/server configuration" ci-dessus.
1 /etc/postfix/master.cf: 2 127.0.0.1:9998 inet n n n - - spawn 3 user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl 4 5 /etc/postfix/main.cf: 6 127.0.0.1:9998_time_limit = 3600
Pour appeler ce service, vous devez indiquer "check_policy_service inet:127.0.0.1:9998".
Il est relativement sécurisé d'activer la mise en liste grise pour des domaines apparaissant souvent dans les messages forgés. Une liste des domaines fréquemment utilisés dans les commandes MAIL FROM est disponible à l'adresse suivante : http://www.monkeys.com/anti-spam/filtering/sender-domain-validate.in.
1 /etc/postfix/main.cf: 2 smtpd_recipient_restrictions = 3 reject_unlisted_recipient 4 ... 5 reject_unauth_destination 6 check_sender_access hash:/etc/postfix/sender_access 7 ... 8 restriction_classes = greylist 9 greylist = check_policy_service unix:private/policy 10 11 /etc/postfix/sender_access: 12 aol.com greylist 13 hotmail.com greylist 14 bigfoot.com greylist 15 ... etc ...
NOTES :
Ligne 9 : Sur Solaris vous devez utiliser des sockets réseau au lieu des sockets UNIX comme indiqué au paragraphe "Exemple: serveur de politique liste grise" ci-avant.
Ligne 6 : Assurez-vous d'insérer "check_sender_access" APRÈS "reject_unauth_destination" sinon votre système risque de devenir un relais ouvert.
Ligne 3 : Sur les version 2.0 et antérieures de Postfix, "reject_unlisted_recipient" est appelé "check_recipient_maps". Postfix 2.1 accepte les deux syntaxes.
Ligne 3 : La base de données de la liste grise est rapidement poluée avec les adresses invalides. Protégez la liste grise avec d'autres restrictions qui rejettent les destinataires et expéditeurs inconnus.
Si vous activez la liste grise pour tout le courrier, vous souhaiterez probablement faire des exceptions pour les listes de distributions qui utilisent une adresse d'expédition changeante car de telles listes peuvent polluer relativement rapidement la base de données de la liste grise.
1 /etc/postfix/main.cf: 2 smtpd_recipient_restrictions = 3 reject_unlisted_recipient 4 ... 5 reject_unauth_destination 6 check_sender_access hash:/etc/postfix/sender_access 7 check_policy_service unix:private/policy 8 ... 9 10 /etc/postfix/sender_access: 11 securityfocus.com OK 12 ...
NOTES :
Ligne 7 : Sur Solaris vous devez utiliser des sockets TCP et non UNIX comme indiqué au paragraphe "Exemple: serveur de politique liste grise" ci-avant.
Lignes 6 et 7 : Assurez vous d'insérer check_sender_access et check_policy_service APRÈS reject_unauth_destination sinon votre système risque de devenir un relais ouvert.
Ligne 3 : La base de données de la liste grise est rapidement poluée avec les adresses invalides. Protégez la liste grise avec d'autres restrictions qui rejettent les destinataires et expéditeurs inconnus.
La base de données de la liste grise s'accroît au fil du temps car le serveur de politique ne retire jamais d'entrées. Sans surveillance, elle risque de saturer votre système.
Lorsque ce fichier dépasse un certain seuil, vous pouvez simplement le renommer ou le détruire sans effet nuisible; Postfix le recrééra automatiquement. Dans le pire des cas, les nouveaux messages seront retardés d'une heure. Pour minimiser cet impact, effectuez cette opération au milieu de la nuit ou le week-end.
Ci-dessous une sous-routine Perl qui implémente la politique liste grise citée en exemple. C'est une partie de l'exemple inclus dans les sources de Postfix (exemples/smtpd-policy/greylist.pl).
# # greylist status database and greylist time interval. DO NOT create the # greylist status database in a world-writable directory such as /tmp # or /var/tmp. DO NOT create the greylist database in a file system # that can run out of space. # $database_name="/var/mta/greylist.db"; $greylist_delay=60; # # Demo SMTPD access policy routine. The result is an action just like # it would be specified on the right-hand side of a Postfix access # table. Request attributes are available via the %attr hash. # sub smtpd_access_policy { my($key, $time_stamp, $now); # Open the database on the fly. open_database() unless $database_obj; # Lookup the time stamp for this client/sender/recipient. $key = lc $attr{"client_address"}."/".$attr{"sender"}."/".$attr{"recipient"}; $time_stamp = read_database($key); $now = time(); # If new request, add this client/sender/recipient to the database. if ($time_stamp == 0) { $time_stamp = $now; update_database($key, $time_stamp); } # The result can be any action that is allowed in a Postfix access(5) map. # # To label the mail, return ``PREPEND headername: headertext'' # # In case of success, return ``DUNNO'' instead of ``OK'', so that the # check_policy_service restriction can be followed by other restrictions. # # In case of failure, return ``DEFER_IF_PERMIT optional text...'', # so that mail can still be blocked by other access restrictions. # syslog $syslog_priority, "request age %d", $now - $time_stamp if $verbose; if ($now - $time_stamp > $greylist_delay) { return "dunno"; } else { return "defer_if_permit Service temporarily unavailable"; } }
traduction par Xavier Guimard - Retour au menu