diff --git a/services/mail/normes.md b/services/mail/normes.md new file mode 100644 index 0000000..1e38b38 --- /dev/null +++ b/services/mail/normes.md @@ -0,0 +1,435 @@ +# Résumé + +## Objectif du document + +Description de plusieurs RFC intéressantes (ou non) autour des protocoles liés +aux emails. Lorsque ces normes sont en application au Cr@ns (ou ont +volontairement été repoussées à plus tard), les solutions techniques étudiées +seront décrites. + +*Remarques préalables :* + +- SMTP est un protocole incontournable car largement utilisé. Malgré tous ses + défauts, il restera important pendant un bon bout de temps. Pour cette raison, + de nombreuses personnes ont cherché à augmenter la sécurité des emails tant + bien que mal, en proposant de chiffrer les mails qui transitent d'un MTA à un + autre, signant les mails émis par un serveur,... Toutes ces techniques sont + mises en place autour du protocole mail, lequel ne change pas. +- Aujourd'hui, certains organismes influents ont le bon goût de rejeter les + mails issus de serveurs n'implémentant pas les protocoles les plus + importants. Quoi que l'on pense du poids de l'influence des géants, cela + permet d'élever les standards qualités des autres. Serons-nous un jour + spam-free ? Les publicités mentionnant nos informations personnelles (nom, + préférences, ...) seront-elles un jour toutes chiffrées ? Je ne sais pas, + mais je l'espère haha. + +## Au Cr@ns + +| | Statut au Cr@ns ? | Adoption | +|---------|-------------------|------------------------------------| +| SPF | Implémenté | Large | +| DKIM | Implémenté | Large | +| SRS | Implémenté | ? | +| DMARC | Non-implémenté | Large | +| ARC | Non-implémenté | ? (Google l'utilise) | +| MTA-STS | Non-implémenté | ? (MS, Méta et Google l'utilisent) | +| DANE | Non-implémenté | Faible (requiert DNSSEC) | + +Tous ce qui est discuté ci-dessous fonctionne de la manière suivante : + +- l'infrastructure émettrice (le Cr@ns) publie des informations la concernant, +- les serveurs réceptionnant les mails (les `MX` des destinataires + des mails émis par + le Cr@ns) peuvent vérifier les mails à l'aide de ces informations. + +*NB :* je parle d'infrastructure ou d'organisation émettrice et non pas de serveur +émetteur car plus d'un serveur est souvent requis (*e.g.* un serveur DNS +autoritaire, un serveur Web,...). + +## SPF + +- [SPF](https://www.rfc-editor.org/rfc/rfc7208), +- [Page Wikipédia](https://en.wikipedia.org/wiki/Sender_Policy_Framework). + +Le SPF (*Sender Policy Framework*) permet d'indiquer quels serveurs ont le droit +d'émettre des mails en `crans.org` (ou tout autre domaine, bien entendu). + +### Implémentation (côté infrastructure émettrice) + +Pour cela, nous publions un champ `TXT` pour `crans.org`. Voici le contenu que l'on +obtient pour quelques associations avec `kdig -t TXT crans.org` (`dig` +peut être utilisé à la place de `kdig`) : + +Au Cr@ns : + +```txt +v=spf1 mx ip4:185.230.79.1 ip6:2a0c:700:2:0:ec4:7aff:fe59:a1ad ip4:185.230.79.38 +ip6:2a0c:700:2::ff:fe01:3502 ~all +``` + +Cela signifie que les serveurs mail du Cr@ns (`mx`) et les adresses listées (et +celles-ci uniquement) ont le droit d'envoyer des mails dont la source +prétendue est *...@crans.org*. + +Utiliser `~all` permet d'indiquer que si un mail provient d'une autre IP, il ne +faut pas rejeter le mail, mais le mettre en *permerror*. + +À l'April : + +```txt +v=spf1 include:spf.mailjet.com mx ip4:62.73.5.35 include:spf.protection.outlook.com include:_spf.april.com ip4:37.71.69.68 ip4:37.71.69.69 ip4:37.71.69.70 include:_spf.salesforce.com -all +``` + +Idem, avec des champs `include:...` en plus. Ces derniers permettent d'inclure +un autre enregistrement SPF (*e.g.* celui de `spf.mailjet.com`). + +Utiliser `-all` permet de demander aux serveurs récepteurs de rejeter tout mail +ne satisfaisant pas ce test. +C'est une politique plus sévère que `~all`, qui a l'avantage de +filtrer plus efficacement les mails douteux et l'inconvénient +de risquer des pertes de mails plus ou moins importants, +en tout cas légitimes, émis par des domaines configurés +avec un respect des standards mail plus léger. + +D'autres mécanismes et formats existent, mais nous ne les présentons pas +ici. Se référer à la RFC ou la page Wikipédia pour leur description. + +### Vérification (côté serveur récepteur) + +Lorsque `redisdead` (le `MX` du Cr@ns) reçoit un mail, nous demandons à un service +externe de vérifier le SPF (via la variable `smtpd_recipient_restrictions`). Le +service externe tourne sur la même VM et est `postfix-policyd-spf-python`. + +## SRS + +- [Le papier d'origine](https://www.libsrs2.org/srs/srs.pdf), +- [La page Wikipédia](https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme). + +Au Cr@ns comme ailleurs, on aime bien les mailing-lists +et les transferts automatiques de mails par `.forward`. +Le problème, c'est qu'intercaler un serveur entre l'expéditeur et +le destinataire final est parfois peu distingable d'une usurpation. + +Cas d'usage : un expéditeur envoie un mail à une mailing-list (du Cr@ns), +qui retransmet aux adresses abonnées, qu'elles soient ou non au Cr@ns. +Un problème survient, empêchant un abonné de recevoir le mail +(à tout hasard, le quota de stockage est dépassé). +Ce problème génère un *bounce*, un mail automatique d'erreur. + +Question : qui doit recevoir ce *bounce* ? +Logiquement, l'expéditeur d'origine, c'est lui qui a envie +de savoir qu'un destinataire n'a pas lu son message. + +Pour cela, le serveur intermédiaire va conserver le champ `Envelope-From` +d'origine et passer le mail tel quel au serveur final. +Or, ce choix bien intentionné se heurte, comme annoncé, +aux politiques anti-usurpation à base de `SPF`. +Si le serveur de l'expéditeur applique une politique `SPF` +strice (`-all`) et que le serveur d'arrivée suit les instructions, +le mail transféré sera refusé en raison de son champ `SPF` invalide. + +Comment faire ? Réfléchissons à partir de nos contraintes : +dans le pire des cas, on doit s'adapter à une politique `SPF` +stricte pour ne perdre aucun mail d'adhérent. +On doit donc montrer patte blanche en transférant le mail +avec un champ `Envelope-From` dans notre domaine, +de sorte que le mail soit accepté à l'arrivée. + +Conséquence : c'est à nous que reviendront les +éventuels *bounces* qui nous motivaient à l'origine. +Sauf qu'ils ne nous intéressent pas directement, +on doit trouver un moyen de les renvoyer à l'expéditeur. + +C'est là que `SRS` entre en jeu : il fabrique, +en suivant un schéma de nommage normalisé, +une adresse temporaire qui va encoder l'adresse de +l'expéditeur d'origine, plus quelques métadonnées, +dans la partie "compte" (avant le `@`) de l'adresse fabriquée. + +Prenons un exemple, éhontément pris de la page Wikipédia. +Alice, détentrice de l'adresse `alice@nane.in`, +veut envoyer un mail à son ami Bob, détenteur de +l'adresse `bob@crans.org`. +Ce qu'Alice ne sait pas (et n'a pas besoin de savoir), +c'est que Bob est en train de passer ses contacts +sur son adresse ENS, `bob@ens-cachan.fr`. +Il transfère donc tous ses mails Cr@ns vers sa +boîte ENS, sans avoir besoin de prévenir qui que ce soit. + +À la réception d'un mail d'Alice, le serveur du Cr@ns (`redisdead`) +va lire l'instruction de forwarding de Bob et va changer le champ +`Envelope-From` de `alice@nane.in` (origine) à +`SRS0=HHH=TT=nane.in=alice@crans.org`. +Le `HHH` est un hash d'identification, le `TT` +un marqueur temporel. + +Si la boîte mail ENS de Bob est pleine, le *bounce* part sur +l'adresse `SRS` et est ensuite retransféré à Alice, dont +l'adresse est clairement extractible de l'adresse `SRS`. +Et voilà ! + +*Note :* les adresses générées par `postsrsd` sont valides pendant 21 jours. + +*Note 2 :* si un utilisateur a l'idée saugrenue de prendre +un alias commençant par `SRS0=`, on va peut-être avoir un problème. +Prions pour que ça n'arrive pas. + +### Implémentation + +TODO + +## DKIM + +- [La RFC](https://www.rfc-editor.org/rfc/rfc6376.html), +- [La page Wikipédia](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail). + +Le protocole DKIM (*Domain Key Identified Mail*) permet au serveur +émetteur de signer les +mails, et au serveur récepteur de vérifier cette signature, en utilisant des +méthodes de cryptographie asymétrique. + +### Implémentation (côté émetteur) + +#### Serveur mail + +Le serveur émetteur possède la clef privée. Il ajoute à tout mail sortant un +champ à l'en-tête de la forme suivante : + +```txt + DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=crans.org; s=mail; + t=1702660809; bh=NqcDLO2gkZU0IxcV+mE7uZ2NRnN/yfceH73Q1nhaFg4=; + h=From:To:Subject:Date:From; + b=ZjomU0jkljKVwA6sUhUioCemnxh/OhSGgwwr57irEn39Gfbv8/cLF8jmHc3hmv4ly + fLvJdj7iVTkeGlTVeW72H93wEA0qrB6LHHz81YBeHPb8eg63zm+9soDSOaP91Gux8J + UgeY1PWXvfjdfe+MJX9JqnlBKqd4JRgpD8AXaO852Lrq+fLJy4ewLOc/3dAqpNMrTf + swi5y6vV5QH89cuFjpjWqF3UcuD4a20RCQIpU/j5K1sxr1CTbdKjgqlsq5mt9/JSKx + OcvZ5WTmgPwdimKKz0DfjAeXQBMac9d7V9Kb5LvCZx84kSbLQEKboGxpRRhNWGdBsK + f3YZXjmpe8cl8cpbvuvdKYWOE7E6fRGu/CwQEyEQYqmrmljiklSYPaG8IKs5uYWKrA + A2D4VTisIYOwGvdljFTQP5zfhPsi4OnNbiN3RVX475lCHNWbnFMh8OCF/ugLj30dyk + s8MLAzDyYlgaccOD0uZ6VsdGJ0LK8+TCKbsc5H1ynjg0VejmRyVzZJ5TzAjXrzS6CC + Lj9eQQex1IaO6d7uGe4P/ULghjSP90tgBcZVNFLlU3r59ylkVQyAu7THDr4CDaxFO0 + 63QE7/GNDE2vZv0K5gp5Yz2veVC3wyaP1dJzIoAzZc1kZRoWz6QK9cH1Bfmnlx9nUs + j+G+VLDQbxi2NuoYAD/I2naA= +``` + +Le bloc contient une liste de clefs-valeurs : + +- `v` indique la version du protocole, +- `d` le domaine attestant de la validité du mail, +- `s` le nom du sélecteur (/Cf/. plus bas), +- `b` et `bh` contiennent les signatures. + +*Notes :* + +- Il est possible que le mail ne soit pas signé par le domaine correspondant à + l'adresse d'envoi, puisqu'il est possible d'autoriser autrui à envoyer un + mail à notre place (*cf*. SPF plus haut). +- Se référer à la page Wikipédia, ou à la RFC pour une liste exhaustive des + clefs. + +#### Serveur DNS + +Il faut placer dans le serveur DNS un champ TXT dont la clef est +`sélecteur._domainkey.domain`, où `domain` (resp. `sélecteur`) est la valeur de la +clef `d` (resp. `s`) définie plus haut. + +Par exemple, pour le champ fourni plus haut, nous pouvons lire : + +```txt +"v=DKIM1; k=rsa; " +"p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtwkNVd9Mmz8S4WcfuPk0X2drG39gS8" " ++uxAv8igRILgzWeN8j2hjeZesl8pm/1UTVU87bYcdfUgXiGfQy9nR5p/Vmt2kS7sXk9nsJ/VYENg" +"b3IJQ6paWupSTFMyeKycJ4ZHCEZB/bVvifoG6vLKqW5jpsfCiOcfdcgXATn0UPuVx9t93yRrhoEM" +"ntMv9TSodjqd3FKCtJUoh5cNQHo0T6dWKtxoIgNi/mvZ92D/IACwu/XOU+Rq9fnoEI8GukBQUR5A" "kP0B/ +JrvwWXWX/3EjY8X37ljEX0XUdq/ShzTl5iK+CM83stgkFUQh/rpww5mnxYEW3X4uirJ7VJH" "mY4KPoIU ++2DPjLQj9Hz63CMWY3Ks2pXWzxD3V+GI1aJTMFOv2LeHnI3ScqFaKj9FR4ZKMb0OW2BE" "FBIY3J3aeo/ +paRwdbVCMM7twDtZY9uInR/NhVa1v9hlOxwp4/2pGSKQYoN2CkAZ1Alzwf8M3EONL" +"KeiC43JLYwKH1uBB1oikSVhMnLjG0219XvfG/tphyoOqJR/bCc2rdv5pLwKUl4wVuygfpvOw12bc" "vnTfYuk/ +BXzVHg9t4H8k/DJR6GAoeNAapXIS8AfAScF8QdKfplhKLJyQGJ6lQ75YD9IwRAN0oV+8" "NTjl46lI/C ++b7mpfXCew+p6YPwfNvV2shiR0Ez8ZGUQIcCAwEAAQ==" +``` + +### Vérification (côté récepteur) + +Côté réception (`redisdead` pour nous), nous utilisons le milter (filtre pour +mail) fourni par `opendkim`. Ce milter écoute en local et est appelé par `postfix`. +Lors de la réception d'un mail, postfix demande à `opendkim` quelle décision +prendre. Ce dernier va regarder les en-têtes du mail. Si il trouve une signature +DKIM, il va effectuer la requête DNS décrite plus haut et vérifier la signature +du mail (valeurs des clefs `b` et `bh`). + +## DMARC + +- [La RFC](https://www.rfc-editor.org/rfc/rfc7489), +- [La page Wikipédia](https://en.wikipedia.org/wiki/DMARC). + +## ARC + +- [La RFC](https://www.rfc-editor.org/rfc/rfc8617.html), +- [La page Wikipédia](https://en.wikipedia.org/wiki/Authenticated_Received_Chain). + +## MTA-STS + +- [La RFC](https://datatracker.ietf.org/doc/html/rfc8461), +- [La page Wikipédia](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#SMTP_MTA_Strict_Transport_Security). + +Le MTA-STS consiste à publier les protocoles de sécurité supportés par les +serveur mail d'un certain domaine (pour nous, les mails en `@crans.org`). + +Contrairement au `DANE` (décrit plus bas), ce protocole ne demande pas la mise en +place de DNSSEC. En revanche, il demande d'avoir un serveur Web accessible en +`https` (pour nous, `https://crans.org` doit être servi par un serveur Web). + +### Implémentation (côté infrastructure émettrice) + +#### Dans la zone DNS + +Il faut ajouter un champ `TXT` accessible à `_mts-sts.domain.tld`. + +Quelques exemples : + +- Gmail : `v=STSv1; id=20190429T010101;`, +- Microsoft : `v=STSv1; id=20190225000000Z;`, +- Outlook : `v=STSv1; id=20190225000000Z;`. + +#### Sur le serveur Web + +Il faut que le serveur Web associé serve un fichier texte accessible à l'adresse +`https://mta-sts.domain.tld/.well-known/mta-sts.txt` + +Quelques exemples : + +- [Gmail](https://mta-sts.gmail.com/.well-known/mta-sts.txt), +- [Outlook](https://mta-sts.outlook.com/.well-known/mta-sts.txt), +- [Microsoft](https://mta-sts.microsoft.com/.well-known/mta-sts.txt). + +Le fichier texte contient une liste de clefs-valeurs. Ces clefs décrivent quel +protocole sera utilisé. + +### Vérification côté récepteur + +Est-il possible d'utiliser `postfix-mta-sts-resolver` ? N'ayant pas implémenté cette +solution pour le moment (ni au Cr@ns, ni personnellement), nous ne pouvons pas +commenter sur le sujet. + +## DANE + +- [La RFC](https://www.rfc-editor.org/rfc/rfc6698), +- [La page Wikipédia](https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities). + +Actuellement, pour vérifier un certificat `C` proposé par un serveur mail, il faut +faire confiance à un certificat racine, lequel est utilisé pour signer un autre +certificat (dit *certificat intermédiaire*), lequel est utilisé pour signer le +certificat `C`. Pour vérifier `C`, il faut + +- faire confiance au certificat racine, +- vérifier les deux signatures sus-mentionnées. + +`DANE` est une norme permettant aux propriétaires de domaines de déclarer quels +cetificats doivent être acceptés pour quels services. + +*Note :* cela n'est pas spécifique aux mails. + +### Implémentation (côté infrastructure émettrice) + +Pour mettre en place `DANE`, il suffit d'ajouter un champ DNS à sa zone : + +- Il faut que la zone soit signée DNSSEC. +- Le champ à ajouter est : + - de type TLSA (TLS Authentication), + - de clef `_port._protoL4.domain.tld`. + - de valeur `x y z t`, où : + - `x` est appelé `certificate usage`, + - `y` est appelé `selector`, + - `z` est appelé `matching type`, + - `t` est appelé `certificate associated data`. + +### Format du champ TLSA + +#### Certificate usage + +L'objectif de ce champ est d'indiquer comment vérifier le certificat. + +| *Valeur* | *Signification* | +|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0 | Le certificat doit être valide (`root` -> `intermediate` -> `cert`), et `associated data` décrit l'un des certificats parents de `cert` | +| 1 | `associated data` décrit `cert`, et le certificat doit aussi être valide par rapport à un certificat racine de confiance. | +| 2 | `associated data` décrit un parent de `cert`. Ce parent est supposé de confiance, et `cert` doit bien être son descendant. | +| 3 | `associated data` décrit `cert`. Le certificat n'a pas besoin d'être valide par rapport à un certificat racine. Il a simplement besoin de correspondre à `associated data`. | + +#### Selector + +Ce champ décrit ce qui est décrit par `associated data`. + +| *Valeur* | *Signification* | +|--------|-----------------------------| +| 0 | Tout le certificat. | +| 1 | Seulement la clef publique. | + +#### Matching type + +Ce champ indique comment vérifier `associated data` contre la donnée du certificat +(ou de la clef publique). + +| *Valeur* | *Signification* | +|--------|--------------------------------------------------------| +| 0 | `associated data` doit être égal à la donnée. | +| 1 | `associated data` doit être égal au sha256 de la donnée. | +| 2 | `associated data` doit être égal au sha512 de la donnée. | + +où la donnée est décrite par le `selector` et le choix de certificat décrit par +le `certificate usage`. + +#### Certificate associated data + +Chaîne de caractères au format hexadécimal. + +### Recommandation pour le Cr@ns + +À titre personnel, j'utilise des champs TLSA en `3 0 1`. Je pense que le Cr@ns +peut faire la même chose (ou du `3 0 2`). + +### Mise en place + +Hypothèses : + +- le serveur DNS accepte des mises à jour DNS dynamiques de la part du serveur + mail, +- le renouvellement du certificat utilise `certbot`. + +Mise en place : + +- Dans la confguration `certbot`, + - passer en challenge DNS-01 et : + - `manual_auth_hook` : un script mettant en place le challenge, + - `renew_hook` : script de déploiement du certificat, lequel *ajoute* un champ + TLSA et place le certificat à déployer dans un dossier "staging", + - `manual_cleanup_hook` : un script retirant le challenge `acme`. +- Roll-over scheme : Un champ DNS a une durée de vie (TTL), généralement 1h. De + ce fait, les requêtes de chalmp TLSA peuvent être en retard d'une heure (au + plus). Il est done conseillé d'avoir le nouveau champ TLSA en place pendant + deux TTL avant de (1) mettre en place le nouveau certificat et (2) retirer le + vieux champ TLSA. + +Je propose de mettre en place un timer `systemd` qui serait activé "après +l'arrêt de `certbot` pour plus de 2 TTLs". Ce timer lancerait un service, lequel +aurait une condition d'activation "un certificat existe dans le dossier +staging". + +### Exemple + +```txt + dig +short TLSA _25._tcp.nanein.fr + => 3 0 1 50E9221F066DCD1991ED9D3BA0AD10159F3585780F6FABBAE2942E43 37789FC8 +``` + +### Implémentation (côté serveur mail destinataire) + +Côté serveur mail destinataire, la configuration est très simple (car nous +utilisons Postfix). Cela se fait principalement via les options suivantes : + +- `smtp_dns_supoprt_level` (valeur `dnssec`) +- `smtp_tls_dane_insecure_mx_policy` (valeur `dane`) + +D'autres options de Postfix peuvent être utilisées pour permettre un contrôle +plus fin sur le comportement du service. diff --git a/services/mail/normes.org b/services/mail/normes.org deleted file mode 100644 index 44650b0..0000000 --- a/services/mail/normes.org +++ /dev/null @@ -1,355 +0,0 @@ --*- mode: org; org-hide-emphasis-markers: t; -*- - -#+TITLE: Description de normes autour des emails. -#+AUTHOR: Des nounous quelconques. -#+EMAIL: contact@crans.org -#+SEQ_TODO: TODO | in_progress | DONE -#+DESCRIPTION: Pfiou que c'est fastidieux d'apprendre à parler au monde entier. -#+INSTITUTE: Cr@ns -#+LANGUAGE: fr -#+STARTUP: overview -#+OPTIONS: broken-links:t - -* Résumé - -** Objectif du doc - -Description de plusieurs RFC intéressantes (ou non) autour des protocoles liés -aux emails. Lorsque ces normes sont en application au Cr@ns (ou ont -volontairement été repoussées à plus tard), les solutions techniques étudiées -seront décrites. - -/Remarques préalables/ : - -- SMTP est un protocole incontournable car largement utilisé. Malgré tous ses - défauts, il restera important pendant un bon bout de temps. Pour cette raison, - de nombreuses personnes ont cherché à augmenter la sécurité des emails tant - bien que mal, en proposant de chiffrer les mails qui transitent d'un MTA à un - autre, signant les mails émis par un serveur, ... Toutes ces techniques sont - mises en place autour du protocole mail, lequel ne change pas. - -- Aujourd'hui, certains organismes influents ont le bon goût de rejeter les - mails issus de serveurs n'implémentant pas les protocoles les plus - importants. Quoi que l'on pense du poids de l'influence des géants, cela - permet d'élever les standards qualités des autres. Serons-nous un jour - spam-free ? Les publicités mentionnant nos informations personnelles (nom, - préférences, ...) seront-elles un jour toutes chiffrées ? Je ne sais pas, - mais je l'espère haha. - -** Au Cr@ns - -| | /Statut au Cr@ns/ ? | Adoption | -|---------+-------------------+------------------------------------| -| SPF | Implémenté | Large | -| DKIM | Implémenté | Large | -| SRS | Implémenté | ? | -| DMARC | Non-implémenté | Large | -| ARC | Non-implémenté | ? (Google l'utilise) | -| MTA-STS | Non-implémenté | ? (MS, Méta et Google l'utilisent) | -| DANE | Non-implémenté | Faible (requiert DNSSEC) | - -Tous ce qui est discuté ci-dessous fonctionne de la manière suivante : -- l'infrastructure émettrice (le Cr@ns) publie des informations la concernant, -- les serveurs réceptionnant les mails (~MX~ des destinataires des mails émis par - le Cr@ns) peuvent vérifier les mails à l'aide de ces informations. - -/NB/ : Je parle d'infrastructure ou d'organisation émettrice et non pas de serveur -émetteur car plus d'un service est souvent requis (/e.g./ un serveur DNS -autoritaire, un serveur Web, ...). - - -* SPF - -- [[https://www.rfc-editor.org/rfc/rfc7208][SPF]], -- [[https://en.wikipedia.org/wiki/Sender_Policy_Framework][Page Wikipédia]]. - -Le SPF (/Sender Policy Framework/) permet d'indiquer quels serveurs ont le droit -d'émettre des mails en ~crans.org~ (ou tout autre domaine, bien entendu). - -** Implémentation (côté infrastructure émettrice) - -Pour cela, nous publions un champ ~TXT~ pour ~crans.org~. Voici le contenu que l'on -obtient pour quelques associations (obtenues avec ~kdig -t TXT crans.org~ (~dig~ -peut être utilisé à la place de ~kdig~) : - -- Cr@ns: ~v=spf1 mx ip4:185.230.79.1 ip6:2a0c:700:2:0:ec4:7aff:fe59:a1ad ip4:185.230.79.38 ip6:2a0c:700:2::ff:fe01:3502 ~all~ - - Cela signifie que les serveurs mail du Cr@ns (~mx~) et les adresses listées (et - celles-ci uniquement) ont le droit d'envoyer des mails dont la source - prétendue est /...@crans.org/. - - Utiliser /~all/ permet d'indiquer que si un mail provient d'une autre IP, il ne - faut pas rejeter le mail, mais le mettre en /permerror/. - -- April: ~v=spf1 include:spf.mailjet.com mx ip4:62.73.5.35 include:spf.protection.outlook.com include:_spf.april.com ip4:37.71.69.68 ip4:37.71.69.69 ip4:37.71.69.70 include:_spf.salesforce.com -all~ - - Idem, avec des champs ~include:...~ en plus. Ces derniers permettent d'inclure - un autre enregistrement SPF (/e.g./ celui de ~spf.mailjet.com~). - - Utiliser ~-all~ permet de demander aux serveurs récepteurs de rejeter tout mail - ne satisfaisant pas ce test. - -D'autres mécanismes et formats existent, mais nous ne les présentons pas -ici. Se référer à la RFC ou la page Wikipédia pour leur description. - - -** Vérification (côté serveur récepteur) - -Lorsque ~redisdead~ (~MX~ du Cr@ns) reçoit un mail, nous demandons à un service -externe de vérifier le SPF (via la variable ~smtpd_recipient_restrictions~). Le -service externe tourne sur la même VM et est ~postfix-policyd-spf-python~. - - - -* TODO SRS - -- [[https://www.libsrs2.org/srs/srs.pdf][Papier]], -- [[https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme][Page Wikipédia]]. - -/Note/ : Les adresses générées par ~postsrsd~ sont valides pendant 21 jours. - - -* DKIM - -- [[https://www.rfc-editor.org/rfc/rfc6376.html][RFC]]. -- [[https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail][Page Wikipedia]]. - -DKIM (/Domain Key Identified Mail/) permet au serveur émetteur de signer les -mails, et au serveur récepteur de vérifier cette signature, en utilisant des -méthodes de cryptologie asymétrique. - -** Implémentation (côté émetteur) - -*** Serveur Mail - -Le serveur émetteur possède la clef privée. Il ajoute à tout mail sortant un -champ à l'en-tête de la forme suivante : -#+begin_src mail - DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=crans.org; s=mail; - t=1702660809; bh=NqcDLO2gkZU0IxcV+mE7uZ2NRnN/yfceH73Q1nhaFg4=; - h=From:To:Subject:Date:From; - b=ZjomU0jkljKVwA6sUhUioCemnxh/OhSGgwwr57irEn39Gfbv8/cLF8jmHc3hmv4ly - fLvJdj7iVTkeGlTVeW72H93wEA0qrB6LHHz81YBeHPb8eg63zm+9soDSOaP91Gux8J - UgeY1PWXvfjdfe+MJX9JqnlBKqd4JRgpD8AXaO852Lrq+fLJy4ewLOc/3dAqpNMrTf - swi5y6vV5QH89cuFjpjWqF3UcuD4a20RCQIpU/j5K1sxr1CTbdKjgqlsq5mt9/JSKx - OcvZ5WTmgPwdimKKz0DfjAeXQBMac9d7V9Kb5LvCZx84kSbLQEKboGxpRRhNWGdBsK - f3YZXjmpe8cl8cpbvuvdKYWOE7E6fRGu/CwQEyEQYqmrmljiklSYPaG8IKs5uYWKrA - A2D4VTisIYOwGvdljFTQP5zfhPsi4OnNbiN3RVX475lCHNWbnFMh8OCF/ugLj30dyk - s8MLAzDyYlgaccOD0uZ6VsdGJ0LK8+TCKbsc5H1ynjg0VejmRyVzZJ5TzAjXrzS6CC - Lj9eQQex1IaO6d7uGe4P/ULghjSP90tgBcZVNFLlU3r59ylkVQyAu7THDr4CDaxFO0 - 63QE7/GNDE2vZv0K5gp5Yz2veVC3wyaP1dJzIoAzZc1kZRoWz6QK9cH1Bfmnlx9nUs - j+G+VLDQbxi2NuoYAD/I2naA= -#+end_src - -Le bloc contient une liste de clefs-valeurs : -- ~v~ indique la version du protocole, -- ~d~ le domaine attestant de la validité du mail, -- ~s~ le nom du sélecteur (/Cf/. plus bas), -- ~b~ et ~bh~ contiennent les signatures. - -/Notes/ : -- Il est possible que le mail ne soit pas signé par le domaine correspondant à - l'adresse d'envoi, puisqu'il est possible d'autoriser autrui à envoyer un - mail à notre place (/Cf/. SPF plus haut). -- Se référer à la page Wikipédia, ou à la RFC pour une liste exhaustive des - clefs. - -*** Serveur DNS - -Il faut placer dans le serveur DNS un champ TXT dont la clef est -~sélecteur._domainkey.domain~, où ~domain~ (resp. ~sélecteur~) est la valeur de la -clef ~d~ (resp. ~s~) définie plus haut. - -Par exemple, pour le champ fourni plus haut, nous pouvons lire : -#+begin_src mail -"v=DKIM1; k=rsa; " "p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtwkNVd9Mmz8S4WcfuPk0X2drG39gS8" "+uxAv8igRILgzWeN8j2hjeZesl8pm/1UTVU87bYcdfUgXiGfQy9nR5p/Vmt2kS7sXk9nsJ/VYENg" "b3IJQ6paWupSTFMyeKycJ4ZHCEZB/bVvifoG6vLKqW5jpsfCiOcfdcgXATn0UPuVx9t93yRrhoEM" "ntMv9TSodjqd3FKCtJUoh5cNQHo0T6dWKtxoIgNi/mvZ92D/IACwu/XOU+Rq9fnoEI8GukBQUR5A" "kP0B/JrvwWXWX/3EjY8X37ljEX0XUdq/ShzTl5iK+CM83stgkFUQh/rpww5mnxYEW3X4uirJ7VJH" "mY4KPoIU+2DPjLQj9Hz63CMWY3Ks2pXWzxD3V+GI1aJTMFOv2LeHnI3ScqFaKj9FR4ZKMb0OW2BE" "FBIY3J3aeo/paRwdbVCMM7twDtZY9uInR/NhVa1v9hlOxwp4/2pGSKQYoN2CkAZ1Alzwf8M3EONL" "KeiC43JLYwKH1uBB1oikSVhMnLjG0219XvfG/tphyoOqJR/bCc2rdv5pLwKUl4wVuygfpvOw12bc" "vnTfYuk/BXzVHg9t4H8k/DJR6GAoeNAapXIS8AfAScF8QdKfplhKLJyQGJ6lQ75YD9IwRAN0oV+8" "NTjl46lI/C+b7mpfXCew+p6YPwfNvV2shiR0Ez8ZGUQIcCAwEAAQ==" -#+end_src - - -** Vérification (côté récepteur) - -Côté réception (~redisdead~ pour nous), nous utilisons le milter (filtre pour -mail) fourni par ~opendkim~. Ce milter écoute en local et est appelé par ~postfix~. -Lors de la réception d'un mail, postfix demande à ~opendkim~ quelle décision -prendre. Ce dernier va regarder les en-têtes du mail. S(il trouve une signature -DKIM, il va effectuer la requête DNS décrite plus haut, et vérifier la signature -du mail (valeurs des clefs ~b~ et ~bh~). - - - -* TODO DMARC - -- [[https://www.rfc-editor.org/rfc/rfc7489][RFC]], -- [[https://en.wikipedia.org/wiki/DMARC][Page Wikipédia]]. - - -* TODO ARC - -- [[https://www.rfc-editor.org/rfc/rfc8617.html][RFC]], -- [[https://en.wikipedia.org/wiki/Authenticated_Received_Chain][Page Wikipedia]]. - - -* MTA-STS - -- [[https://datatracker.ietf.org/doc/html/rfc8461][RFC]], -- [[https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#SMTP_MTA_Strict_Transport_Security][Section de page Wikipédia]]. - -Le MTA-STS consiste à publier les protocoles de sécurité supportés par les -serveur mail d'un certain domaine (pour nous, les mails en /...@crans.org/). - -Contrairement au ~DANE~ (décrit plus bas), ce protocole ne demande pas la mise en -place de DNSSEC. En revanche, il demande d'avoir un serveur Web accessible en -~https~ (pour nous, ~https://crans.org~ doit être servi par un serveur Web). - -** Implémentation (côté infrastructure émettrice) - -*** Dans la zone DNS - -Il faut ajouter un champ TXT accessible à ~_mts-sts.domain.tld~. - -Quelques exemples: -- Gmail: ~v=STSv1; id=20190429T010101;~, -- Microsoft: ~v=STSv1; id=20190225000000Z;~, -- Outlook: ~v=STSv1; id=20190225000000Z;~. - -*** Sur le serveur Web - -Il faut que le serveur Web associé serve un fichier texte accessible à l'adresse -~https://mta-sts.domain.tld/.well-known/mta-sts.txt~ - -Quelques exemples : -+ [[https://mta-sts.gmail.com/.well-known/mta-sts.txt][Gmail]] -+ [[https://mta-sts.outlook.com/.well-known/mta-sts.txt][Outlook]], -+ [[https://mta-sts.microsoft.com/.well-known/mta-sts.txt][Microsoft]]. - -Le fichier texte contient une liste de clefs-valeurs. Ces clefs décrivent quel -protocole - - -** Vérification côté récepteur. - -~postfix-mta-sts-resolver~ peut être utilisé ? N'ayant pas implémenté cette -solution pour le moment (ni au Cr@ns, ni personnellement), nous ne pouvons pas -commenter sur le sujet. - - - -* DANE - -- [[https://www.rfc-editor.org/rfc/rfc6698][RFC]], -- [[https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities][Page Wikipédia]]. - -Actuellement, pour vérifier un certificat ~C~ proposé par un serveur mail, il faut -faire confiance à un certificat racine, lequel est utilisé pour signer un autre -certificat (dit /certificat intermédiaire/), lequel est utilisé pour signer le -certificat ~C~. Pour vérifier ~C~, il faut (1) faire confiance au certificat racine -et (2) vérifier les deux signatures sus-mentionnées. - -DANE est une norme permettant aux propriétaires de domaines de déclarer quels -cetificats doivent être acceptés pour quels services. - -/Note/ : Cela n'est pas spécifique aux mails. - -** Implémentation (côté infrastructure émettrice) - -Pour mettre en place DANE, il suffit d'ajouter un champ DNS à sa zone : - -- Il faut que la zone soit signée DNSSEC. - -- Le champ à ajouter est : - + de type TLSA (TLS Authentiction?), - + de clef ~_port._protoL4.domain.tld~. - + de valeur ~x y z t~, où : - * ~x~ est appelé /certificatie usage/, - * ~y~ est appelé /selector/, - * ~z~ est appelé /matching type/, - * ~t~ est appelé /certificate associated data/. - -*** Format du champ TLSA. - -**** /Certificate usage/ - -L'objectif de ce champ est d'indiquer comment vérifier le certificat. - -| *Valeur* | *Signification* | -|--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 0 | Le certificat doit être valide (root -> intermediate -> "cert"), et /associated data/ décrit l'un des certificats parents de "cert" | -| 1 | /associated data/ décrit "cert", et le certificat doit aussi être valide /wrt/. un certificat racine de confiance. | -| 2 | /associated data/ décrit un parent de "cert". Ce parent est supposé de confiance, et "cert" doit bien être son descendant. | -| 3 | /associated data/ décrit "cert". Le certificat n'a pas besoin d'être valide /wrt/. un certificat racine. Il a simplement besoin de correspondre à /associated data/. | - -**** /Selector/ - -Ce champ décrit ce qui est décrit par /associated data/. - -| *Valeur* | *Signification* | -|--------+-----------------------------| -| 0 | Tout le certificat. | -| 1 | Seulement la clef publique. | - -**** /Matching type/ - -Ce champ indique comment vérifier /associated data/ contre la donnée du certificat -(ou de la clef publique). - -| *Valeur* | *Signification* | -|--------+--------------------------------------------------------| -| 0 | /associated data/ doit être égal à la donnée. | -| 1 | /associated data/ doit être égal au sha256 de la donnée. | -| 2 | /associated data/ doit être égal au sha512 de la donnée. | -où "la donnée" est décrite par le /selector/ et le choix de certificat décrit par -le /certificate usage/. - -**** /Certificate associated data/ - -Chaîne de caractère au format hexadécimal. - - -*** Recommandation pour le Cr@ns - -À titre personnel, j'utilise des champs TLSA en ~3 0 1~. Je pense que le Cr@ns -peut faire la même chose (ou du ~3 0 2~). - -*** Mise en place - -Hypothèses : -- le serveur DNS accepte des mises à jour DNS dynamiques de la part du serveur - mail, -- le renouvellement du certificat utilise ~certbot~. - - -Mise en place : -- Dans la confguration ~certbot~, - + passer en challenge DNS-01 et : - * ~manual_auth_hook~ : un script mettant en place le challenge, - * ~renew_hook~ : script de déploiement du certificat, lequel *ajoute* un champ - TLSA et place le certificat à déployer dans un dossier "staging", - * ~manual_cleanup_hook~ : un script retirant le challenge ~acme~. -- Roll-over scheme : Un champ DNS a une durée de vie (TTL), généralement 1h. De - ce fait, les requêtes de chalmp TLSA peuvent être en retard d'une heure (au - plus). Il est done conseillé d'avoir le nouveau champ TLSA en place pendant - deux TTL avant de (1) mettre en place le nouveau certificat et (2) retirer le - vieux champ TLSA. - - Je propose de mettre en place un timer systemd qui serait activé "après - l'arrêt de certbot pour plus de 2 TTLs". Ce timer lancerait un service, lequel - aurait une condition d'activation "un certificat existe dans le dossier - staging". - - -*** Exemple - -#+begin_src dig - dig +short TLSA _25._tcp.nanein.fr - => 3 0 1 50E9221F066DCD1991ED9D3BA0AD10159F3585780F6FABBAE2942E43 37789FC8 -#+end_src - -** Implémentation (côté serveur mail destinataire) - -Côté serveur mail destinataire, la configuration est très simple (car nous -utilisons Postfix). Cela se fait principalement via les options suivantes : -- ~smtp_dns_supoprt_level~ (valeur ~dnssec~) -- ~smtp_tls_dane_insecure_mx_policy~ (valeur ~dane~) - -D'autres options de Postfix peuvent être utilisées pour permettre un contrôle -plus fin sur le comportement du service.