Douze constructions

Un serveur mail auto-hébergé qui atteint réellement la boîte de réception

Postfix, Dovecot et rspamd sur une seule instance, avec SPF, DKIM et DMARC correctement configurés, et une étape de vérification qui lit les en-têtes du destinataire.

Ce que ce guide construit

Un serveur mail complet pour un seul domaine : Postfix pour le transport, Dovecot pour IMAP et la livraison locale, rspamd pour le filtrage et la signature DKIM, et les trois enregistrements DNS qui décident si les grands récepteurs placent votre courrier dans la boîte de réception ou dans un dossier que personne n'ouvre. Il envoie, il reçoit, il authentifie, et ce n'est pas un relais ouvert.

Gérer son propre mail est un conseil démodé et c'est souvent pour une bonne raison. La délivrabilité est la partie difficile, pas le logiciel. Si le DNS est mal configuré, le Postfix le plus soigneusement configuré du monde envoie des messages dans le vide.

Avant de commencer

  • Une R-8 ou plus. Le filtrage est gourmand en CPU et rspamd utilisera volontiers tous les cœurs pendant une vague de spam.
  • Un domaine dont vous contrôlez le DNS, et de la patience pour la propagation.
  • Le reverse DNS configuré sur l'adresse de l'instance pour pointer vers votre nom de domaine mail. Il est modifiable depuis le panneau et il est obligatoire : les récepteurs rejettent les expéditeurs non résolubles.
  • Un ticket au support pour demander si le port 25 sortant est ouvert sur votre instance. Demandez avant de construire, pas après.
  • mail.example.com partout. Remplacez par vos propres valeurs.

1. Nom d'hôte et DNS

hostnamectl set-hostname mail.example.com
apt update && apt full-upgrade -y

Publiez ces enregistrements maintenant, car l'étape du certificat a besoin de l'enregistrement A et l'étape de signature a besoin d'un endroit pour mettre une clé. Les valeurs du tableau indiquent ce que fait chaque enregistrement, pas ce qu'il faut coller.

TypeNomContenu
A / AAAAmailLes adresses de l'instance depuis le panneau
MX@10 mail.example.com.
TXT@v=spf1 mx -all
TXT_dmarcv=DMARC1; p=none; rua=mailto:[email protected]; adkim=s; aspf=s
PTRadresse de l'instancemail.example.com — défini dans le panneau

L'enregistrement SPF indique : mes serveurs MX envoient mon courrier, tout le reste est falsifié. Échec strict plutôt que souple, car ~all invite les récepteurs à prendre leur propre décision, et leur décision ne sera pas la plus généreuse. DMARC commence à p=none afin que vous collectiez des rapports pendant une semaine avant que quoi que ce soit soit rejeté en votre nom.

2. Certificats

apt install -y certbot
certbot certonly --standalone -d mail.example.com

Rien n'écoute encore sur le port 80, donc le mode autonome est le plus simple. Les hooks de renouvellement viendront à la fin, une fois que les démons existeront pour recharger.

3. Postfix

DEBIAN_FRONTEND=noninteractive apt install -y postfix postfix-pcre dovecot-imapd dovecot-lmtpd rspamd redis-server

Maintenant, définissez la configuration de transport. Chaque ligne ci-dessous est délibérée ; postconf les écrit en place, donc il n'y a pas d'éditeur à mal utiliser :

postconf -e "myhostname = mail.example.com"
postconf -e "mydestination = localhost"
postconf -e "smtpd_banner = \$myhostname ESMTP"
postconf -e "inet_interfaces = all"
postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem"
postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem"
postconf -e "smtpd_tls_security_level = may"
postconf -e "smtp_tls_security_level = dane"
postconf -e "smtpd_tls_mandatory_protocols = >=TLSv1.2"
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination"
postconf -e "smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unknown_recipient_domain reject_unauth_destination"
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "virtual_mailbox_domains = example.com"
postconf -e "smtpd_milters = inet:127.0.0.1:11332"
postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
postconf -e "milter_default_action = accept"

La ligne la plus importante est smtpd_relay_restrictions. Elle se termine par reject_unauth_destination, ce qui empêche tout Internet d'utiliser votre machine pour envoyer du courrier. Un relais ouvert vous fait radier en quelques heures et constitue une violation de la politique d'utilisation acceptable en plus.

Activez le port de soumission pour que vos propres clients puissent envoyer, avec authentification requise et aucun accès anonyme :

postconf -M submission/inet="submission inet n - y - - smtpd"
postconf -P "submission/inet/syslog_name=postfix/submission"
postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
postconf -P "submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"

4. Dovecot

Les boîtes aux lettres en Maildir sous un seul utilisateur système maintient ce montage simple. Créez l'utilisateur et le stockage :

groupadd -g 5000 vmail
useradd -g vmail -u 5000 -d /var/vmail -m vmail
install -d -o vmail -g vmail -m 700 /var/vmail/example.com

Écrivez /etc/dovecot/conf.d/99-local.conf :

mail_location = maildir:/var/vmail/%d/%n
mail_uid = vmail
mail_gid = vmail
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
ssl_min_protocol = TLSv1.2
auth_mechanisms = plain login
disable_plaintext_auth = yes

passdb {
  driver = passwd-file
  args = scheme=ARGON2ID username_format=%u /etc/dovecot/users
}
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

Créez une boîte aux lettres. La commande demande deux fois le mot de passe et écrit un hash, jamais le mot de passe lui-même :

echo -n "[email protected]:" >> /etc/dovecot/users
doveadm pw -s ARGON2ID >> /etc/dovecot/users
chmod 640 /etc/dovecot/users
chgrp dovecot /etc/dovecot/users

5. rspamd et DKIM

Générez la clé de signature, puis publiez la partie publique :

install -d -o _rspamd -g _rspamd -m 750 /var/lib/rspamd/dkim
rspamadm dkim_keygen -s mail -b 2048 -d example.com -k /var/lib/rspamd/dkim/example.com.mail.key
chown _rspamd:_rspamd /var/lib/rspamd/dkim/example.com.mail.key
chmod 400 /var/lib/rspamd/dkim/example.com.mail.key

Cette commande affiche un enregistrement DNS sur la sortie standard. Publiez-le comme enregistrement TXT à mail._domainkey.example.com, exactement comme imprimé, avec les segments entre guillemets joints comme votre fournisseur DNS l'attend. Ensuite, dites à rspamd où se trouve la clé, dans /etc/rspamd/local.d/dkim_signing.conf :

path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector = "mail";
allow_username_mismatch = true;
use_domain = "header";
sign_authenticated = true;
sign_local = true;

Liez le milter et définissez un mot de passe pour l'interface web :

echo "bind_socket = \"127.0.0.1:11332\";" > /etc/rspamd/local.d/worker-proxy.inc
rspamadm pw

Collez le hash résultant dans /etc/rspamd/local.d/worker-controller.inc comme password = "...". Accédez à l'interface via un tunnel SSH plutôt que d'ouvrir le port 11334 au monde.

6. Démarrez tout

systemctl enable --now redis-server rspamd dovecot postfix
postfix check
systemctl --no-pager --failed

Ajoutez un hook de renouvellement afin qu'un nouveau certificat atteigne les deux démons :

echo "systemctl reload postfix dovecot" > /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh

Vérification

Trois tests. Le premier est local, le second est celui qui importe, le troisième est celui qui vous garde sur les listes noires.

echo | openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com 2>/dev/null | grep -E "subject=|Verify return"

Ensuite, envoyez un message depuis votre nouveau serveur vers une boîte aux lettres que vous détenez chez un grand fournisseur de webmail, ouvrez le message reçu et lisez ses en-têtes bruts. Vous cherchez une ligne :

Authentication-Results: mx.receiver.example;
  dkim=pass [email protected];
  spf=pass smtp.mailfrom=example.com;
  dmarc=pass (p=NONE) header.from=example.com

Trois succès et vous avez terminé. Un dkim=none signifie que rspamd ne signe pas, vérifiez donc rspamadm configdump dkim_signing. Un spf=fail signifie presque toujours que le message est parti en IPv6 alors que votre enregistrement SPF ne couvre que l'adresse MX v4.

Enfin, prouvez que vous n'êtes pas un relais. Depuis une autre machine, connectez-vous et essayez d'envoyer un courrier entre deux domaines que vous ne possédez pas :

apt install -y swaks
swaks --to [email protected] --from [email protected] --server mail.example.com

Le résultat correct est un rejet au stade du destinataire : 554 5.7.1 Relay access denied. Toute autre chose signifie que vous avez configuré une machine qui sera abusée dans la journée, et vous devriez vous arrêter et relire l'étape trois.

Ensuite

Laissez DMARC à p=none pendant une semaine et lisez les rapports agrégés. Une fois qu'ils montrent que seul votre serveur signe votre courrier, passez à p=quarantine, puis p=reject deux semaines plus tard. Ajoutez une sauvegarde hors nœud pour /var/vmail pendant que vous y êtes, car le courrier est la seule chose dont les utilisateurs ne font jamais une deuxième copie, et notre add-on de sauvegarde écrit sur un site différent de celui de l'instance.

Prêt quand vous l'êtes

Choisissez une ville. Choisissez une taille. Payez en crypto.

Aucun formulaire sur votre identité, pas d'attente d'approbation humaine, pas d'appel téléphonique pour vérifier quoi que ce soit. La facture est réglée et les identifiants arrivent dans votre boîte mail.