# Courrier entrant d'owni : l'usurpation du domaine Comment owni refuse un message qui se fait passer pour `@alpinux.org`, et pourquoi `postmaster@` était la seule adresse qu'on pouvait usurper sans aucun contrôle. Le pendant sortant est [`courrier-sortant.md`](courrier-sortant.md). État au 29/09/2026. ## L'incident du 28/09/2026 Un phishing (« Modification d'un e-mail envoyé », lien vers `*.web.core.windows.net`) est arrivé dans la boîte `postmaster@`, avec `From:` et `To:` tous deux à `postmaster@alpinux.org`. Il ne portait **aucun** en-tête `X-Spam-*` ni `Authentication-Results`. ``` Received: from [171.249.196.126] (unknown [171.249.196.126]) by owni.alpinux.org (Postfix) with ESMTP id 79115207A0 ``` L'expéditeur était une ADSL Viettel, qui s'est connectée directement au port 25, sans authentification. Pourtant, le SPF `-all` et le DMARC `p=quarantine` du domaine auraient suffi à l'arrêter. Aucun des deux n'a été consulté. ## Pourquoi il est passé **Postfix l'a accepté.** Le destinataire est local, et l'expéditeur `postmaster@` existe, donc `reject_unlisted_sender` le laisse passer. Il n'y avait pas de `reject_sender_login_mismatch`. Et même activé, celui-ci n'aurait rien vu : la boîte `postmaster@` a le SMTP désactivé (`mail_user.disablesmtp = 'y'`), elle est donc **absente** de `smtpd_sender_login_maps`. **rspamd ne l'a pas analysé.** Dans `/var/log/rspamd/rspamd.log` : ``` apply static settings whitelist; rcpt matched; priority high task is whitelisted (default: S (no action): [0.00/15.00] []) ... settings_id: whitelist ``` L'installeur d'ISPConfig écrit dans `/etc/rspamd/local.d/users.conf` : ``` whitelist { priority = 5; rcpt = "postmaster"; rcpt = "hostmaster"; rcpt = "abuse"; want_spam = yes; } ``` L'intention est bonne : la RFC 2142 veut que ces adresses reçoivent toujours les plaintes. Mais `want_spam = yes` coupe **toutes** les vérifications, SPF et DMARC compris, pour tout ce qui leur est adressé. ## Les trois protections en place ### 1. rspamd : liste noire sur l'enveloppe (interface ISPConfig) Dans **Email → Spamfilter → Blacklist**, deux entrées : `postmaster@alpinux.org` et `abuse@alpinux.org` (table `spamfilter_wblist`). ISPConfig génère `/etc/rspamd/local.d/users/spamfilter_wblist_N.conf` : si l'**expéditeur d'enveloppe** est cette adresse et le destinataire `@alpinux.org`, alors `reject = 0.2`. La priorité (50) l'emporte sur la liste blanche (5). À ne pas confondre avec **Email → Global Filters → Blacklist**, qui alimente la table Postfix `mail_access`. Celle-ci est lue **avant** `permit_sasl_authenticated` : un expéditeur ajouté là serait refusé même authentifié. ### 2. Postfix : expéditeur local ⇒ authentification (interface ISPConfig) Dans **System → Server Config → owni → Mail**, l'option « Reject sender and recipient login mismatch » est cochée. ISPConfig réécrit alors : ``` smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch, permit_mynetworks, check_sender_access proxy:mysql:/etc/postfix/mysql-virtual_sender.cf, reject_sender_login_mismatch, permit_sasl_authenticated, reject_non_fqdn_sender, reject_unlisted_sender ``` - Un client **non authentifié** qui envoie avec une boîte existante (SMTP activé) est refusé. - Un client **authentifié** ne peut envoyer qu'avec sa propre adresse, ou avec un alias marqué « Allow send as ». Avant d'activer l'option, j'ai vérifié sur 3 jours de logs que tous les envois SASL utilisaient leur propre adresse (`git_app.noreply`, `alpid.noreply`). `localhost` envoie avec `alpinux@` et `secretaire@`, mais passe par `permit_mynetworks`. ### 3. rspamd : analyser sans jamais rejeter (fichier, hors interface) `want_spam = yes` est remplacé dans `/etc/rspamd/local.d/users.conf` : ```diff rcpt = "abuse"; - want_spam = yes; + # Plus de want_spam : on analyse (SPF/DMARC), on ne rejette jamais (RFC 2142) + apply { + actions { + reject = null; + greylist = null; + } + } ``` L'ancien fichier est sauvegardé dans `users.conf.bak-20260929`. Pour que la correction survive à une mise à jour d'ISPConfig, une copie est placée dans `/usr/local/ispconfig/server/conf-custom/install/rspamd_users.conf.master`. ## Pourquoi pas « destination locale ⇒ authentification » Ce serait refuser toute la réception : le port 25 est le MX, et aucun serveur extérieur (Gmail, Orange, les listes) ne s'y authentifie. La règle porte sur l'**expéditeur** local (protection 2). Celle-ci ne suffit pas seule : elle lit l'enveloppe (`MAIL FROM`), pas l'en-tête `From:`. Un `MAIL FROM:` accompagné de `From: postmaster@alpinux.org` passe Postfix. C'est DMARC, dans rspamd, qui l'arrête, et il ne le peut que si la liste blanche ne l'en empêche pas (protection 3). ## Où finit le spam de postmaster@ Dans `Junk`. La chaîne : 1. rspamd, via `milter_headers`, pose `X-Spam: Yes` et `X-Spam-Status: Yes, score=…`. 2. Dovecot exécute `sieve_before = /var/vmail/%d/%n/.ispconfig-before.sieve`, généré par ISPConfig parce que `mail_user.move_junk = 'y'` : `if header :matches "X-Spam-Status" "Yes, *" { fileinto :create "Junk"; stop; }` 3. En secours, `sieve_before2 = /var/lib/dovecot/sieve/spam-to-junk.sieve` fait la même chose. La relève de la messagerie lit `INBOX,Junk` (`IMAP_PM_DOSSIER`) : un rapport DMARC classé à tort reste donc traité. ## Vérifier ```sh # Rejouer une usurpation dans rspamd, depuis l'IP de l'attaquant rspamc -h localhost:11333 -i 171.249.196.126 \ -F -r < test.eml # Le tri sieve, à sec, sur une copie du script et un maildir jetable # ($W doit être lisible par vmail ; -u postmaster@… échoue sur l'auth) rspamc -h localhost:11333 --mime -i 171.249.196.126 -F bidon@example.ru \ -r postmaster@alpinux.org < test.eml > $W/out.eml sudo sieve-test -o mail_uid=vmail -o mail_gid=vmail \ -o mail_location=maildir:$W/md $W/before.sieve $W/out.eml # Un utilisateur qui envoie avec une adresse qui n'est pas la sienne sudo grep "not owned by user" /var/log/mail.log ``` Résultats relevés le 29/09/2026 : | Scénario | Avant | Après | |---|---|---| | Enveloppe et `From:` = postmaster@, vers postmaster@ | accepté, 0.00 | **rejeté** | | Enveloppe bidon, `From:` = postmaster@, vers postmaster@ | accepté, 0.00 | **Junk**, 17.80 (SPF, DMARC) | | Même chose vers president@ | rejeté | rejeté | | Rapport externe légitime vers postmaster@ | accepté | accepté, -0.40 | ## Pièges - **Un refus `not owned by user`** : quelqu'un envoie avec un alias sans « Allow send as ». Cocher la case sur l'alias dans ISPConfig ; ne pas décocher l'option globale. - **Après une mise à jour d'ISPConfig**, vérifier que `users.conf` n'a pas retrouvé `want_spam` : la copie dans `conf-custom/install/` doit l'éviter. - **Les boîtes au SMTP désactivé et les redirections sans « Allow send as »** (`abuse@`, `kernel@`, `cedric.a5l@`) ne sont pas couvertes par la protection 2. Seuls DMARC et, pour `abuse@`, la liste noire les protègent. ## Retour arrière ```sh sudo cp -a /etc/rspamd/local.d/users.conf.bak-20260929 /etc/rspamd/local.d/users.conf sudo rm /usr/local/ispconfig/server/conf-custom/install/rspamd_users.conf.master sudo systemctl reload rspamd ``` Les protections 1 et 2 s'annulent depuis l'interface ISPConfig.