Serveur Familial - Le Mail

Par ghislain , 31 décembre, 2024

Cette partie est assez complexe car la elle nécessite de nombreux serveurs interconnecté entre eux. Afin de garantir la réputation de l'IP publique du serveur il faut toujours veiller à ne pas relayer n'importe quel mail. Dans le cas contraire le serveur servira de relai spam et sera rapidement blacklisté.

Pour la mise en place du mail nous allons déployer un serveur Postfix associé à un serveur Dovecot. Afin de séparer les comptes système des comptes mails, l'authentification de Postfix sera déléguée par LMTP à Dovecot qui utilisera un fichier plat comme base d'authentification.

Pour démarrer il faut installer les packages dovecot postfix.

Dovecot

Nous allons conserver la configuration séparée dans différents fichiers.

Fichier 10-auth.conf

Dans le fichier /usr/local/etc/dovecot/conf.d/10-auth.conf

auth_username_format = %Ln
auth_mechanisms = plain login digest-md5 cram-md5
!include auth-passwdfile.conf.ext

Et le fichier   /usr/local/etc/dovecot/conf.d/auth-passwdfile.conf.ext doit contenir à minima les lignes suivantes:

passdb {
  driver = passwd-file
  args = scheme=SHA256-CRYPT username_format=%u /usr/local/etc/dovecot/users
}
userdb {
  driver = passwd-file
  args = username_format=%u /usr/local/etc/dovecot/users
  # Default fields that can be overridden by passwd-file
  #default_fields = quota_rule=*:storage=1G
}

Ainsi le fichier /usr/local/etc/dovecot/users sera composé d'une ligne par compte, chaque ligne aura la structure suivante  : 

identifiant:Algorithme et hash du mot de passe:uid:guid::chemin vers le répertoire personnel de mails::

pour le champ "Algorithme et hash du mot de passe" on utilise la commande suivant pour obtenir la valeur:

doveadm pw -s SHA512-CRYPT

ce qui à titre d'exemple donne :

john:{SHA512-CRYPT}$6$NghdlFQTiFoQjAaU$SxdtT3Ax4/B44Jkgc7cebfWV3WmNWq/PstM1Dugn66Bgw7i9ppHmWXPAF10DsjTWKmBVZr0xSV8soApsonU8R.:3000:3000::/usr/local/srv/mails/john::

Pour ceux qui se posent la question, le mot de passe utilisé est "john".

 

Fichier 10-master.conf

Le fichier /usr/local/etc/dovecot/conf.d/10-master.conf contient tout les paramétrages pour les différents protocoles écoutés par le serveur Dovecot.

service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
  # Number of connections to handle before starting a new process. Typically
  # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0
  # is faster. <doc/wiki/LoginProcess.txt>
  #service_count = 1
  # Number of processes to always keep waiting for more connections.
  #process_min_avail = 0
  # If you set service_count=0, you probably need to grow this.
  #vsz_limit = $default_vsz_limit
}
service pop3-login {
  inet_listener pop3 {
    port = 110
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}
service submission-login {
  inet_listener submission {
    port = 587
  }
  inet_listener submissions {
    port = 465
  }
}
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    group = postfix
    mode = 0600
    user = postfix 
  }
  # Create inet listener only if you can't use the above UNIX socket
  #inet_listener lmtp {
    # Avoid making LMTP visible for the entire internet
    #address =
    #port = 
  #}
}
service imap {
  # Most of the memory goes to mmap()ing files. You may need to increase this
  # limit if you have huge mailboxes.
  #vsz_limit = $default_vsz_limit
  # Max. number of IMAP processes (connections)
  #process_limit = 1024
}
service pop3 {
  # Max. number of POP3 processes (connections)
  #process_limit = 1024
}
service submission {
  # Max. number of SMTP Submission processes (connections)
  #process_limit = 1024
}
service auth {
  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0600
    user = postfix
    group = postfix
  }
  # Auth process is run as this user.
  user = $default_internal_user
}
service auth-worker {
  # Auth worker process is run as root by default, so that it can access
  # /etc/shadow. If this isn't necessary, the user should be changed to
  # $default_internal_user.
  #user = root
}
service dict {
  # If dict proxy is used, mail processes should have access to its socket.
  # For example: mode=0660, group=vmail and global mail_access_groups=vmail
  unix_listener dict {
    #mode = 0600
    #user = 
    #group = 
  }
}

 

Fichier 10-mail.conf

Dans le fichier /usr/local/etc/dovecot/conf.d/10-mail.conf il faut mettre la valeur suivante :

mail_location = maildir:~/Maildir

On utilise ainsi un sous répertoire Maildir dans chaque répertoire racine des utilisateurs Dovecot.

Fichier 10-ssl.conf

Dans le fichier /usr/local/etc/dovecot/conf.d/10-ssl.conf il suffit de mettre les lignes suivantes :

ssl = yes
ssl_cert = </usr/local/etc/letsencrypt/live/XXXXXX/cert.pem
ssl_key = </usr/local/etc/letsencrypt/live/XXXXXX/privkey.pem

Adaptez en fonction de votre installation.
Ajouter le démarrage automatique du service dovecot : sysrc dovecot_enable="YES"

Pulgin Pigeonhole

Le plugin Pigeonhole permet de créer des tris automatiques dans Dovecot. Pour l'installer utilisez la commande :

pkg install dovecot-pigeonhole

Dans le /usr/local/etc/docevot/cond.d/20-lmtp.conf modifier le paramétrage des plugins :

protocol lmtp { 
 # Space separated list of plugins to load (default is global mail_plugins). 
 mail_plugins = $mail_plugins sieve 
}

Ajouter un fichier 90-sieve dans le répertoire /usr/local/etc/dovecot/conf.d

service managesieve-login {
  inet_listener sieve {
    port = 4190
  }

  # Number of connections to handle before starting a new process. Typically
  # the only useful values are 0 (unlimited) or 1\. 1 is more secure, but 0
  # is faster. <doc/wiki/LoginProcess.txt>
  #service_count = 1

  # Number of processes to always keep waiting for more connections.
  #process_min_avail = 0

  # If you set service_count=0, you probably need to grow this.
  #vsz_limit = 64M
}

service managesieve {
  # Max. number of ManageSieve processes (connections)
  process_limit = 1024
}

# Service configuration

protocol sieve {
  # Maximum ManageSieve command line length in bytes. ManageSieve usually does
  # not involve overly long command lines, so this setting will not normally need
  # adjustment
  #managesieve_max_line_length = 65536

  # Maximum number of ManageSieve connections allowed for a user from each IP address.
  # NOTE: The username is compared case-sensitively.
  #mail_max_userip_connections = 10

  # Space separated list of plugins to load (none known to be useful so far). Do NOT
  # try to load IMAP plugins here.
  #mail_plugins =

  # MANAGESIEVE logout format string:
  #  %i - total number of bytes read from client
  #  %o - total number of bytes sent to client
  #managesieve_logout_format = bytes=%i/%o

  # To fool ManageSieve clients that are focused on CMU's timesieved you can specify
  # the IMPLEMENTATION capability that the dovecot reports to clients.
  # For example: 'Cyrus timsieved v2.2.13'
  #managesieve_implementation_string = Dovecot Pigeonhole

  # Explicitly specify the SIEVE and NOTIFY capability reported by the server before
  # login. If left unassigned these will be reported dynamically according to what
  # the Sieve interpreter supports by default (after login this may differ depending
  # on the user).
  #managesieve_sieve_capability =
  #managesieve_notify_capability =

  # The maximum number of compile errors that are returned to the client upon script
  # upload or script verification.
  #managesieve_max_compile_errors = 5

  # Refer to 90-sieve.conf for script quota configuration and configuration of
  # Sieve execution limits.
}

plugin {
  # Used by both the Sieve plugin and the ManageSieve protocol
  sieve = ~/.dovecot.sieve
  sieve_dir = ~/sieve
  sieve_default = /usr/local/etc/dovecot/conf.d/sieve/default
}

Il faut ensuite créer le fichier /usr/local/etc/dovecot/conf.d/sieve/default avec comme contenu :

require "fileinto";

if header :contains "X-Spam-Flag" ["YES"] {
  fileinto "Spam";
  stop;
}

 

Postfix

Il faut tout d'abord comprendre que les serveurs de mails sont très scruté tant par des personnes malveillantes pour tenter d'envoyer des spams que par les listes noires de serveurs de spam. Aussi il faut toujours faire attention et tant que le serveur n'est pas sécurisé, pensez à arrêter le service.

Fichier main.cf

Dans le fichier /usr/local/etc/postfix/main.cf

mail_owner = postfix
compatibility_level=3.6
unknown_local_recipient_reject_code = 550
mynetworks_style = host
myhostname = mail.XXXXXX.tld
mydomain = XXXXXX.tld
myorigin = $mydomain
mydestination = $myhostname $mydomain localhost.$mydomain localhost
local_recipient_maps =
mynetworks_style = host
inet_interfaces = all
inet_protocols = all
local_transport = lmtp:unix:private/dovecot-lmtp
virtual_mailbox_domains = YYYYYY.tld
#virtual_mailbox_base = /usr/local/srv/mails
#virtual_mailbox_maps = passwd:/usr/local/etc/dovecot/users
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_alias_maps = hash:/usr/local/etc/postfix/virtual
virtual_alias_domains = $virtual_alias_maps
smtpd_banner = $myhostname ESMTP $mail_name
smtpd_tls_chain_files = /usr/local/etc/postfix/ssl/ecdsa.pem
smtpd_tls_CApath = /etc/ssl/certs
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_ciphers = high
smtpd_tls_security_level = may
smtpd_tls_mandatory_protocols = >=TLSv1.2
smtpd_tls_exclude_ciphers     = NULL, MD5, DES, RC4
smtpd_recipient_restrictions = permit_sasl_authenticated permit_inet_interfaces reject_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_relay_restrictions = permit_sasl_authenticated permit_mynetworks permit_inet_interfaces reject_unauth_destination
smtp_tls_CApath = /etc/ssl/certs
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_mandatory_ciphers = high
smtp_tls_mandatory_protocols = >=TLSv1.2
smtp_tls_note_starttls_offer = no
smtp_tls_exclude_ciphers     = NULL, MD5, DES, RC4
smtp_tls_security_level = may
smtp_tls_note_starttls_offer = no

Le champ smtpd_relay_restriction est essentiel car c'est lui qui protège votre serveur de faire serveur relais. Dans mon exemple il s'agit bien d'un serveur autonome. Selon la complexité de votre infrastructure mail cela peut s'avérer totalement différent.

Le champ smtpd_tls_chain_files est celui à utiliser pour charger les certificats et ce quelques soit l'algorithme utilisé ( RSA, ECDSA, etc  ... ). Les fichier doivent être composés de la clef privée suivie du certificat lui-même.

Attention, le domaine $mydomain ne doit pas être présent dans $virtual_mailbox_domains.

Si votre serveur n'a qu'une IPv4 il faut mettre : inet_protocols = ipv4

Fichier master.cf

Dans le fichier /usr/local/etc/postfix/master.cf

smtp      inet  n       -       n       -       -       smtpd
submission  inet n       -       n       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sasl_local_domain=$myhostname
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_sender_login_maps=hash:/usr/local/etc/postfix/controlled_envelope_senders
#  -o smtpd_sender_restrictions=reject_sender_login_mismatch,reject_non_fqdn_sender
#  -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sasl_local_domain=$myhostname
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_sender_login_maps=hash:/usr/local/etc/postfix/controlled_envelope_senders

Dans cette configuration deux fichiers sont nécessaires : 

  • virtual : utilisé pour créer des alias entre deux domaines. Par exemple exemple.fr et exemple.eu, ainsi plusieurs adresses emails de domaines différents peuvent être liées à un seul compte
exemple.eu              exemple.fr
moi@exemple.eu       	moi@exemple.fr
  • controlled_envelope_senders: utilisé contrôler les adresses expéditeur en fonction du login SASL.
 # envelope sender           owners (SASL login names)
 john@example.com            john@example.com
 helpdesk@example.com        john@example.com, mary@example.com

 

Il faut ensuite générer les tables de hash à partir de fichiers plats, pour cela on utilise la commande :

postmap hash:/usr/local/etc/postfix/virtual
postmap hash:/usr/local/etc/postfix/controlled_envelope_senders

Ajouter le démarrage automatique du service postfix : sysrc postfix_enable="YES"

Spamassasin

J'ai utilisé Le blog de Nrz  pour m'aider.

Installation et paramétrage

Tout d'abord on installe le package spamassassin avec ses dépendances.

Il faut alors vérifier la configuration. Pour cela dans le fichier /usr/local/etc/mail/spamassassin/local.cf il faut vérifier les valeurs :

report_contact postmaster@domain.tld
rewrite_header Subject *****SPAM*****
bayes_ignore_header X-Bogosity
bayes_ignore_header X-Spam-Flag
bayes_ignore_header X-Spam-Status

 et dans le fichier /usr/local/etc/mail/spamassassin/init.pre les valeurs :

loadplugin Mail::SpamAssassin::Plugin::URIDNSBL
loadplugin Mail::SpamAssassin::Plugin::SPF

On ajoute le démarrage du service dans le système.

sysrc spamd_enable="YES"

Pour améliorer les performances on va utiliser une socket unix, ainsi dans le fichier /etc/rc.conf on ajoute :

spamd_flags="--socketpath=/var/run/spamd/spamd.sock --socketmode=0660 --socketowner=spamd --socketgroup=spamd"

Il faut aussi exécuter les commandes sa-update et sa-compile

Ajouter dans un crontab :

00      3       *     *     *     root    /usr/local/bin/sa-update && /usr/local/bin/sa-compile

 

Configuration de Postfix

Je ne suis pas un spécialiste de Postfix mais la méthode qui consiste à ajouter un filtre spamassassin et utiliser sendmail pour réinjecter le mail après la commande spamc ne fonctionne pas du tout. En effet sendmail réinjecte le mail dans la file de traitement Postfix qui le renvoi de nouveau dans SpamAssassin et l'histoire fini avec une erreur :

Out: 554 5.4.0 Error: too many hops

Dans notre cas nous allons utiliser spamass-milter pour utiliser Milter :

pkg install --yes spamass-milter

Il faut ajouter les lignes suivantes dans le fichier /etc/rc.conf :

spamass_milter_enable="YES"
spamass_milter_user="spamd"
spamass_milter_group="spamd"
spamass_milter_socket="/var/run/spamd/spamass-milter.sock"
spamass_milter_socket_owner="spamd"
spamass_milter_socket_group="mail"
spamass_milter_socket_mode="660"
spamass_milter_localflags="-u spamd -- -u spamd --socket=/var/run/spamd/spamd.sock"

Dans le fichier de configuration de Postfix /usr/local/etc/postfix/main.cf on adapte la ligne suivante :

smtpd_milters = unix:/var/run/spamd/spamass-milter.sock

Redémarrer les services

service postfix restart
service sa-spamd restart
service spamass-milter restart

SPF DKIM DMARC

SPF

Pour paramétrer le SPF, nous considérons que tous les services sont hébergés sur le serveur, toutes les applications utilisent le serveur de mail. 

Ayant un seul serveur ajoutera dans le DNS une entrée type TXT avec la valeur :

IN TXT "v=spf1 mx -all"

Pour utiliser un envoi de mail directement depuis une application ( comme Drupal ) on peut utiliser la configuration :

IN TXT "v=spf1 mx a:domain.tld a:www.domain.tld -all"

DKIM

Paramétrage initial

Pour installer le package on utilise la commande :

pkg install opendkim

On obtient l'information suivante à la fin de l'installation du package:

In order to run this port, write your opendkim.conf and:
if you use sendmail, add the milter socket `socketspec' in
/etc/mail/<your_configuration>.mc:
INPUT_MAIL_FILTER(`dkim-filter', `S=_YOUR_SOCKET_SPEC_, F=T, T=R:2m')
or if you use postfix write your milter socket `socketspec' in
/usr/local/etc/postfix/main.cf:
smtpd_milters = _YOUR_SOCKET_SPEC_

And to run the milter from startup, add milteropendkim_enable="YES" in
your /etc/rc.conf.
Extra options can be found in startup script.
Note: milter sockets must be accessible from postfix/smtpd;
 using inet sockets might be preferred.

Le package installe un fichier de configuration "/usr/local/etc/mail/opendkim.conf", dans ce fichier le paramètre le plus important est la socket. Nous allons modifier deux autres valeurs pour supporte le multidomaine.

Dans ce fichier commentez la ligne :

#KeyFile                        /var/db/dkim/example.private

et adapter les lignes suivantes :

KeyTable                /var/db/dkim/keytable
...
Socket                  inet:8891@localhost

Génération des clefs

Pour générer les clefs nous utilisons la commande opendkim-genkey pour les stocker dans un répertoire "/vat/db/dkim/keys/domain.tld" 

mkdir -p /var/db/dkim/keys/domain.tld
opendkim-genkey -D /var/db/dkim/keys/domain.tld -d domain.tld

La commande opendkim-genkey crée deux fichiers :

  • default.private qui contient la clef privée
  • default.txt qui contient la clef publique

Il faut alors changer le owner des fichiers.

On ajoute maintenant une référence dans le keytable ( à savoir le fichier /var/db/dkim/keytable ) sous le format "[KEYNAME] [DOMAIN]:[SELECTOR]:[KEY]" ce qui donne à titre d'exemple :

nom_de_clef domain.tld:default:/var/db/dkim/keys/domain.tld/default.private

On ajoute ensuite une référence dans le table de signature ( sa savoir le fichier /var/dkim/signingtable ) sous le format "[DOMAIN] [KEYNAME]" ce qui donne à titre d'exemple :

domain.tld nom_de_clef

Configuration Postfix

Postfix doit maintenant savoir qu'il doit interroger OpenDKIM, pour cela on édite le fichier /usr/local/etc/postfix/main.cf et on ajoute la ligne:

smtpd_milters = inet:localhost:8891

Démarrer le service

On ajouter dans les services le service "milteropendkim" :

sysrc milteropendkim_enable="YES"

puis on lance le service et on recharge la configuration Postfix :

service milter-opendkim start
postfix reload

Ajout de l'entrée DNS

On ajoute une entrée DNS pour annoncer à tous les serveurs de mails du monde notre clef publique générée précédemment, pour la configuration on autorise cette clef pour tous les sous domaines. Le "SELECTOR" utilisé lors du paramétrage apparait dans l'entrée DNS sous la forme "[SELECTOR]._domainkey" ce qui donne dans notre cas :

default._domainkey IN TXT "v=DKIM1;g=*;k=rsa;p=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;"

Pour mettre l'entrée en test on ajoute "t=y;" ce qui donne :

default._domainkey IN TXT "v=DKIM1;g=*;k=rsa;p=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;t=y;"

DMARC

J'ai utilisé le site dmarcassist.com comme source d'information : 

Politique de surveillance (p=none)

Commencez par une politique de surveillance pour collecter des données sans affecter la distribution des e-mails :

v=DMARC1; p=none; rua=mailto:dmarc-reports@votredomaine.com; sp=none; adkim=s; aspf=s

Politique de quarantaine (p=quarantine)

Une fois que vous êtes à l'aise avec les rapports, vous pouvez passer à une politique de quarantaine :

v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@votredomaine.com; ruf=mailto:dmarc-failures@votredomaine.com; sp=quarantine; adkim=s; aspf=s

Politique de rejet (p=reject)

Enfin, pour une protection maximale, vous pouvez configurer une politique de rejet :

v=DMARC1; p=reject; pct=100; rua=mailto:dmarc-reports@votredomaine.com; ruf=mailto:dmarc-failures@votredomaine.com; sp=reject; adkim=s; aspf=s