Howto Postfix
- Installation
- Configuration
- Administration
- Plomberie
- Monitoring
- Délivrabilité
- Postcreen
- FAQ
- Envoyer un mail de test en CLI
- Récupérer expéditeur et destinataire dans mail.log
- Taille maximum d’un message
- SMTPUTF8
- Relai vers Mailjet selon l’expéditeur
- .forward
- vacation
- Restreindre selon le From
- Transporter les mails vers un autre serveur et/ou port
- Date et Maildir
- warning: service “smtp” (25) has reached its process limit “100”
- Header Checks
- Comment désactiver l’IPv6 pour Postfix ?
- Délivrabilité vers Microsoft
- entête Received:
- postsrsd
- renvoi vers d’autres serveurs
- Alignement HELO avec le reverse DNS
- Postfix is using backwards-compatible default settings
- warning: TLS library problem: error:0A0000C1:SSL routines::no shared cipher
- soft_bounce = yes
- Documentation : http://www.postfix.org/documentation.html
- Options
main.cf
: https://www.postfix.org/postconf.5.html - Rôle Ansible : https://gitea.evolix.org/evolix/ansible-roles/src/branch/stable/postfix
- Statut de cette page : prod / bookworm
Postfix est serveur SMTP libre et populaire sous GNU/Linux et BSD. Il a été développé en 1999 par Wietse Venema comme une alternative plus facile à administrer et plus sécurisée que l’historique Sendmail.
Un serveur SMTP, appelé aussi MTA (Mail Transport Agent), est l’élément principal d’un serveur d’emails. Tout email transite forcément par un serveur SMTP dont il existe de nombreuses implémentations libres (Postfix, Exim, Sendmail, Qmail etc.) ou propriétaires (Microsoft Exchange, Sun Java System Messaging Server, IBM Lotus Domino, etc.).
Installation
# apt install postfix
# postconf -d | grep ^mail_version
mail_version = 3.7.11
# systemctl status postfix
● postfix.service - Postfix Mail Transport Agent
Loaded: loaded (/lib/systemd/system/postfix.service; enabled; preset: enabled)
Active: active (exited) since Mon 2024-10-21 21:26:44 CEST; 3h 35min ago
Docs: man:postfix(1)
Process: 548168 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
Main PID: 548168 (code=exited, status=0/SUCCESS)
Configuration
Postfix n’est pas monolithique : le processus master
tourne en permanence et gère le démarrage d’autres processus qui ont des
tâches dédiées (cleanup, smtpd, pickup, etc.) notamment la transition
entre les différentes files d’attente de Postfix (incoming, active,
deferred, corrupt, hold). La configuration de ces processus se trouve
dans le fichier /etc/postfix/master.cf
. Et le fichier
/etc/postfix/main.cf
gère les nombreuses options de
configuration.
L’utilitaire postconf permet de lister/vérifier les
options du main.cf
.
## Vérifier la validité de la configuration (check conf)
# postconf >/dev/null
## Lister les options par défaut
# postconf -d
## Lister les options actuelles
# postconf
## Lister les options modifiées par rapport au défaut
# postconf -n
## Manpage très détaillée sur toutes les options disponibles
# man 5 postconf
Configuration minimale
Pour une configuration minimale, nous conseillons d’avoir le fichier
main.cf
suivant en ajustant le paramètre
myhostname avec un enregistrement DNS existant pointant vers le
serveur concerné :
smtpd_banner = $myhostname ESMTP mail server
biff = no
append_dot_mydomain = no
myhostname = hosting.example.com
#smtp_helo_name = $myhostname
#myorigin = $myhostname
mydestination = $myhostname localhost.localdomain localhost localhost.$mydomain
mynetworks = 127.0.0.0/8
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
relayhost =
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
disable_vrfy_command = yes
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtp_tls_security_level = may
smtp_tls_mandatory_protocols=!SSLv2,!SSLv3
smtp_tls_protocols=!SSLv2,!SSLv3
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_loglevel = 1
compatibility_level=3.6
Configuration minimale pour serveur web
N.B. : cette configuration complète la configuration minimale donnée plus haut.
Un serveur web va souvent envoyer des emails, et notamment vers des
fournisseurs d’accès connus (gmail.com, orange.fr, etc.). On conseille
donc d’ajouter les options suivantes dans main.cf
pour
gérer le rythme d’envoi :
#delay_warning_time = 4h
minimal_backoff_time = 15m
maximal_backoff_time = 6h
maximal_queue_lifetime = 4d
queue_run_delay = 100s
bounce_queue_lifetime = 1d
initial_destination_concurrency = 5
default_destination_concurrency_limit = 20
slow_destination_rate_delay = 0
slow_destination_concurrency_limit = 1
slow_destination_concurrency_failed_cohort_limit = 100
slow_destination_recipient_limit = 25
transport_maps = hash:$config_directory/transport
et on ajoute la ligne suivante dans master.cf
:
slow unix - - n - - smtp -o syslog_name=postfix-slow
Il faut également créer le fichier
/etc/postfix/transport
et indiquer des domaines vers
lesquels le rythme d’envoi sera plus lent (à cause de restrictions de
leur côté) :
orange.fr slow:
wanadoo.fr slow:
voila.fr slow:
laposte.net slow:
On fera ensuite :
# postmap /etc/postfix/transport
# systemctl restart postfix
On peut ensuite vérifier que la configuration est bien prise en compte en regardant dans les logs de Postfix. On doit pouvoir observer des processus « postfix-slow » pour tous les domaines concernés.
alias
Postfix utilise par défaut une base d’alias située dans le fichier
/etc/aliases
.
Voici un exemple :
root: jdoe
abuse: root
noc: root
security: root
postmaster: msmith
MAILER-DAEMON: postmaster
daemon: /dev/null
bin: /dev/null
sys: /dev/null
hey: foo@example.com
hello: foo@example.com, bar@example.com
Si l’on modifie /etc/aliases
il faut ensuite la «
regénérer » pour qu’elle soit prise en compte :
# newaliases
Configuration avancée pour serveur de messagerie
Voici un exemple détaillé de fichier main.cf
avec des
commentaires en français :
Section : Emplacements
## fichier principal de configuration de Postfix
## commentaires de Gregory Colpart reg AT evolix DOT fr
## version 1.0 : 1ere version publique (05.04.2010)
########################
# Section : Emplacements
########################
# Repertoire ou se trouvent les commandes de postfix [OBLIGATOIRE]
#par defaut, = $program_directory
command_directory = /usr/sbin
# Repertoire ou se trouvent les demons de postfix [OBLIGATOIRE]
#par defaut, = $program_directory
daemon_directory = /usr/lib/postfix
# Variable pour indiquer les emplacements des commandes et demons de postfix
#program_directory = /usr/lib/postfix
# Repertoire contenant les fichiers de boites aux lettres
#par defaut, = /var/mail
#mail_spool_directory =
# Repertoire de la file d'attente de postfix
#par defaut, = /var/spool/postfix
#queue_directory =
# Boites aux lettres
#par defaut, =
home_mailbox = Maildir/
# Transmettre les mails a un MDA
#par defaut, =
#mailbox_command = /usr/bin/procmail
# Separateur entre noms d'utilisateur et extensions d'adresse
# mettre + pour intégration avec amavis
#par defaut, =
recipient_delimiter = +
# Controle si le repertoire existe (souvent pour les systemes de fichiers montes)
#par defaut, = no
#require_home_directory =
# Commande pour transmettre le courrier a un MDA
#par defaut, =
#mailbox_command = /usr/bin/procmail
# Banniere SMTP affichee
#par default, = $myhostname ESMTP $mail_name
smtpd_banner = $myhostname ESMTP mail server
# Groupe des commandes set-gid ayant des acces en ecriture
#par defaut, = postdrop
# setgid_group = postdrop
# Produire des "biff notifications" aux utilisateurs pour
# prevenir de l'arrivee de nouveaux mails
# par default, = yes
#biff = no
Section : domaines
####################
# Section : domaines
####################
# Indique le nom d'hote pleinement qualifie ou se trouve postfix [OBLIGATOIRE]
#par defaut, = [retour de la commande Unix hostname]
myhostname = hosting.example.com
# Variable indiquant le domaine dans lequel se trouve la machine
#par defaut, = [partie domain de la variable $myhostname]
#mydomain =
# Liste des noms de domaine (ou IP) consideres comme local
#par defaut, = $myhostname, localhost.$mydomain, localhost
mydestination = $myhostname
# Indique le domaine apparaissant dans le courrier envoye
#par defaut, = $myhostname
myorigin = example.com
# Liste de domaine fonctionnant UNIQUEMENT avec des alias virtuels
#par defaut, = $virtual_alias_maps
virtual_alias_domains = [ domaines avec alias virtuels ]
# Liste de domaine fonctionnant avec des comptes virtuels
#par defaut, = $virtual_mailbox_maps
virtual_mailbox_domains = [ domaines avec comptes virtuels ]
# Repertoire de base de l'espace de stockage
#par defaut, =
virtual_mailbox_base = /
# Ajoute $mydomain aux adresse ne compoirtant que la partie hote sans le domaine
#par defaut, = yes
#append_dot_mydomain = no
# Ajoute $myorigin aux adresses ne comportant pas de composante de domaine
#par defaut, = yes
#append_at_myorigin = no
# Liste de domaines cachant des sous-domaines internes
#par defaut, =
#masquerade_domains =
# A l'exception de certains comptes :
#par defaut, =
#masquerade_exceptions = root, admin
# Champs d'application de la reecriture des sous-domaines caches
#par defaut, = envelope_sender, header_sender, header_recipient
#masquerade_classes =
# Sites eligibles pour un vidage rapide (postqueue -s [domain.tld])
#par defaut, = $relay_domains
#fast_flush_domains =
# Interfaces sur lesquelles ecoutent postfix
#par defaut, = all
#inet_interfaces = all
# Envoyer les mails avec une IP spécifique
smtp_bind_address = 192.168.1.1
# Adresse IP externe du firewall/proxy si derriere NAT ou proxy
# evite principalement les boucles si MX secondaire et MX primaire indisponible
#par defaut, =
#proxy_interfaces = [adresse IP]
# Domaines acceptes pour faire relai (MX 2aire)
#relay_domains = [domaine a relayer]
Section : base de donnees
###########################
# Section : base de donnees
###########################
# Liste des bases de donnees utilisees par l'agent de distribution locale
# Pour regenerer une base de donnees : postalias /etc/aliases (par ex)
#par defaut, = hash:/etc/aliases, nis:mail.aliases
alias_maps = hash:/etc/aliases hash:/etc/postfix/liste_diff ldap:ldapaliases
# Liste des bases de donnees locales
# Pour regenerer avec newaliases
#par defaut, = hash:/etc/aliases
alias_database = hash:/etc/aliases hash:/etc/postfix/liste_diff
# Chemin vers la commande newaliases
#par defaut, = /usr/bin/newaliases
#newaliases_path =
# Base de donnes d'alias virtuels
# ne pas oublier : postmap /etc/postfix/virtual
#par defaut, = $virtual_maps
virtual_alias_maps = hash:/etc/postfix/virtual
# Base de donners des boites virtuelles
# ne pas oublier : postmap /etc/postfix/vmailbox
#par defaut, =
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
# Reecriture des adresses
#par defaut, =
#canonical_maps = hash:/etc/postfix/canonical
# Reecriture des adresses a l'arrivee (ecrase $canonical_maps)
#par defaut, =
#recipient_canonical_maps = hash:/etc/postfix/canonical
# Reecriture des adresses au depart
#par defaut, =
#sender_canonical_maps = hash:/etc/postfix/canonical
# Adresses changees
#relocated_maps = hash:/etc/postfix/relocated
# Boite pour receptionner tous les utilisateurs inconnus
#luser_relay = spam
# Liste de base de donnees contenant les adresses locales permettant de rejeter les messages aux utilisateurs inconnus
# (sera nulle pour recuperer les courriels vers les utilisateurs inconnus)
#par defaut, = proxy:unix:passwd.byname $alias_maps
#local_recipient_maps =
# MAILING-LIST nommee xx
# dans le fichier /etc/aliases :
# xx: user1@domain1 user2@domain2 etc.
# owner-xx: admin@domain
# Utiliser ou non l'alias xx-owner comme adresse d'enveloppe d'expedition
#par defaut, = yes
#owner_request_special =
# Utiliser l'adresse relle de l'admin au lieu de xx-owner
#par defaut, = no
#expand_owner_alias =
Section : paramètres de la file d’attente
###########################################
# Section : parametres de la file d'attente
###########################################
# Lorsqu'un message n'a pas ete delivre, Postfix adjoint une marque indiquant le moment ou la prochaine tentaive pourra avoir lieu
# Delai au-dela duquel les messages non delivres seront renvoyes a l'expediteur
#par defaut, = 5d
#maximal_queue_lifetime =
# Intervalle de temps ou postfix examinera la file
# Il examine notamment la file deferred pour voir si de NOUVEAUX messages sont arrives
# Il faut aussi que la marque indique qu'ils soient prets
#par defaut, = 1000s
#queue_run_delay =
# A chaque echec, le delai de la prochaine distribution double, avec les restrictions suivantes :
# Delai minimal
#par defaut, = 1000s
#minimal_backoff_time =
# Delai maximal
#par defaut, = 4000s
#maximal_backoff_time =
# Si maxproc est vide (master.cf), nombre maximal est :
#par defaut, = 100
#default_process_limit =
# Nombre maximal de destinataires stockes en memoire par qmgr pour un transport particulier
#par defaut, = 10000
#default_recipient_limit =
# Nombre limitant de messages envoyes simultanement INITIALEMENT pour une destination particuliere
# (forcement majoree par maxproc du master.cf ou $default_process_limit)
#par defaut, = 5
#initial_destination_concurrency =
# Une fois ces messages distribues, si il reste des messages dans la file d'attente pour cette destination
# particuliere, postfix augmente le nombre de tentative tant qu'il ne detecte pas de probleme avec
# la destination, avec la limite suivante :
#par defaut, = 20
#default_destination_concurrency_limit =
# Cette limite peut etre differente selon le type de transport utilise :
#par defaut, = $default_destination_concurrency_limit
#lmtp_destination_concurrency_limit =
#par defaut, = 2
#local_destination_concurrency_limit =
#par defaut, = $default_destination_concurrency_limit
#relay_destination_concurrency_limit =
#par defaut, = $default_destination_concurrency_limit
#smtp_destination_concurrency_limit =
#par defaut, = $default_destination_concurrency_limit
#virtual_destination_concurrency_limit =
# On peut aussi limiter le nombre maximum de destinataire pour un meme message
# Si le nombre de destinataire depasse la limite, postfix divise en groupe d'adresses plus petites et envoie des copies distinctes du message
#par defaut, = 10000
#default_destination_recipient_limit =
#par defaut, = $default_destination_recipient_limit
#lmtp_destination_recipient_limit =
#par defaut, = 1
#local_destination_recipient_limit =
#par defaut, = 20000
#qmgr_message_recipient_limit =
#par defaut, = $default_destination_recipient_limit
#relay_destination_recipient_limit =
#par defaut, = $default_destination_recipient_limit
#smtp_destination_recipient_limit =
#par defaut, = 1000
#smtpd_recipient_limit =
#par defaut, = $default_destination_recipient_limit
#virtual_destination_recipient_limit =
# Nombre maximum de destinataires pour un transport lorsque priorite superieure de transport
#par defaut, = 1000
#default_extra_recipient_limit =
# Types d'incidents a rapporter
# resource : message non delivre pour probleme de ressource
# software : message non delivre pour probleme de logiciels
# policy : envoie le transcription smtp d'un message rejete par restrictions
# protocol : envoie toute transcription smtp erronee
# delay : envoie les entetes de messages differes
# bounce : envoie les entetes de tous les message renvoyes
# 2bounce : envoie les entetes de tous les messages renvoyes non delivres
#par defaut, = resource, software
notify_classes = resource, software, bounce, 2bounce, delay, policy, protocol
# A qui les reporter ?
#Pour delay
#par defaut, = postmaster
delay_notice_recipient = delay
#Pour policy, protocol, resource, software
#par defaut, = postmaster
error_notice_recipient = error
#Pour bounce
#par defaut, = postmaster
bounce_notice_recipient = 1bounce
#Pour 2bounce
#par defaut, = postmaster
2bounce_notice_recipient = 2bounce
Section : restrictions
########################
# Section : restrictions
########################
# Restrictions au depart de la conversation
#par defaut, =
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, check_client_access hash:/etc/postfix/acces_client
# Restrictions au niveau de la commande HELO/EHLO
#par defaut, =
smtpd_helo_restrictions = reject_invalid_hostname
# Restrictions au niveau de la commande MAIL FROM
#par defaut, =
smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/acces_expediteur
# Restrictions au niveau de la commande MAIL FROM
#par defaut, = permit_mynetworks, reject_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
# Attendre la commande 'RCPT TO' avant d'evaluer les restrictions ?
# (peut poser pb avec certains clients et permet d'avoir renseignements suppl)
#par defaut, = yes
#smtpd_delay_reject =
# Definition des plages IP appartenant a mynetworks
#par defaut, toutes les plages d'adresses IPv4 (et IPv6) des interfaces
mynetworks = 127.0.0.0/8,[::1]/128,10.0.0.0/16
# Exiger la commande HELO/EHLO
#par defaut, = no
smtpd_helo_required = yes
# Exiger syntaxe conforme dans les commandes MAIL FROM ou RCPT TO
#par defaut, = no
#strict_rfc821_envelopes =
# Rejeter le courrier provenant d'une adresse inexistante ?
#par defaut, = no
#smtpd_reject_unlisted_sender =
# Rejeter le courrier a destination d'une adresse inexistante ?
#par defaut, = yes
#smtpd_reject_unlisted_recipient =
Utilisation avec un annuaire LDAP
Les bases de données d’utilisateurs et de leurs paramètres peuvent être stockés dans une base de données externe. On peut ainsi utiliser une base de donnée ou un annuaire LDAP. Dans le cas de Postfix, on peut l’utiliser avec MySQL ou OpenLDAP.
Dans le fichier main.cf de Postfix, on utilisera une configuration type :
alias_maps = [autres bases] ldap:blabla
blabla_server_host = [serveur ldap]
blabla_search_base = [dn de base]
blabla_result_attribute = [type de champs à chercher]
Dans l’annuaire LDAP on a notamment des champs ressemblant à :
dn: uid=nnom,[dn de base]
objectClass: inetOrgPerson
objectClass: inetLocalMailRecipient
objectClass: posixAccount
sn: Nom
givenName: Prenom
cn: Nom Prenom
displayName: Nom Prenom
mailLocalAddress: pnom@example.com
uid: nnom
userPassword: ****
uidNumber: 1006
gidNumber: 1006
homeDirectory: /chemin_boite/
Prenons un exemple d’une configuration de comptes virtuels. La configuration de Postfix peut être :
virtual_mailbox_domains = virtual.example.com
virtual_mailbox_base = /
virtual_mailbox_maps = ldap:ldapaliases2
ldapaliases2_server_host = localhost
ldapaliases2_search_base = ou=Virtualmail,ou=Mail,dc=example,dc=com
ldapaliases2_bind = yes
ldapaliases2_bind_dn = cn=Manager,ou=Virtualmail,ou=Mail,dc=example,dc=com
ldapaliases2_bind_pw = ******
ldapaliases2_query_filter = (mailLocalAddress=%s)
ldapaliases2_result_attribute = homeDirectory
Au niveau de l’annuaire LDAP :
dn: uid=mvegas,ou=Onlymail,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: inetLocalMailRecipient
objectClass: posixAccount
sn: Vegas
givenName: Mister
cn: Virtual Mister
displayName: Mister Vegas
mailLocalAddress: mvegas@example.com
uid: mvegas
userPassword: ****
uidNumber: 1006
gidNumber: 1006
homeDirectory: /home/vmail/virtual.example.com/mvegas/
Quelques remarques :
Il faut qu’il y ait les permissions sur le homeDirectory. Dans ce cas, les répertoires seront créés automatiquement lors du premier mail reçu.
Vous pouvez obtenir des messages de ce genre :
warning: dict_ldap_connect: Unable to bind to server ldap://localhost:389 as : 2 (Protocol error)
Il faut alors ajouter au fichier slapd.conf :
allow bind_v2
SSL/TLS
http://www.postfix.org/TLS_README.html
Il est désormais fortement conseiller d’activer le chiffrement SSL/TLS entre les serveurs SMTP pour éviter de faire circuler en clair les informations (identifiants, contenu des messages) et s’assurer que l’on s’adresse au bon serveur.
Activation SSL/TLS au niveau serveur SMTP (smtpd)
Activer SSL/TLS au niveau serveur SMTP permet la réception d’emails depuis des clients SMTP capables d’envoyer en SSL/TLS.
Il faut générer une clé privée et un certificat, voir HowtoSSL. On peut ensuite
activer via le fichier /etc/postfix/main.cf
:
smtpd_tls_security_level = may
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
smtpd_tls_protocols=!SSLv2,!SSLv3
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_loglevel = 1
smtpd_tls_key_file = /etc/ssl/private/smtp.example.com.key
smtpd_tls_cert_file = /etc/ssl/certs/smtp.example.com.crt
smtpd_tls_CAfile = /etc/ssl/certs/GandiStandardSSLCA2.pem
Note 1 : la désactivation des protocoles SSLv2 et SSLv3 est désormais par défaut, mais on préfère garder cette option
Note 2 : Pour Debian 7 et 8, on conseille d’ajouter également :
smtpd_tls_mandatory_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL smtpd_tls_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL smtpd_tls_mandatory_ciphers = medium
Pour l’envoi d’emails depuis des clients SMTP authentifiés
(smtpd_sasl_auth_enable=yes), on active en général le port
TCP/587 (appelé SMTP Submission) qui n’accepte que des
connexions chiffrées (smtpd_tls_security_level=encrypt) et le
port TCP/465 (appelé SMTPS) qui n’accepte que des connexions
SMTP over TLS (smtpd_tls_wrappermode=yes). Ces activations se
font en décommentant les lignes appropriées dans
/etc/postfix/master.cf
:
submission inet n - - - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - - - - smtpd
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
Dans le cas d’utilisation de Let’s Encrypt voici un exemple de configuration à utiliser :
smtpd_tls_key_file = /etc/letsencrypt/live/smtp.example.com/privkey.pem
smtpd_tls_cert_file = /etc/letsencrypt/live/smtp.example.com/fullchain.pem
On peut ensuite vérifier l’activation de SSL/TLS au niveau serveur en
obtenant le message STARTTLS
dans une session SMTP :
$ telnet bugs.debian.org 25
Trying 209.87.16.39...
Connected to bugs.debian.org.
Escape character is '^]'.
220 buxtehude.debian.org
EHLO example.com
250-buxtehude.debian.org Hello example.com [80.12.63.254]
250-SIZE 104857600
250-8BITMIME
250-STARTTLS
250 HELP
QUIT
221 buxtehude.debian.org closing connection
Connection closed by foreign host.
On peut également utiliser une connexion chiffrée avec un serveur SMTP via la commande :
$ openssl s_client -CApath /etc/ssl/certs -connect smtp.example.com:25 -crlf -starttls smtp
Activation SSL/TLS au niveau client SMTP (smtp)
Activer SSL/TLS au niveau client SMTP permet d’envoyer des emails vers des serveurs SMTP capables de recevoir en SSL/TLS.
On conseille d’activer cela par défaut via le fichier
/etc/postfix/main.cf
:
smtp_tls_security_level = may
smtp_tls_mandatory_protocols=!SSLv2,!SSLv3
smtp_tls_protocols=!SSLv2,!SSLv3
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_loglevel = 1
Note : la désactivation des protocoles SSLv2 et SSLv3 est désormais par défaut, mais on préfère garder cette option
Debug
On peut activer smtp_tls_loglevel = 2
ou
smtpd_tls_loglevel = 2
pour avoir des logs verbeux sur le
SSL handshake
Authentification SMTP
Cette solution est décrite dans la RFC 2554 : SMTP Service Extension for Authentication. Il faut néanmoins prendre garde, car cette possibilité fait baisser le niveau de sécurité de votre service. En effet, tout repose désormais sur les paramètres d’authentification et, outre des moyens sociaux, il faut veiller à ce que ces paramètres ne soient pas interceptés, c’est-à-dire ne circulent pas en clair sur des canaux non sécurisés. Il sera donc prudent de rajouter une couche de chiffrement, ou alors d’exclure certains types d’authentification comme les types PLAIN ou LOGIN.
Un mécanisme d’authentification souvent utilisé est SASL (Simple Authentication and Security Layer), librairie développée par le projet Cyrus. La lecture du document Cyrus SASL for System Administrators donnera des élements pour installer et configurer conrrectement une authentification basée sur la librairie Cyrus. L’installation se fera à partir des sources ou de paquets (sasl2-bin libsasl2 libsasl2-modules). Certains modules sont optionnels et permettent d’utiliser diverses méthodes d’authentification (libsasl2-modules-gssapi-heimdal libsasl2-modules-kerberos-heimdal). Sous Debian Sarge, on installera le paqut postfix-tls qui contient notamment les extensions SASL pour Postfix.
Plusieurs bases d’authentification sont possibles selon les configurations :
shadow : authentification basée sur le fichier /etc/shadow
pam utilise directement les librairies PAM (on peut donc par exemple utiliser LDAP ou RADIUS)
pwcheck : authentification basée sur le deamon pwcheck utilisant aussi le fichier /etc/shadow (précision pour Debian Sarge : saslauthd est dans le paquet cyrus-common)
saslauthd : authentification basée sur le deamon saslauthd qui est plus flexible que pwcheck et peut utiliser PAM (mais aussi shadow, ldap, kerberos, etc,.) (précision pour Debian Sarge : saslauthd est dans le paquet sasl2-bin)
La configuration s’effectue dans dans /etc/default/saslauthd :
START=yes
MECHANISMS="pam"
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"
Et ajouter l’utilisateur postfix
au groupe
sasl
.
On vérifie la validité des utilisateurs par :
$ testsaslauthd -u username -p password
Note : attention, sous Debian Sarge, testsaslauth ne tient apparemment pas compte du mécanisme passé en paramètre de saslauthd, c’est OK depuis Etch
saslauthd utilise le fichier pam.d/smtp (ou pam.d/other) dans ce cas (quelques modifications sont nécessaires si Postfix est chrooté, voir section CHROOT) * auxprop (ou sasldb pour SASL version 1) : utilisation de /etc/sasldb(2)
C’est l’authentification utilisée par défaut par Postfix (si aucun paramètre pwcheck_method n’est précisé dans le smtpd.conf)
Commandes : sasldblistusers(2), saslpasswd(2)
Note : possibilité d’utiliser une base de données avec l’option auxprop_plugin: sql (quelques modifications sont nécessaires si Postfix est chrooté, voir section CHROOT)
Si vous utilisez une authentification non disponible, vous obtiendrez probablement :
warning: SASL authentication problem: unknown password verifier
Plusieurs possibilités de type d’authentification : NTLM, LOGIN, PLAIN, DIGEST-MD5, CRAM-MD5, KERBEROS4, GSSAPI, etc.
Nous devons maintenant configurer postfix afin qu’il utilise SASL. Voir Postfix SMTP Authentification.
Nous ajoutons les paramètres suivants :
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated, reject
Un fichier smtpd.conf contiendra la méthode d’authentification et les types disponibles :
pwcheck_method: [choix_methode]
mech_list: [choix_type]
Note concernant Debian Sarge : le paquet authsasld ne permet que les types PLAIN et LOGIN. Si l’on autorise un autre type, il cherchera le fichier /etc/sasldb2 (a priori, le paquet n’a pas été compilé avec les options –enable-cram –enable-digest).
Exemple, authentification en PLAIN :
EHLO [hostname]
AUTH PLAIN [mon_auth]
On obtient [mon_auth] ainsi :
$ printf 'username\0username\0password' | openssl base64
Deuxième exemple, authentification en LOGIN :
EHLO [hostname]
AUTH LOGIN
[mon_login]
[mon_password]
On obtient [mon_login] et [mon_password] ainsi :
$ printf 'username' | openssl base64
$ printf 'password' | openssl base64
Pour en savoir plus, lisez Authentification SASL avec Postfix
On peut aussi restreindre au niveau de Postfix les types d’authentification possibles :
smtpd_sasl_security_options = noanonymous, noplaintext
Authentification client SMTP
Postfix, lorsqu’il communique avec d’autres serveurs en tant que client, peut avoir besoin de s’authentifier. On peut donc lui passer des paramètres d’authentifications pour certains serveurs :
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
Le fichier sasl_passwd contiendra :
foo.com username:password
bar.com username
On peut choisir des options pour le mode compte, par exemple les types d’authentification autorisés :
smtp_sasl_security_options = noplaintext
Gestion du chroot de Postfix
Enfermer Postfix dans un chroot permet de restreindre les accès à d’autres applications en cas de faille de sécurité. Cette protection s’indique au fichier master.cf. Par défaut, cette protection est activée sous Debian. Le répertoire de chroot se situe dans /var/spool/postfix
L’utilisation de chroot impose quelques modifications, notamment si l’on utilise l’authentification SMTP :
saslauthd
Pour SASL avec la méthode saslauthd, il faut préciser la directive suivante dans le fichier /etc/default/saslauthd :
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"
Note : avant Etch, il était nécessaire de réaliser un hack de ce type :
# mkdir /var/spool/postfix/var ; mkdir /var/spool/postfix/var/run
# mv /var/run/saslauthd/ /var/spool/postfix/var/run/
# chown -R postfix /var/spool/postfix/var/run/saslauthd
# ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd
Ne pas oublier de mettre des droits de lecture sur les répertoires /var/spool/postfix/var/ et /var/spool/postfix/var/run/ afin d’autoriser l’utilisateur postfix. L’utilisateur postfix sera ajouté au groupe sasl si nécessaire (si le répertoire saslauthd appartient à root:sasl). Sans ces changements, on obtiendra un message :
warning: SASL authentication failure: cannot connect to saslauthd server: Permission denied
auxprop
Pour SASL avec la méthode auxprop (ou sasldb) :
# mv /etc/sasldb2 /var/spool/postfix/etc/sasldb2
# ln -s /var/spool/postfix/etc/sasldb2 /etc/sasldb2
resolv.conf
Le fichier /etc/resolv.conf est copié dans /var/spool/postfix/etc/resolv.conf. Il faut le tenir synchronisé en cas de modification (notamment en cas d’installation sur un réseau différent du réseau final).
Antispam
Voir /HowtoMail/Antispam.
Administration
Logs
Postfix envoie une trace de ses actions à Syslog avec la
facility LOG_MAIL. On retrouve donc les fichiers de
journalisation définis dans le fichier /etc/rsyslog.conf
:
mail.* -/var/log/mail.log
mail.info -/var/log/mail.info
mail.warn -/var/log/mail.warn
mail.err /var/log/mail.err
Note : ce sont les adresses email d’enveloppe affichées dans les logs Postfix
L’indication delays=a/b/c/d dans les logs est utile pour avoir des informations sur le temps d’envoi d’un mail :
a=time before queue manager, including message transmission;
b=time in queue manager;
c=connection setup time including DNS, HELO and TLS;
d=message transmission time.
File d’attente
Postfix utilise différentes files d’attente (ou queues). Les files d’attente principales sont incoming, active et deferred :
incoming : première étape pour tous les nouveaux messages (après un passage par cleanup)
active : messages en cours de livraison (provenant principalement d'incoming ou deferred)
deferred : messages non délivrés lors du premier essai
Il existe aussi d’autres files d’attente, qui servent beaucoup moins fréquemment : corrupt (messages invalides) et hold (messages mis de côté).
Ces files d’attente sont des répertoires situés dans
/var/spool/postfix
dans lesquels chaque message est stocké
dans un fichier (sur une seule ligne), avec une arborescence de 16
répertoires (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F) pour optimiser lorsqu’un
grand nombre de messages est dans une file d’attente. On peut gérer ces
files d’attente grâce à des commandes d’administration.
Lecture et analyse de la file d’attente
mailq
(ou sendmail -bp
) liste toutes les
files d’attente. Cela nous donne pour chaque message :
- Queue ID
- Taille du message
- Date d’arrivée dans la file d’attente
- Expéditeur
- Éventuelle raison de non-livraison (entre parenthèses)
- Destinataires(s)
Voici dans quel ordre sont listés les messages :
- Messages de la queue active (une étoile figure à côté du Queue ID)
- Messages de la queue deferred
- Messages de la queue hold (un point d’exclamation figure à côté du queue ID)
Afficher le contenu d’un message :
# postcat -vq <queue_id>
Afficher seulement les mails IDs (utile pour les scripts) :
# mailq | sed -E -n 's/^([[:alnum:]]+)[[:blank:]].*/\1/gp'
Exemple d’usage :
keyword="blabla"
ids=$(mailq | sed -E -n 's/^([[:alnum:]]+)[[:blank:]].*/\1/gp')
for id in $ids; do
mail_content=$()
if postcat -q $id | grep -q $keyword; then
echo "$id contains $keyword"
# Faire quelque chose (voir la section suivante "Opérations sur la file d'attente")
fi
done
Exclure les mails en cours d’envoi de l’affichage de la file d’attente :
# mailq | sed -E '/v[[:alnum:]]+\*[[:blank:]]/,+2d'
Compter le nombre d’e-mails par adresse expéditrice dans la
mailq
:
# mailq | awk '$1 ~ /^[0-9A-F]+$/ { a[$NF]++ } END { for (i in a) printf "%d %s\n", a[i], i }' | sort -n
Obtenir la liste les expéditeurs triés par ordre croissant du nombre d’e-mails en attente d’envoi :
# mailq | awk '/^[0-9A-F]+[*!]? /{a[$NF]++}END{for(i in a)print a[i],i | "sort -n"}'
Note : le BEGIN { RS = "" }
est nécessaire car
la sortie de mailq peut être sur plusieurs lignes, et le
tr -d '*!'
permet de ne pas prendre les messages en « hold
».
Lister les messages dans la file d’attente deffered :
# qshape deferred
T 5 10 20 40 80 160 320 640 1280 1280+
TOTAL 78 0 0 0 0 1 0 0 0 0 77
gmail.fr 11 0 0 0 0 0 0 0 0 0 11
homail.fr 3 0 0 0 0 0 0 0 0 0 3
yaoo.fr 2 0 0 0 0 0 0 0 0 0 2
yahou.fr 2 0 0 0 0 0 0 0 0 0 2
oange.fr 2 0 0 0 0 0 0 0 0 0 2
hotmai.fr 2 0 0 0 0 0 0 0 0 0 2
wanado.fr 2 0 0 0 0 0 0 0 0 0 2
orangr.fr 1 0 0 0 0 0 0 0 0 0 1
prange.fr 1 0 0 0 0 0 0 0 0 0 1
ornage.fr 1 0 0 0 0 0 0 0 0 0 1
# Affichage par sender
# qshape -s deferred
#### Opérations sur la file d’attente
Suppressions :
## Supprimer un message (ou tous) des files d'attente :
# postsuper -d <queue_id>
## Supprimer tous les messages de la queue deferred
# postsuper -d ALL deferred
## Supprimer tous les messages des files d'attente :
# postsuper -d ALL
# mailq -q
/!\ Attention, postsuper -d ALL
et mailq -q
réactivent immédiatement l’ensemble des messages en file d’attente, il
faut donc les utiliser avec modération, surtout sur les serveurs avec
des files d’attentes chargées.
Divers :
## Libérer un message (ou tous) en « hold »
# postsuper -H <queue_id>
# postsuper -H ALL
# Refaire passer un message (ou tous) par les process de livraison
# postsuper -r <queue_id>
# postsuper -r ALL
## Purger des fichiers temporaires (en cas de crash par exemple)
# postsuper -p
## Réparer/vérifier l'arborescence des files d'attente
# postsuper -s
La commande postsuper -r
est pratique dans les cas où
l’on a modifié des alias ou des ré-écritures, elle va déposer les
messages concerné dans la queue maildrop et lui attribuer un
nouveau . Attention, cela ne va pas provoquer un envoi
immédiat car le traitement des files d’attente est différé. Si l’on veut
un ré-envoi immédiat d’un message :
Hold :
## Placer en « hold » un message (ou tous)
# postsuper -h <queue_id>
# postsuper -h ALL
## Placer en « hold » tous les messages de la queue deferred
# postsuper -h ALL deferred
Traitement par lot via un pré-filtrage avec Awk :
On pourra utiliser ces commandes sur des ensembles de messages via des scripts du type :
# mailq | tail -n +2 | awk 'BEGIN { RS = "" } /user@example\.com/ { print $1 }' | tr -d '*!' | postsuper -h -
# mailq | tail -n +2 | awk 'BEGIN { RS = "" } /example\.com/ { print $1 }' | tr -d '*!' | postsuper -d -
# mailq | awk '/^[0-9A-Z]+/&&/sender@example\.com$/{print $1}' | tr -d '*!' | postsuper -h -
# mailq | awk '/^[0-9A-Z]+/&&/example\.com$/{print $1}' | tr -d '*!' | postsuper -d -
# mailq > mailq.log ; for var in $(grep <from@example.com> mailq.log | cut -b '1-12'); do postsuper -d $var; done
## Supprimer les e-mails envoyés par someone@some.where
# mailq | awk '/^[0-9A-F]+[!*]? /&&/someone@some\.where$/{gsub("[!*]", "", $1); print $1 | "postsuper -d -"}'
## Supprimer les courriels envoyé vers @example.com
# mailq | tail -n +2 | awk 'BEGIN { RS = "" } /@example\.com$/ { r = $1; gsub(/[!*]/, "", r); print r }' | postsuper -d -
Supprimer les mails correspondant à ce type de ligne :
6B28125849 3039 Fri Sep 25 07:27:53 MAILER-DAEMON
(host mx2.foo.com[1.2.3.4] said: 452 Too many incoming emails for this account (in reply to RCPT TO command))
mail.example.com
# mailq | awk '/^[0-9A-F]+/&&/MAILER-DAEMON$/{id=$1} /mail@example.com$/{print id}' | postsuper -d -
Notifications
Postfix envoie des notifications à ajuster avec l’option
notify_classes
.
On peut ainsi ajuster cette option ainsi :
notify_classes = resource, software, bounce, 2bounce, delay
delay_notice_recipient = delay
error_notice_recipient = error
bounce_notice_recipient = 1bounce
2bounce_notice_recipient = 2bounce
Puis ajuster les alias via /etc/alias
:
error: localadmin
1bounce: postmaster
2bounce: postmaster
delay: alert0@example.com
/!\ Attention, pour un serveur recevant pas mal de messages, cela peut générer pas mal de notifications. Si nécessaire, ajuster ainsi pour avoir un minimum d’alertes :
notify_classes = resource, software
error_notice_recipient = error
Plomberie
Postfix est découpé en plusieurs processus (qmgr, pickup, smtp,
smtpd, bounce, cleanup, error, etc.) contrôlé par un processus nommé
master
. Chaque processus est défini dans le fichier de
configuration master.cf
.
Sur un serveur inactif, vous verrez au minimum les processus suivants :
|-master,432636 -l -t unix -u
| |-qmgr,5036 -l -t unix -u-u -c
| `-pickup,9162 -l -t unix -u -c
Sur un serveur actif, vous verrez de nombreux processus, par exemple :
|-master,2576
| |-scache,13334 -l -t unix -u
| |-qmgr,22888 -l -t fifo -u
| |-anvil,22891 -l -t unix -u
| |-smtp,25261 -t unix -u
| |-smtp,26204 -t unix -u
| |-trivial-rewrite,26596 -n rewrite -t unix -u
| |-smtp,26629 -t unix -u
| |-pickup,27010 -l -t fifo -u
| |-smtp,27102 -t unix -u
| |-smtp,27976 -t unix -u
| |-proxymap,28383 -t unix -u
| |-smtp,29967 -t unix -u
| |-smtp,29968 -t unix -u
| |-smtp,29969 -t unix -u
| |-bounce,29970 -z -t unix -u
| |-bounce,30351 -z -n defer -t unix -u
| |-bounce,30352 -z -n defer -t unix -u
| |-bounce,30354 -z -n defer -t unix -u
| |-bounce,30355 -z -n defer -t unix -u
| |-cleanup,30364 -z -t unix -u
| |-cleanup,30365 -z -t unix -u
| |-smtpd,30366 -n smtp -t inet -u -o stress= -s 2
| |-error,30367 -n retry -t unix -u
| |-error,30368 -n retry -t unix -u
| |-error,30369 -n retry -t unix -u
| `-smtpd,30374 -n smtp -t inet -u -o stress= -s 2
Voici un schéma qui illustre la communication entre les processus/files d’attente/tables :
- Le processus bounce gère les messages de
non-livraison qui sont stockés dans les répertoires
/var/spool/postfix/bounce/*
,/var/spool/postfix/defer/*
ou encore/var/spool/postfix/trace/*
selon les types de message.
Changer les templates de bounce
Par exemple pour mettre un message personnalisé (et en Français) des DSN du type « successful delivery ».
Installer le paquet postfix-doc
, copier le fichier
bounce.cf.default
dans /etc/postfix/bounce.cf
,
éditer le fichier comme voulu et ajouter la directive
bounce_template_file = /etc/postfix/bounce.cf
à
postfix.
# apt install postfix-doc
# install -m 644 /usr/share/doc/postfix-doc/examples/bounce.cf.default /etc/postfix/bounce.cf
# vim /etc/postfix/bounce.cf
# echo "bounce_template_file = /etc/postfix/bounce.cf" >> /etc/postfix/main.cf
# systemctl reload postfix
Monitoring
La surveillance régulière des fichiers de journalisation ainsi que des files d’attente s’avère nécessaire, éventuellement à l’aide d’outils permettant de générer des statistiques, des courbes, etc. On peut ainsi citer l’outil mailgraph qui trace des courbes rrdtool à partir du fichier de journalisation, ou encore Munin qui trace des courbes selon l’état des files d’attente.
mailgraph
# apt install mailgraph
mailgraph fait tourner
un démon Perl qui analyse /var/log/mail.log
, on peut
ensuite visualiser des courbes RRDtool via un script CGI
/usr/lib/cgi-bin/mailgraph.cgi
.
Pour diverses raisons, si l’on ne veut pas avoir de module CGI on pourra utiliser un script Shell à placer en crontab :
#!/bin/sh
MAILGRAPH_PATH=/usr/lib/cgi-bin/mailgraph.cgi # Debian
MAILGRAPH_DIR=/var/www/mailgraph
umask 022
mkdir -p $MAILGRAPH_DIR
$MAILGRAPH_PATH | sed '1,2d ; s/mailgraph.cgi?//' > $MAILGRAPH_DIR/index.html
for i in 0-n 0-e 1-n 1-e 2-n 2-e 3-n 3-e; do
QUERY_STRING=$i $MAILGRAPH_PATH | sed '1,3d' > $MAILGRAPH_DIR/$i
done
Munin
Par défaut, on trouve des plugins intéressants, notamment postfix_mailqueue pour l’évolution des files d’attente. Pour activer les plugins Postfix pour Munin :
# cd /etc/munin/plugins
# ln -s /usr/share/munin/plugins/postfix_mailqueue
# ln -s /usr/share/munin/plugins/postfix_mailstats
# ln -s /usr/share/munin/plugins/postfix_mailvolume
Nagios
Voici des checks standards pour vérifier que Postfix répond en SMTP et surveiller sa file d’attente :
$ /usr/lib/nagios/plugins/check_smtp -H localhost
$ /usr/lib/nagios/plugins/check_mailq -M postfix -w 42 -c 1337
log2mail
Pour être alerté en cas d’erreurs graves, voici une config pour log2mail :
file = /var/log/mail.log
pattern = "fatal:"
mailto = alert@example.com
pattern = "panic:"
mailto = alert@example.com
pattern = "No such file or directory"
mailto = alert@example.com
pattern = "table lookup problem"
mailto = alert@example.com
pattern = "warning: connect to Milter service"
mailto = alert@example.com
pattern = "451 4.7.1 Service unavailable - try again later"
mailto = alert@example.com
pflogsumm
C’est un petit outil pour afficher des stats sur les logs mails.
Plutôt pratique, il évite de « grepper » à la main
mail.log
.
pflogsumm /var/log/mail.log [/var/log/mail.log.1 [...]] >> stats_mail.out
Délivrabilité
La délivrabilité est un concept visant à s’assurer qu’un email envoyé va bien atteindre son destinataire.
Voici un check-up pour s’assurer d’avoir une bonne délivrabilité :
- Reverse DNS configuré vers un enregistrement valide pointant lui-même vers l’adresse IP du serveur mail
- IPv6 correctement configuré (avec reverse DNS) ou desactivé
- Utiliser une adresse de retour valide (expéditeur d’enveloppe ou Return-Path) et traiter les retours régulièrement voire dynamiquement en cas de gros volume
- Configurer SPF
- Configurer DKIM
- Configurer DMARC
- Nettoyer ses entêtes, notamment des informations locales (IP RFC1918, enregistrements DNS locaux, etc.)
- S’enregistrer auprès de http://www.dnswl.org/
- S’enregistrer auprès de http://www.emailreg.org/ (payant, environ 20$/domaine/an)
- Pour Hotmail/Outlook/Microsoft/Office365, faire un ticket support depuis sender.office.com et ce formulaire https://support.microsoft.com/en-us/supportrequestform/8ad563e3-288e-2a61-8122-3ba03d6b8d75 pour autoriser IPv4.
- Payer validity.com (ex-ReturnPath) pour améliorer sa délivrabilité auprès de Yahoo/Microsoft/etc. (tarif en fonction du volume)
- Régler son rythme d’envoi, notamment vers Orange, Free, etc.
- Vérifier son contenu via des outils comme SpamAssassin
- Vérifier la réputation via https://www.talosintelligence.com/reputation_center/email_rep
- Vérifier via Postmaster tools de Google en cas de problème de Spam pour Google/Gmail
- Vérifier via https://sendersupport.olc.protection.outlook.com/snds/ en cas de problème de Spam pour Microsoft/Hotmail/Live
SPF
SPF est
une norme pour vérifier l’adresse IP expéditrice d’un email. La
vérification se fait en utilisant le nom de domaine de l’expéditeur
d’enveloppe (MAIL FROM:
) et en récupérant un enregistrement
DNS qui va lister les adresses IP autorisées. La vérification peut aussi
se faire par rapport au FQDN annoncé dans le HELO (cf [(RFC 7208,
2.3](
Voici un exemple d’enregistrement DNS pour du SPF :
@ IN TXT "v=spf1 mx ip4:192.0.2.142 ip4:192.0.2.0/24 ip6:2001:db8::/32 -all"
Voici un exemple d’enregistrement DNS n’autorisant aucun envoi (à mettre pour vos domaines voire sous-domaines qui n’envoient jamais d’emails) :
@ IN TXT "v=spf1 -all"
On peut utiliser des include:
vers un autre
enregistrement TXT.
Chez Evolix, on utilise ainsi
include:spf.protection.evolix.net
. Si vous utilisez Mailchimp
vous devez ajouter include:spf.mandrillapp.com
par
exemple.
Il faut savoir que l’on peut contourner la longueur maximale de 255 caractères pour un enregistrement TXT en concatener plusieurs chaînes. On notera qu’au moins une des deux chaînes doit contenir une espace. Voici un exemple :
@ IN TXT "v=spf1 mx ip4:192.0.2.142 ip4:192.0.2.0/24" " ip6:2001:db8::/32 ~all"
En pratique il est conseillé d’éviter une longueur totale du champ
TXT (FQDN compris) de plus de 450 octets (à vérifier via
MSG SIZE rcvd:
avec dig
).
Il est également conseillé de ne pas mettre plus de 101 adresses ou préfixes IP (Gmail refuserait au-delà et de ne pas avoir besoin de plus de 10 résolutions DNS pour savoir si l’IP expéditrice est incluse dans l’enregistrement SPF.
Attention, la RFC
7208 spécifie que le mot clé PTR
ne devrait pas être
utilisé même si en pratique ça semble toujours utilisé (OVH l’utilise
par exemple).
Enfin, on se demande souvent si l’on doit mettre “~all” ou “-all” :
on a tendance à privilégier de plus en plus -all
car cela
donnera davantage de rejets explicites (au niveau SMTP par exemple, au
lieu d’aller en Spam ou Quarantaine).
Vérification SPF
Pour vérifier les enregistrements SPF des emails puis rejeter les
emails invalides et marquer le résultat de la vérification via un entête
Received-SPF
nous utilisons policyd-spf :
# apt install postfix-policyd-spf-python
# cp /usr/share/doc/postfix-policyd-spf-python/policyd-spf.conf.commented /etc/postfix-policyd-spf-python/policyd-spf.conf
On ajoutera dans /etc/postfix/master.cf
:
policyd-spf unix - n n - 0 spawn
user=policyd-spf argv=/usr/bin/policyd-spf
et /etc/postfix/main.cf
:
smtpd_recipient_restrictions =
...
reject_unauth_destination
check_policy_service unix:private/policyd-spf
...
policyd-spf_time_limit = 3600
Voici les paramètres intéressants pour
/etc/postfix-policyd-spf-python/policyd-spf.conf
:
TestOnly = 0 # Mode simulation, aucun rejet, seulement la description de l'action dans les logs (note: TestOnly=0 est contre-intuitif)
defaultSeedOnly = 0 # ancien nom pour "TestOnly", fonctionne toujours mais met une erreur dans les logs
Mail_From_reject = Fail # Rejete les mails si le check SPF échoue
Mail_From_reject = Softfail # Rejete les mails si le check SPF échoue même en « soft » (utilisation de ~all par exemple)
Mail_From_reject = SPF_Not_Pass # Encore plus bourrin, rejete les emails si le SPF échoue (même en soft) ou erreur temporaire
HELO_reject = Fail # Rejete les mails si le check SPF sur le HELO échoue
HELO_reject = Fail # Rejete les mails si le check SPF sur le HELO échoue même en « soft » (utilisation de ~all par exemple)
HELO_reject = SPF_Not_Pass # Encore plus bourrin, rejete les emails si le SPF échoue (même en soft) ou erreur temporaire
Reject_Not_Pass_Domains = aol.com,hotmail.com # Transforme un ~all en -all pour des domaines en particulier
Voir policy-spf.conf(5).
Cela ajoutera l’entête suivant aux emails :
Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=192.0.2.1; helo=mail.example.com; envelope-from=jdoe@example.com; receiver=<UNKNOWN>
ou en cas d’échec :
Received-SPF: Softfail (mailfrom) identity=mailfrom; client-ip=192.0.2.1; helo=mail.example.com; envelope-from=jdoe@example.com; receiver=<UNKNOWN>
Note : receiver=<UNKNOWN>
est une anonymisation
pour des raisons de confidentialité, cf l’option par défaut
Hide_Receiver = Yes
Cet entête pourra notamment être utilisé par des filtres, SpamAssassin, etc.
Note : attention, pour les emails locaux, cela n’ajoutera pas l’entête
Received-SPF
ce qui peut poser des soucis avec les outils s’appuyant dessus, notamment SpamAssassin ou OpenDMARC.
Utilitaire spfquery
Pour vérifier manuellement un enregistremnt SPF vous pouvez utiliser
spfquery
fourni par le paquet du même nom. La commande
necessite 3 arguments et s’utilise comme suit :
$ spfquery -ip=31.170.8.17 -sender=example@evolix.fr -helo=evolix.fr
pass
spfquery: domain of evolix.fr designates 31.170.8.17 as permitted sender
Received-SPF: pass (spfquery: domain of evolix.fr designates 31.170.8.17 as permitted sender) client-ip=31.170.8.17; envelope-from=example@evolix.fr; helo=evolix.fr;
Utilisaire spf
L’utilitaire spf
permet
aussi d’avoir une vision synthétique sur la configuration SPF d’un
domaine. Écrit en Perl il est facile à installer et fonctionne presque
partout.
$ spf netmeister.org
netmeister.org:
policy:
a -all
valid
pass:
a (1 name):
netmeister.org
a (2 IPs):
166.84.7.99
2001:470:30:84:e276:63ff:fe72:3900
All others: fail
SPF record for domain 'netmeister.org': valid
Total counts:
Total number of DNS lookups : 1
pass:
Total # of a directives : 1
Total # of ip4 addresses : 1
Total # of ip6 addresses : 1
All others: fail
postwhite (test)
Pour économiser des requêtes DNS pour vérifier SPF, on peut utiliser “postwhite” qui va générer une liste des adresses IPv4/IPv6 des plus gros fournisseurs d’email pour les mettre en liste blanche pour Postscreen.
https://github.com/stevejenkins/postwhite/
DKIM
DKIM est une norme pour ajouter une
signature cryptographique dans les entêtes d’un email envoyé. La
signature se fait à partir à de l’expéditeur d’entête
(From:
d’un email), des entêtes au choix (sujet, date,
etc.) et le corps du message. Cela utilise aussi une clé publique
stockée dans un enregistrement DNS TXT.
Voir https://wiki.evolix.org/HowtoOpenDKIM
DMARC
DMARC est une spécification qui vient en complément de DKIM et SPF. Cela permet de spécifier aux serveurs de messagerie comment traiter les emails reçus non conformes aux vérifications SPF et/ou DKIM. Cela permet également de récupérer des informations voire des emails complets si ils ne sont pas conformes. Encore une fois, cela se fait avec un enregistrement DNS TXT.
Attention, l’enregistrement DMARC recherché est celui du domaine de
l’expéditeur d’entête (From:
), appelé aussi
“RFC5322.From”.
Pour que la vérification DMARC passe, il suffit que l’un des cas soit rempli :
- DKIM passe (et le “RFC5322.From” aligné, mais c’est le principe de base sauf cas tordu)
- SPF passe ET le “RFC5321.MailFrom” est aligné avec le “RFC5322.From”.
DMARC n’exige pas que DKIM et SPF soit valide. Ainsi DMARC peut ainsi très bien être “PASS” avec un SPF invalide ou avec une signature DKIM invalide !
Plus d’infos dans la RFC7489 : Domain-based Message Authentication, Reporting, and Conformance (DMARC)
Voici un exemple d’enregistrement DNS basique :
_dmarc IN TXT "v=eMARC1; p=reject; sp=reject; aspf=s; adkim=s"
On pourra spécifier :
p=none
si l’on ne veut pas que les emails non conformes soient rejetésp=reject
si l’on veut que les emails non conformes soient rejetés (rarement utilisé)p=quarantine
si l’on veut que les emails non conformes soient mis de côté (dans une sous-boîte Spam en général)
De façon similaire, on peut spécifier la politique par défaut pour
les sous-domaines avec sp=
. En effet, si un enregistrement
_dmarc
n’est pas trouvé pour un sous-domaine, il
interrogera le « top-level domain » (ou encore appelé « organizational
domain »).
Attention, si vous spécifiez
rua=mailto:dmarc@example.com
vous recevrez pas mal de
rapports Report domain
de Google, Outlook, etc. vous
notifiant des emails non conformes. Les rapports incluent un fichier
XML, on peut le lire via des outils comme mxtoolbox ou
easydmarc.
On pourra aussi spécifier que l’on veut un alignement entre
l’expéditeur d’enveloppe (MAIL FROM:
utilisé par SPF) et
l’expéditeur d’entête (From:
) :
aspf=r
: relaxed, on exige un alignement mais cela peut-être des sous-domainesaspf=s
: strict, on exige que cela soit exactement le même FQDN
De façon similaire, on peut aussi spécifier que la signature DKIM
corresponde bien à l’expéditeur d’entête (From:
) :
adkim=r
: relaxed, on exige que cela correspond à un domaine ou sous-domaineadkim=s
: strict, on exige que cela soit exactement le même FQDN
Voici un exemple d’un enregistrement DNS plus avancé :
_dmarc IN TXT "v=DMARC1;p=reject;sp=none;rua=mailto:dmarc+aggr@example.com;ruf=mailto:dmarc+forensic@example.com;fo=1;adkim=s;aspf=s;pct=100"
Un outil génial pour tester DMARC est https://www.learndmarc.com/ : il faut envoyer un email et l’on a toutes les explications sur SPF / DKIM / DMARC et notamment l’alignement.
Vérification DMARC
Pour vérifier la politique des emails nous utilisons OpenDMARC.
OpenDMARC s’appuie sur DKIM qui ajoute
l’entête Authentication-Results
, il faut donc au préalable
avoir installé et configuré OpenDKIM.
OpenDKIM s’appuye également sur l’entête Received-SPF
mais
il peut également faire la vérification SPF lui-même.
On installe :
# apt install opendmarc dbconfig-no-thanks
# systemctl enable opendmarc
# systemctl start opendmarc
Note : attention, la version d’OpenDMARC de Debian 11 (Bullseye) a tendance à planter donc on conseille d’utiliser la version de Debian 12 (un backport est en cours de préparation de notre côté si l’on arrive à pousser cela dans Debian 11).
On configure via /etc/opendmarc.conf
:
AuthservID hosting.example.com
PidFile /var/run/opendmarc/opendmarc.pid
PublicSuffixList /usr/share/publicsuffix
Socket inet:8893@localhost
#Socket local:/var/run/opendmarc/opendmarc.sock
Syslog true
UMask 0002
UserID opendmarc
IgnoreHosts /etc/opendmarc/ignore.hosts
SPFSelfValidate true
TrustedAuthservIDs hosting.example.com
IgnoreAuthenticatedClients true
Note : bien aligner AuthservID avec le « myhostname
» de Postfix, et le mettre aussi dans
TrustedAuthservIDs
Par défaut, OpenDMARC se contente de vérifier et d’ajouter l’entête
Authentication-Results
(AR). Si l’on veut que les emails
avec une politique DMARC invalide soit rejeté (mais c’est rare car
p=reject
est rarement utilisé), on peut mettre l’option
:
RejectFailures true
Voir opendmarc.conf(5).
Et il faut ajouter un fichier
/etc/opendmarc/ignore.hosts
pour ignorer les emails locaux
:
# mkdir /etc/opendmarc
# touch /etc/opendmarc/ignore.hosts
# chown -R opendmarc:opendmarc /etc/opendmarc
# cat /etc/opendmarc/ignore.hosts
127.0.0.0/8
::1/128
localhost
localhost.localdomain
192.168.0.0/16
192.0.2.0/24
Et l’on ajoute un milter à la suite de celui pour OpenDKIM :
non_smtpd_milters = inet:127.0.0.1:8891 inet:127.0.0.1:8893
smtpd_milters = inet:127.0.0.1:8891 inet:127.0.0.1:8893
in_flow_delay = 0s
Cela ajoutera un 2e entête Authentication-Results
(AR)
en plus de celui d’OpenDKIM :
Authentication-Results: antispam.example.com; dmarc=pass (p=none dis=none) header.from=example.com
ou en cas d’échec :
Authentication-Results: antispam.example.com; dmarc=fail (p=none dis=none) header.from=example.com
Cet entête pourra notamment être utilisé par des filtres, SpamAssassin, etc.
Contacts des principaux fournisseurs d’email
En cas de souci de délivrabilité vers un domaine
particulier, on est amené à contacter son responsable. En théorie
l’adresse email postmaster@
permet cela.
En pratique pour les principaux fournisseurs d’emails, voici comment les contacter :
- Free : http://postmaster.free.fr/
- Orange : http://assistance.orange.fr/la-cellule-abuse-1260.php
- Hotmail/Outlook/Microsoft : https://support.microsoft.com/en-us/getsupport?oaspworkflow=start_1.0.0.0&wfname=capsub&productkey=edfsmsbl3&ccsid=635688189955348624&wa=wsignin1.0
- Yahoo : https://postmaster.yahoo.com/sender-request
- La Poste : https://postmaster.laposte.net/
- GMAIL : http://support.google.com/mail/bin/request.py?contact_type=bulk_send&&hl=en (NE REPONDENT JAMAIS !!!)
ARC
Le protocole ARC (Authenticated Received Chain) est destiné à signer les entêtes d’authentification dans les cas où certains champs peuvent être modifié, par exemple dans le cas d’une liste de diffusion ou d’un « forwarding » d’email utilisant SRS. Cela ne sert que si l’on fait confiance au serveur d’envoi, donc ça n’est pas vraiment utile de façon globale sur Internet.
Voici des pages qui expliquent bien le protocole ARC :
- https://powerdmarc.com/fr/qu%27est-ce-que-l%27arc/
- https://www.badsender.com/2020/10/29/arc-definition-fonctionnement-verification/
Pour Postfix, on peut utiliser le gros milter de Fastmail car le projet OpenARC semble abandonné depuis plusieurs années.
BIMI
BIMI (Brand Indicators for Message Identification) est une RFC encore en draft : https://datatracker.ietf.org/doc/draft-brand-indicators-for-message-identification/
Cela consiste à publier un logo SVG dans un enregistrement DNS pour qu’il puisse être affiché par les clients emails, aujourd’hui c’est surtout GMAIL qui l’utilise.
Les infos pour publier son logo dans un enregistrement DNS TXT : https://mxtoolbox.com/dmarc/bimi/how-to-create-bimi-record
Néanmoins ça n’est pas suffisant pour GMAIL par exemple, il faut aussi prouver que le logo nous appartient ! Donc conrètement il faut avoir déposé sa marque à l’INPI (pour la France), et payer un VMC/CMC auprès d’une autroité de certificat, ce qui coûte 1000 à 2000 EUR par an. Par ailleurs on évitera ENTRUST qui a été banni de GMAIL à cause de problèmes de sécurité. On peut passer par DigiCert : https://digicert.tbs-certificats.com/certificats_VMC.html.fr
Postcreen
Postscreen est un démon léger destiné à faire des tests préliminaires avant de passer un message entrant à Postfix… ou de le rejeter !
Voir https://wiki.evolix.org/HowtoMail/Antispam#postscreen
FAQ
Envoyer un mail de test en CLI
$ telnet 127.0.0.1 25
HELO example.com
MAIL FROM: <noreply@example.com>
RCPT TO: <foo@example.org>
DATA
From: <noreply@example.com>
To: Foo <foo@example.org>
Subject: test
Ceci est un test
.
Récupérer expéditeur et destinataire dans mail.log
Pour récupérer à la fois l’adresse expéditeur et destinataire dans les logs :
# grep "blocked using FBLW15" /var/log/mail.log | cut -d " " -f 6 | tr -d ':' \
| while read msgid; do grep $msgid /var/log/mail.log |grep " postfix/" \
| grep -E '(from|to)=<'|awk -F ' ' '{ print $1,$2,$3,$7 }' |tr -d ','; echo; done
Taille maximum d’un message
Par défaut, la taille d’un message est limitée à 10 Mo, cela se
modifie avec le paramètre message_size_limit
.
Attention, lorsqu’une pièce jointe est dans un format binaire (exemples : JPG, PDF, etc.), les emails sont traduits en caractères texte (conversion uuencode) ce qui provoque une augmentation de la taille jusqu’à 40%.
La taille est indiquée en octets, la valeur par défaut est
10240000
Par exemple pour autoriser les messages jusqu’à 25 Mo, on mettra 25Mo +40% soit 35 Mo :
message_size_limit = 35840000
Attention, il faudra aussi ajuster mailbox_size_limit
à
partir de message_size_limit = 51200000
. Cette option
mailbox_size_limit
(par défaut à 50Mo) désigne la taille
maximum d’une Mailbox ou d’un fichier d’une Maildir.
SMTPUTF8
SMTPUTF8 est une extension pour support l’UTF8 dans les entêtes de messages.
En effet, de façon standard tous les entêtes de messages doivent avoir un encoding spécial pour les caratères non ASCII.
Il peut arriver que cela pose des problèmes, notamment avec des clients SMTP qui gèrent mal cet encoding.
À partir de Debian 9, on peut alors activer l’option
smtputf8_enable = yes
dans Postfix.
Et Postfix annoncera qu’il supporte cette extension :
$ nc 127.0.0.1 25
220 smtp.example.com ESMTP mail server
EHLO foo.bar
250-smtp.example.com
250-PIPELINING
250-SIZE 51200000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 SMTPUTF8
Pour plus de détails, lire http://www.postfix.org/SMTPUTF8_README.html
Relai vers Mailjet selon l’expéditeur
Voir leur documentation : https://fr.mailjet.com/docs/code/postfix
.forward
Voir aussi : /HowtoMail/Roundcube#plugin-vacation
De façon similaire aux fichiers .htaccess
pour Apache,
un utilisateur UNIX peut créer un fichier .forward
à la
racine de son home-directory pour faire passer tous ses emails reçus
dans une moulinette : renvoi automatique vers une autre adresse,
traitement via Procmail, envoi d’un message d’absence, etc. Attention,
cela ne fonctionne que pour Postfix en mode local, cela ne fonctionne
pas en mode virtual.
Pour ré-envoyer tous les emails vers une autre adresse
jdoe@example.com
on mettra simplement :
$ cat ~/.forward
jdoe@example.com
Pour envoyer tous les emails vers une autre adresse MAIS garder une
copie sur sa boîte foo
:
$ whoami
foo
$ cat ~/.forward
\foo,jdoe@example.com
Pour faire traiter tous ses emails reçus par le logiciel Procmail :
$ cat ~/.forward
"| IFS=' ' && exec /usr/bin/procmail -f- || exit 75"
Pour envoyer un message d’absence en gardant une copie sur sa boîte
foo
:
$ cat ~/.forward
\foo,"|/usr/bin/vacation foo"
vacation
Voir aussi : /HowtoMail/Roundcube#plugin-vacation
# apt install vacation
Le programme vacation
permet d’envoyer des messages
d’absence SANS renvoyer des messages aux adresses déjà prévenues et SANS
envoyer de message d’absence quand le mail reçu est une copie
cachée.
ATTENTION : vacation n’envoie PAS de message
d’absence si la destination n’est pas le compte UNIX. Par exemple si
l’on a un compte jdoe
et que l’on reçoit un email sur
john.doe@example.com
aucun message d’absence ne sera
renvoyé. Il faut alors préciser un alias avec l’option -a
:
/usr/bin/vacation -a john.doe -a jdoe
Le message d’absence en lui-même se trouve dans
~/.vacation.msg
, on conseille notamment de préciser le
Content-Type
et d’éviter les accents dans le sujet :
$ cat ~/.vacation.msg
From: John Doe <john.doe@example.com>
Subject: John Doe / Example - Absence
Content-Type: text/plain; charset=UTF-8
Je suis en congé parental, veuillez joindre mon collègue.
On peut lister les adresses qui ont reçu un message d’absence ainsi :
$ vacation -l
Restreindre selon le From
check_recipient_access hash:/etc/postfix/protected_users,
smtpd_restriction_classes = onlylocal
onlylocal = check_sender_access hash:/etc/postfix/onlylocal, reject
/etc/postfix/protected_users :
service.intra@ onlylocal
Transporter les mails vers un autre serveur et/ou port
On s’appuye sur la directive transport_maps
:
transport_maps = hash:$config_directory/transport
On pourra alors éditer le fichier /etc/postfix/transport
:
outlook.com smtp:[gw.example.com]
Ainsi les emails vers @outlook.com
seront déviés et
envoyés en SMTP vers les adresses IP correspondantes à
gw.example.com
.
Date et Maildir
Le format Maildir s’appuye sur les dates du système de fichiers. On peut ainsi par exemple rechercher les emails entre le 18 mai 2016 et 11 octobre 2016 ainsi :
$ find $HOME/Maildir/.foo/ -type f -newermt 2016-05-18 ! -newermt 2016-09-11
warning: service “smtp” (25) has reached its process limit “100”
En cas de message d’erreur du type :
postfix/master: warning: service "smtp" (25) has reached its process limit "100": new clients may experience noticeable delays
postfix/master: warning: to avoid this condition, increase the process count in master.cf or reduce the service time per client
postfix/master: warning: see http://www.postfix.org/STRESS_README.html for examples of stress-adapting configuration settings
Vous pouvez augmenter le paramètre maxproc
ainsi dans le
master.cf
:
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - y - 1000 smtpd
ou alors de façon plus globale le paramètre
default_process_limit
:
default_process_limit = 500
Header Checks
https://www.sweetnam.eu/index.php/Postfix_Header_Checks https://mailing.postfix.users.narkive.com/GiWF2O9k/encoded-subjects-aren-t-rejected-by-header-checks
Comment désactiver l’IPv6 pour Postfix ?
Il faut mettre le paramètre :
inet_protocols = ipv4
Délivrabilité vers Microsoft
- SPF/DKIM/DMARC doivent être bien configurés
- Attention, Microsoft force son cache DNS, les changements - notamment pour SPF - ne sont pas pris en compte comme on pourrait se l’attendre via le TTL
- Le champ SPF doit être minimum, en particulier ne contenir aucune adresse IP blacklistée
- Microsoft utilise des DNSRBL notamment SpamHaus, s’assurer que ses IP ne sont pas blacklistées quelque part grâce à https://mxtoolbox.com/blacklists.aspx et https://multirbl.valli.org/
- Envoyer au moins 100 messages par jour, si ça n’est pas le cas configurer un cron qui envoie vers une adresse Microsoft
- Vérifier le statut des IPs via SNDS : https://sendersupport.olc.protection.outlook.com/snds/
- Attention, l’antispam d’Office365 est plus « exigeant » que celui d’Hotmail/Outlook (a priori car il utilise « Forefront » en plus)
- Vérifier les entêtes des emails reçus depuis une boîte Microsoft via https://mha.azurewebsites.net/
- Surveiller l’entête
X-MS-Exchange-Organization-SCL:
qui est la note tueuse de l’antispam Microsoft : 1 = tout va bien, à partir de 5 bof, 8 ou 9 tout va mal, cf doc - Les champs “Received:” dans les entêtes sont analysés par l’antispam de Microsoft, ils peuvent la raison qu’un email est considéré comme spam, par exemple si un domaine est blacklisté
- La résolution DNS échoue de temps en temps chez Microsoft
Received-SPF: TempError (protection.outlook.com: error in processing during lookup of example.com : DNS Timeout)
ce qui peut impliquer une note tueuse à 5 (X-MS-Exchange-Organization-SCL: 5
) et probablement un mise en Spam dans ces cas là - Surveiller l’entête
X-MS-Exchange-Organization-PCL:
qui indique si Microsoft considère que votre message est du phising, cf doc - Surveiller l’entête
X-Forefront-Antispam-Report:
par exempleSFV:SPM
signifirait que l’email a été classé comme spam à cause de son contenu etCAT:HSPM
signifie que l’email est “High confidence SPaM” cf doc et ce blog - Surveiller l’entête
X-Microsoft-Antispam:
par exempleBCL:
indique si le message est considéré comme un massif : 0 ça n’est pas le cas, 1 à 3 il y a eu quelques plaintes, à partir de 4 il y a eu pas mal de plaintes, et 8 ou 9 beaucoup; cf doc - L’antispam de Microsoft prend en compte : l’IP, son reverse, le FQDN annoncé dans le HELO, l’ensemble des IPs du SPF (?), le Message-Id: => essayer de faire varier ces paramètres pour détecter ce qui ne va pas
- Demander à ses destinataires chez Microsoft d’indiquer l’email comme « courrier légitime » si ils arrivent en spam, de sélectionner « ne jamais bloquer » (option disponible sur un email reçu)
- Demander à ses destinataires chez Microsoft d’aller dans “Paramètres > Courrier indésirable” puis “Ajouter un expéditeur approuvé” en entrant le nom de domaine de messagerie à mettre en liste blanche cf doc
- Demander à vos destinataires chez Office365 de contacter leur administrateur pour ajouter votre nom de domaine à la liste “Safe Senders” cf doc ou doc
entête Received:
Postfix insère un entête Received:
aux messages qu’il
traite conformément aux RFC822 et RFC1123.
Pour les messages reçus en SMTP il ajoute :
Received: from $helo_annonce (reverse_DNS_IP_client SMTP [IP_client_SMTP])
by $myhostname (Postfix) with ESMTP id ID
for <dest@example.com>; DATE
Pour les messages reçus en local :
Received: by $myhostname (Postfix, from userid UID)
id ID; DATE
postsrsd
Si vous avez des alias qui renvoient vers des adresses externes
(.forward
vers @gmail.com par exemple), ces « bounces »
seront souvent mal délivrés car cela casse le principe du SPF.
Pour contourner cela, il existe la méthode SRS (Sender Rewriting Scheme) qui consiste à modifier le « Return-Path » des messages avec un domaine local et un code temporaire pour gérer un éventuel bounce.
Pour Postfix, postsrsd permet de faire du SRS.
# apt install postsrsd
Il faut choisir un unique domaine pour les ré-écritures et l’on peut
mettre des des domaines en exception. On pourra par exemple choisir le
FQDN utilisé pour le reverse DNS précédé de srs.
.
# grep ^SRS /etc/default/postsrsd
SRS_DOMAIN=srs.hosting.example.com
SRS_EXCLUDE_DOMAINS=hosting.example.com,example.com,example.org
Et dans main.cf
on s’appuye sur les ré-écritures «
canonical » :
sender_canonical_maps = tcp:127.0.0.1:10001
sender_canonical_classes = envelope_sender
recipient_canonical_maps = tcp:127.0.0.1:10002
recipient_canonical_classes = envelope_recipient, header_recipient
sender_canonical_*
va ré-écrire le Return-Path des emails en transitrecipient_canonical_*
va ré-écrire le Return-Path et leTo:
en cas d’un bounce pour qu’il soit renvoyé à l’expéditeur original
L’inconvénient de postsrsd c’est qu’il modifie les Return-Path de tous les emails délivrés localement, ce qui n’est pas très joli.
Si l’email n’est pas signé avec DKIM, cela va notamment casser
l’éventuel alignement DMARC. D’où le fait qu’il faut faire fonctionner
les check SPF / DMARC avant la modification SRS et les noter sous forme
d’entête Authentication-Results:
exploitable par
SpamAssassin par exemple, mais il faut éviter que SpamAssassin fasse
lui-même les checks.
renvoi vers d’autres serveurs
On peut renvoyer tout ou partie du trafic vers d’autres serveurs, une
technique peut consister à utiliser un content_filter
vers
un service HAProxy local qui renverra vers d’autres serveurs.
Si besoin de conserver une partie du trafic local, HAProxy pourra renvoyer sur un process “smtpd” local de façon semblable à Amavis par exemple.
main.cf :
content_filter = smtp:[127.0.0.1]:11024
haproxy.cf :
listen prechauffage
bind 127.0.0.1:11024
mode tcp
balance roundrobin
server localhost11025 127.0.0.1:11025 inter 10000 rise 2 fall 5 check weight 70
server smtp42 192.0.2.42:25 inter 10000 rise 2 fall 5 check weight 30
master.cf :
127.0.0.1:11025 inet n - y - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
Alignement HELO avec le reverse DNS
Des sites conseillent souvent d’aligner le FQDN annoncé via HELO avec le reverse DNS, par exemple mxtoolbox.com En pratique nous ne constatons pas spécialement cette vérification de la part des gros fournisseurs d’email. Et attention, si vous faites cela et que vous utilisez IPv4/IPv6 en envoi, veillez à bien utiliser un FQDN qui aura une résolution A et AAAA à la fois, vers des adresses IPv4 et IPv6 pointant vers ce même FQDN.
Postfix is using backwards-compatible default settings
Si vous avez des logs du type :
mail postfix[1764072]: Postfix is using backwards-compatible default settings
mail postfix[1764072]: See http://www.postfix.org/COMPATIBILITY_README.html for details
mail postfix[1764072]: To disable backwards compatibility use "postconf compatibility_level=3.6" and "postfix reload"
C’est que Postfix est lancé en mode « rétro-compatible ».
Cela signifie que Postfix va garder les options de configuration par
défaut d’une ancienne version. Par exemple, dans les anciennes versions,
par défaut on avait smtputf8_enable=no
ou encore
append_dot_mydomain=yes
. Dans des versions plus récentes,
ces options ont changé leur valeur par défaut.
Cela est utile pour les mises à jour, ou pour une configuration importée d’une ancienne version.
Si l’on est d’accord pour avoir les nouvelles valeurs par défaut, il
faut ajouter dans le main.cf
:
compatibility_level=3.6
Plus d’infos sur https://www.postfix.org/COMPATIBILITY_README.html
warning: TLS library problem: error:0A0000C1:SSL routines::no shared cipher
Si vous obtenez des erreurs SSL/TLS du type
no shared cipher
, par exemple :
SSL_accept error from unknown[192.0.2.110]: -1
warning: TLS library problem: error:0A0000C1:SSL routines::no shared cipher:../ssl/statem/statem_srvr.c:2220
Cela signifie qu’aucun cipher commun n’a été trouvé lors du handshake SSL.
Les options à explorer :
- Descendre le niveau d’exigence sur les ciphers :
smtpd_tls_ciphers=low
etsmtpd_tls_mandatory_ciphers=low
- Utiliser une clé privée du type RSA pour avoir plus de ciphers à
proposer comme expliqué
sur ce blog, cf pour Let’s
Encrypt, si besoin on pourra utiliser une clé ECDSA et une clé RSA
en parallèle, cf options
smtpd_tls_eckey_file
- Tester les ciphers proposés avec testssl
- Ajuster les options
smtpd_tls_exclude_ciphers
,smtpd_tls_protocols
etsmtpd_tls_mandatory_protocols
soft_bounce = yes
En cas de maintenance ou de test, on peut transformer toutes les erreurs 5xx en 4xx avec la directive soft_bounce :
soft_bounce = yes
On peut ainsi s’assurer de ne pas « perdre » d’email : au pire on rejettera uniquement temporairement un email reçu.