85.1.4. pepsi-stage-arc¶
ARC-verify, sign and seal in the Pepsi pipeline
- Section du manuel:
1
85.1.4.1.1. Nom¶
pepsi-stage-arc - l’étape de vérification et de scellement ARC du pipeline Pepsi.
85.1.4.1.2. Synopsis¶
pepsi-stage-arc [GLOBAL-OPTIONS] worker
85.1.4.1.3. Description¶
pepsi-stage-arc est un programme d’étape exécuté par pepsi-dispatch(1) comme un worker persistant lisant les identifiants de message sur l’entrée standard. Il implémente ARC (RFC 8617) : il vérifie toute chaîne ARC entrante existante, note le verdict résultant dans le state.auth.arc de la ligne, et — lorsqu’une identité de signature ARC est configurée — scelle le message en tant que notre ADMD en ajoutant en tête un nouvel ensemble ARC : ARC-Authentication-Results (AAR), ARC-Message-Signature (AMS) et ARC-Seal (AS). Le scellement ne fait qu”ajouter en tête des lignes d’en-tête, de sorte que les signatures existantes plus bas dans le message ne sont pas perturbées. La ligne avance ensuite vers son NEXT_STAGE. Le state de la ligne — y compris d’éventuels paramètres state.dsn RFC 3461 — est laissé intact pour que les étapes ultérieures l’honorent.
La signature ARC est une étape et non une partie de pepsi-ingress(1) : ainsi l’ingress ne détient pas les clés de signature ARC. L’ingress vérifie SPF, DKIM et DMARC, écrit l’en-tête Authentication-Results autonome, et note le texte de résultat rendu sous state.origin.ar_results ; cette étape n’ajoute que l’ensemble ARC. L’AAR (qui, selon la RFC 8617, devrait refléter l’évaluation complète du récepteur) est construit en réinjectant directement ce fragment stocké — de sorte que SPF/DKIM/DMARC ne sont pas re-vérifiés ici, et le travail intensif en DNS est effectué exactement une fois. Seule la chaîne ARC entrante — que l’ingress n’évalue pas — est vérifiée par cette étape, pour calculer la valeur de validation de chaîne (cv=) et ajouter sa propre ligne arc= à l’AAR.
85.1.4.1.4. Qui a scellé la chaîne : state.auth.arc_sealers¶
Outre le verdict, l’étape note le d= de chaque ARC-Seal que le message portait à son arrivée, sous forme de tableau JSON sous state.auth.arc_sealers — en minuscules, débarrassé d’un éventuel point racine final, dédupliqué et ordonné par instance de sorte que l’ADMD le plus proche de l’auteur vienne en premier. Notre propre ARC_DOMAIN n’y figure jamais : la liste est lue dans le message avant que le propre ensemble de cette étape ne soit rendu, de sorte qu’un sceau que nous avons ajouté ne peut satisfaire une règle portant sur des intermédiaires.
Ceci existe parce que state.auth.arc ne peut pas répondre à la question que se pose réellement un destinataire. La RFC 8617 §8.4 est explicite : une chaîne valide ne confère aucune fiabilité — elle établit seulement que les ADMD qui y sont nommés ont manipulé le message, et laisse délibérément à la politique locale la question de savoir si ces ADMD sont honnêtes. Un destinataire qui veut excuser le SPF ou le DKIM cassé d’un saut de redirection doit donc nommer les sauts qu’il accepte, et il lui faut un endroit d’où lire ces sauts. C’est cette clé ; les lignes sealer_domain de pepsi-stage-check-whitelist(1) sont la politique écrite à partir d’elle.
Le tableau est écrit que la chaîne se soit validée ou non — un d= non validé est une revendication, et la trace de ce qui a été revendiqué est ce avec quoi un opérateur diagnostique un message rejeté. Tout ce qui le consomme doit donc exiger d’abord state.auth.arc = pass ; check-whitelist le fait, écartant toute la liste sinon, de sorte qu’une chaîne frappée par n’importe qui ne peut nommer un scelleur digne de confiance.
85.1.4.1.5. Validation de la chaîne et cv=¶
La RFC 8617 §5.2 définit trois résultats de validation de chaîne, et la balise cv= de l”ARC-Seal que cette étape ajoute indique lequel s’applique au message tel qu’il est arrivé :
cv=noneAucune chaîne ARC n’était présente — cet ADMD est le premier à sceller ce message.
cv=passUne chaîne était présente et chaque ensemble s’est validé.
cv=failUne chaîne était présente et ne s’est pas validée.
cv=none est une assertion sur la provenance plutôt qu’une absence : elle indique au récepteur suivant que rien en amont ne s’était déjà porté garant de ce message. L’émettre par-dessus une chaîne présente mais cassée blanchirait cette chaîne — le validateur en aval verrait un ensemble i=1 apparemment immaculé et aucune trace d’une quelconque altération.
Pepsi scelle donc cv=fail pour toute chaîne entrante qui ne se valide pas, y compris dans les cas où la chaîne ne peut pas être lue du tout : un en-tête ARC-Seal/ARC-Message-Signature/ARC-Authentication-Results qui ne s’analyse pas, une chaîne plus longue que les 50 ensembles que la RFC 8617 autorise, et une chaîne comportant des nombres inégaux des trois types d’en-tête. Le nouvel ensemble poursuit la numérotation d’instance de la chaîne au lieu de la redémarrer à i=1.
La seule exception est une chaîne dont l”ARC-Seal le plus récent indique déjà cv=fail. Selon la RFC 8617 §5.1.1, une chaîne en échec ne peut pas être réparée et ce sceau est le dernier ; cette étape n’ajoute donc aucun ensemble et le message est redirigé avec la chaîne en l’état.
Une chaîne qui n’a pu être validée qu’en raison de l’échec d’une recherche de clé (un temperror DNS) n’est pas scellée immédiatement : ce cv=fail serait faux au sujet d’une chaîne peut-être saine, et un sceau ne peut être repris. Le message est mis en pause cinq minutes puis réessayé, jusqu’à trois fois (environ un quart d’heure, compté dans state.arc_temperrors) ; si les recherches échouent toujours, il est alors scellé cv=fail comme toute autre chaîne qui ne se valide pas.
Le contexte de session dont le sceau a besoin — l”authserv-id, le fragment Authentication-Results rendu, l’IP du client connecté et le nom HELO/EHLO annoncé — est lu depuis les métadonnées d’origine SMTP que l’ingress a notées sous le state.origin de la ligne ; l’expéditeur d’enveloppe provient de la colonne mail_from. C’est ainsi que l’information est passée de l’ingress à cette étape.
La clé de signature ARC est la clé DKIM du domaine [pepsi] ARC_DOMAIN sous KEY_DIR (provisionnée par pepsi-setup(1)), signée avec l’algorithme unique nommé par [pepsi] ARC_ALGORITHM (ARC permet une signature par saut).
ARC ne s’applique qu’au courrier que nous recevons et redirigeons : il préserve l’authentification d’un ADMD en amont à travers notre saut. Il ne doit donc jamais toucher le courrier que nous émettons — nos propres soumissions authentifiées (state.local_origin), qui sont authentifiées comme domaine auteur par pepsi-stage-dkim-sign(1) à la place. Sceller un tel message ne ferait que publier les propres verdicts SPF/DKIM/DMARC de la soumission (typiquement un SPF fail pour un client itinérant non listé dans notre enregistrement SPF) à l’intérieur de l’ensemble ARC. L’étape ignore donc tout message state.local_origin qui lui est remis, en l’avançant non scellé ; cela rend l’étape sûre où qu’elle soit placée. Sur un hôte qui à la fois reçoit et soumet, placez-la sur la branche entrante uniquement, après la scission state.local_origin — de sorte qu’elle ne voie que le courrier reçu, avant la réécriture d’enveloppe SRS et toute autre transformation. Sur un hôte en réception seule, elle est naturellement l’étape initiale ([stage-init]).
Le scellement est fail-open : si le contexte d’origine est manquant, si la configuration [pepsi] ou les clés ARC sont indisponibles, si le résolveur ne peut être mis en place, ou si le scellement échoue, le message est avancé non scellé avec un avertissement plutôt que d’être retenu (le verdict ARC est tout de même enregistré chaque fois qu’il a pu être calculé). La section propre de l’étape fait exception : elle est vérifiée au démarrage du worker, et une section qui ne s’analyse pas fait refuser au worker de démarrer (sortie 78), de sorte que le dispatcher retient la file jusqu’à sa correction au lieu de laisser passer chaque message non scellé.
85.1.4.1.6. Configuration¶
L’étape est câblée et configurée via sa propre section [stage-<name>] (PROGRAM = pepsi-stage-arc, un NEXT_STAGE obligatoire). Ses options — les paramètres DNS (DNS_SERVERS, DNS_TIMEOUT) et les paramètres de signature de l’ensemble ARC (HEADER_CANONICALIZATION, BODY_CANONICALIZATION, SIGNATURE_EXPIRATION_DAYS, SIGNED_HEADERS) — ainsi que l’identité de signature partagée [pepsi] (ARC_DOMAIN, ARC_ALGORITHM, KEY_DIR, DKIM_SELECTOR) sont documentées dans pepsi.conf(5).
85.1.4.1.7. État¶
Entrées : state.local_origin — lorsqu’il est vrai, le message est l’une de nos propres soumissions et est avancé sans être touché (pas d’ARC). Sinon state.origin — les métadonnées d’origine SMTP que l’ingress a enregistrées. L”authserv_id est requis pour reproduire l’identité de l’AAR (sans lui, l’étape avance non scellée, fail-open) ; ar_results porte le fragment Authentication-Results rendu par l’ingress, réutilisé tel quel dans l’AAR de sorte que SPF/DKIM/DMARC n’aient pas à être re-vérifiés ; remote_ip et helo affinent le contexte de vérification ARC.
Sorties : l’étape écrase state.auth.arc avec le verdict de chaîne réévalué (remplaçant les amorces none que l’ingress y sème), écrit state.auth.arc_sealers (voir ci-dessus) et ajoute en tête l’ensemble ARC à la colonne headers ; le reste de state — y compris les autres verdicts state.auth et state.dsn — est préservé inchangé. Pendant qu’elle attend la fin d’un temperror DNS, elle compte les tentatives dans state.arc_temperrors. La disposition de l’état est décrite dans pepsi.state(7).
Transitions : avance vers NEXT_STAGE — après avoir ajouté en tête l’ensemble ARC, après avoir simplement noté le verdict dans state.auth.arc lorsqu’aucune identité de signature n’est configurée, ou immédiatement (sans y toucher) pour un message state.local_origin, qui n’est jamais traité par ARC. La seule autre issue est une pause de cinq minutes, au plus trois fois, pour une chaîne entrante dont la validation a rencontré un temperror DNS (voir ci-dessus). Il n’y a pas de branche ; l’étape n’échoue jamais, ne réachemine ni ne termine jamais un message.
85.1.4.1.8. Commandes¶
Exécuté comme worker, le programme vérifie et scelle chaque message et le fait avancer.
85.1.4.1.9. Options globales¶
- -c FILE, –config FILE
Lit la configuration depuis FILE au lieu du chemin de recherche par défaut.
- -L LOGLEVEL, –log LOGLEVEL
Règle la verbosité de journalisation (
error,warn,info,debug,trace; par défautinfo).- -h, –help
Affiche un résumé d’utilisation et quitte.
- -V, –version
Affiche la version et quitte.
85.1.4.1.10. Code de sortie¶
Le résultat de chaque message est rapporté à pepsi-dispatch(1) sur la ligne de statut du worker, et non par le code de sortie.
- 0
Le worker s’est exécuté jusqu’à la fermeture de son entrée standard.
- 1
Une erreur fatale s’est produite (configuration illisible, base de données impossible à ouvrir, ou échec de l’entrée/sortie standard). La raison est écrite dans le journal.
- 78
Le worker a refusé de démarrer : sa section ne s’analyse pas. Le dispatcher remet en file ce qu’il lui avait confié et réessaie l’étape plus tard.
85.1.4.1.11. Voir aussi¶
pepsi-config(1), pepsi-ingress(1), pepsi-stage-srs(1), pepsi-stage-dkim-sign(1), pepsi-dispatch(1), pepsi.conf(5), pepsi.state(7), pepsi-setup(1)
85.1.4.1.12. Bogues¶
Signalez les bogues au gestionnaire de tickets de Pepsi.