DomainKeys, DKIM
Principe de l'authentification des messages
Nous avons tous reçu des spams provenant en apparence de personnes que nous connaissons, soit directement, soit indirectement. Il faut savoir que rien, dans le protocole SMTP, ne permet spontanément d'authentifier l'émetteur d'un message. Rien n'est donc plus facile que d'envoyer un message électronique semblant émaner de untel AT domaine.tld.
Bien sûr, les spammeurs exploitent au maximum cette possibilité. Non seulement nous recevons des messages semblant provenir d'adresses "que nous connaissons" (ou pas), mais parfois nous recevons des notices de non-acheminement ou de rejet de messages que nous n'avons pas expédiés. Dans le premier cas, un spammeur se fait passer pour xyz AT domaine.tld pour vous écrire. Dans le second, il émet des messages portant votre adresse électronique en tant qu'émetteur.
Le principe de DomainKeys (DK) et de son évolution DomainKeys Identified Mail (DKIM) est de produire (à l'émission) ou de vérifier (à la réception) une signature cryptographique attachée à un message électronique. D'une manière similaire à Sender Policy Framework (SPF), DK/DKIM vise à authentifier un message électronique, non pas tant par rapport à l'auteur réel du message mais par rapport au domaine auquel l'émetteur se rattache. Ces outils permettent d'être certain qu'un message semblant provenir d'un certain domaine a bel et bien été émis par un serveur de messagerie de ce domaine, ou par un serveur dûment autorisé à émettre un tel message. Nous avons fait une présentation de SPF/DK.
DKIM met en place une authentification de bout en bout des messages électroniques, indépendante du chemin suivi par le message (relayage, réémissions, etc.).
Utilisation de DK/DKIM
DK/DKIM peut être utilisé selon deux modes indépendants :
- vérification des signatures des messages reçus par un serveur de messagerie, et
- signature de tous les messages émis par un serveur de messagerie.
Il est donc possible de vérifier l'authenticité des messages que l'on reçoit (vérification des signatures) sans pour autant signer ceux que l'on émet (même si la logique et la complétude voudraient que l'on fasse les deux opérations).
Utilisation du DNS pour la diffusion des clés
Les serveurs de messagerie devant vérifier les signatures DK/DKIM doivent pouvoir trouver les clés publiques de signature (dont la clé privée est connue des seuls serveurs d'émission du domaine concerné). La méthode préférée de diffusion de ces clés est, aujourd'hui, le DNS. Cela n'exclut pas d'autres méthodes à l'avenir.
Un domaine décidant de signer les messages qu'il émet à l'aide de DK/DKIM doit ajouter des informations dans sa zone DNS, sous la forme d'un ou plusieurs enregistrements de type TXT. Il est important de comprendre comment les messages sont signés, et donc ce que le serveur de réception va chercher dans le DNS.
La signature DKIM est ajoutée au message, dans un en-tête spécifique :
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=gamma;
h=domainkey-signature:received:received:message-id:date:from:to
:subject:mime-version:content-type:content-transfer-encoding
:content-disposition;
bh=60eiBOZBcZ9GHQqczvh+/sKgg7vU3F2W0i4exrSEIxk=;
b=M0fV6KNncg6fZjZPZxej7wnRwgcmyACn7nPLcLi+Cujo+J+G67mx5at9WrO1Fw/ZqO
1mNFpVCrsNtVPAdnt1ZZtxfAl8ZXyzPTcEmBh/S4EBLe5s+jkePrj2uYnvFMNDEyATrb
g4fGHf0bqdPkBqZTCDONHBOXiIX52xay2Lje4=
Nous détaillons plus loin la signification des différents champs de cet en-tête. Dans l'exemple ci-dessus, et par rapport à la distribution des clés, deux champs (en gras) sont importants :
- le champ d, qui permet de déterminer le domaine à interroger, et
- le champ s, qui indique le sélecteur utilisé pour la signature.
Le serveur de réception du message doit chercher l'enregistrement TXT nommé selecteur._domainkey.domaine. Pour l'exemple ci-dessus, ce sera gamma._domainkey.gmail.com :
$ dig +short gamma._domainkey.gmail.com txt
"k=rsa\; t=y\; p=MIGfMA0GCSqGSIb3 [...] YA+OwSMWQIDAQAB"
Nous avons abrégé le champ p pour améliorer la mise en page.
Diffusion des clés publiques
Le sélecteur est simplement l'identifiant d'une bi-clé. La clé privée est gardée soigneusement par les serveurs d'émission du domaine. La clé publique est diffusée dans le DNS et associée à une ressource portant le nom du sélecteur.
La clé publique associée à un sélecteur doit être placée dans un enregistrement TXT du domaine signataire, dans le sous-domaine nommé _domainkey. Comme nous l'avons indiqué ci-dessus, l'enregistrement doit être nommé sélecteur._domainkey.domaine-signataire. Il n'y a aucune restriction sur le nombre de sélecteurs que l'on peut utiliser, au-delà de la règle un sélecteur = un enregistrement TXT. Par exemple, Google utilise au moins deux sélecteurs différents (béta et gamma) :
$ dig +short alpha._domainkey.gmail.com txt
$ dig +short beta._domainkey.gmail.com txt
"t=y\; k=rsa\; p=MIGfMA0G [...] 8uQIDAQAB"
$ dig +short gamma._domainkey.gmail.com txt
"k=rsa\; t=y\; p=MIGfMA0G [...] MWQIDAQAB"
$ dig +short delta._domainkey.gmail.com txt
Sur l'un de nos domaine, nous n'en n'utilisons qu'un seul :
$ dig +short testdk._domainkey.ba-cst.net txt
"v=DKIM1\; t=y\; g=*\; k=rsa\; p=MIGfMA [...] bkQIDAQAB"
Les différents champs utilisables, et leur signification, sont (par ordre alphabétique) :
- g : la granularité de la clé. Définit l'applicabilité de la clé par rapport au nom local de l'émetteur (partie avant le caractère @ de l'adresse électronique de l'émetteur).
- h : les algorithmes de hachage utilisables, séparés par un caractère : (sha1:sha256:md5:mon-algorithme). Actuellement, seuls sha1 et sha256 sont reconnus et utilisables. Par défaut (absence de ce champ), tous les algorithmes de hachage reconnus sont inclus.
- k : le type de la clé. Actuellement, seul rsa est utilisable.
- n : un commentaire libre. Du fait des restrictions liées à la taille d'un enregistrement DNS sur UDP, ce champ (s'il est utilisé) doit être particulièrement concis. Il n'est pas destiné aux utilisateurs mais aux administrateurs de messagerie.
- p : la clé publique associée au sélecteur, codée en Base64. Ce champ est obligatoire, pour une raison évidente.
- s : le type de service associé à ce sélecteur. Une liste de mots-clés séparés par le caractère :. Actuellement, seuls les mots-clés email et * (tous les services) sont définis.
- t : un ensemble d'indicateurs d'état, séparés par le caractère : (deux points), pour l'utilisation de DKIM par le signataire. L'indicateur y signifie que DKIM est en test par le signataire. L'indicateur s signifie que le domaine du signataire et le domaine de l'émetteur doivent être strictement identique (pas de sous-domaines).
- v : la version de DKIM utilisée. Champ optionnel. S'il est présent, il doit être le premier dans la liste des champs, et il doit valoir DKIM1.
Granularité d'une clé (g=XXX)
La granularité d'une clé de signature permet de définir qui peut utiliser cette clé pour signer ses messages. Par défaut, la granularité est nulle : n'importe quelle adresse d'émetteur du domaine concerné peut voir ses messages signés avec la clé en question. Mais il est possible de restreindre l'utilisation de la clé à certains utilisateurs seulement.
Imaginons par exemple qu'une société a mis en place un service de support pour ses clients. Tous les collaborateur de ce service ont des adresses électroniques de la forme support-prenom AT societe.fr. La société peut alors créer une clé DKIM spécifique au service support (avec un sélecteur particulier, par exemple support) et en plus indiquer que cette clé ne s'applique qu'aux adresses électroniques de la forme support-xxxx AT societe.fr. Cela se fera simplement :
$ dig +short support._domainkey.societe.fr txt
"v=DKIM1\; t=y\; g=support-*\; k=rsa\; p=a[...]k"
A la réception, la signature ne pourra être validée qu'à la condition que l'adresse d'émetteur du message soit de la forme support-* AT societe.fr. Ce contrôle est réalisé sur le champ i de la signature DKIM insérée dans le message.
Type de service (s=xxx)
Ce champ est une anticipation d'une éventuelle extension de DKIM pour signer d'autres éléments que des messages électroniques. Il n'est pas utile actuellement. Toutefois, s'il est utilisé, le destinataire doit s'assurer que l'élément pour lequel il vérifie la signature correspond bien au service indiqué par le champ s.
DKIM n'étant aujourd'hui utilisé que pour signer des messages électroniques, les valeurs s=* ou s=email sont théoriquement équivalentes. Pour éviter les écueils toujours possibles avec certaines mises en oeuvre, nous vous conseillons de ne pas utiliser ce champ.
Politique de signature du domaine d'émission
Dans la logique du principe de signature des messages, un message
- qui porte une signature invalide ou
- qui ne porte pas de signature, si le domaine d'émission signe tous ses messages.
devrait subir une pénalité. C'est le cas pour le premier point (selon les outils de vérification des signatures), mais pas pour le second. En effet, le serveur de destination ne sait pas, a priori, que le domaine associé à l'adresse de l'émetteur signe tous les messages qu'il émet. Un message non signé est donc accepté sans autre forme de procès, même si le domaine de l'émetteur signe tous les messages qu'il émet.
A l'évidence, il n'y a pas d'intérêt de mettre en place la signature à l'émission de tous vos messages si un message semblant venir de votre domaine, mais ne portant aucune signature DK/DKIM, est accepté par ses destinataires. Un serveur de messagerie doit donc, sur réception d'un message, pouvoir apprendre si le domaine d'émission est sensé signé tous ses messages ou non, et agir en conséquence.
La RFC 4870 (rendue obsolète par la RFC 4871) définissait, dans sa section 3.6 intitulée "Policy Statement of Sending Domain", la méthode suivant laquelle un domaine peut informer tous les serveurs de messagerie sur Internet de sa politique quant à la signature DK/DKIM des messages. Cette section a été retirée de la RFC 4871, une proposition de protocole étant tout récemment sortie de l'IETF (RFC 5016). Cette proposition a donné lieu à une suggestion quant au protocole de diffusion de la politique de signature DKIM d'un domaine.
Diffusion de la politique de signature, RFC 4870 [en voie d'obsolescence]
Selon la RFC 4870, il suffisait de définir un enregistrement TXT associé au sous-domaine _domainkey du domaine d'émission (par exemple, _domainkey.ba-cst.net) :
$ dig +short _domainkey.ba-cst.net txt
"t=y\; o=-"
Cet enregistrement servait à indiquer la politique de signature du dit domaine. Les valeurs de champs utilisables étaient (par ordre alphabétique) :
- n : un commentaire libre.
- o : ce champ vaut par défaut ~, ce qui signifie que certains messages peuvent être signés par DK/DKIM et pas d'autres, et donc que la présence d'un en-tête DKIM-Signature est optionnelle. La valeur - (le caractère moins) signifie que tous les messages émis par ce domaine sont signés par DK/DKIM, et donc que l'absence d'un en-tête DK/DKIM est une justification suffisante pour rejeter le message ou lui appliquer une lourde pénalité.
- r : une adresse électronique vers laquelle seront dirigés des messages concernant la non-validation de signatures produites par le domaine en question.
- t : des indicateurs d'état sur l'utilisation de DKIM par le domaine. La valeur y signifie que DKIM est en test.
Pour l'exemple précédent, la ressource signifie
- que la signature DK/DKIM est en test pour le domaine ba-cst.net (t=y), et que
- tous les messages émis par les serveurs de messagerie de ce domaine doivent être signés (o=-).
Diffusion de la politique de signature, draft RFC 5016
[A COMPLETER]
Vérification en réception
La vérification en réception est l'opération la plus facile, pour peu que l'on dispose des outils appropriés. Il n'y a en effet rien à faire au-delà de l'installation des outils adéquats et d'une configuration somme toute très réduite. Le MX de réception (tous les MX associés à un domaine, si vous en avez plusieurs) doit simplement contrôler la signature DK/DKIM des messages reçus, lorsque cette signature est présente. Il doit aussi (pour suivre la RFC 4870, tant qu'aucune autre RFC ne redéfinit le protocole de diffusion de la politique de signature des messages d'un domaine) vérifier si un message non signé est normal par rapport à la politique de signature du domaine émetteur.
Par exemple, pour activer ce contrôle avec SpamAssassin, il suffit de modifier l'un des fichiers de configuration (ici /etc/spamassassin/v312.pre) :
$ cat /etc/spamassassin/v312.pre
# DKIM - perform DKIM verification
#
# Mail::DKIM module required for use, see INSTALL for more information.
#
# Note that if C version 0.20 or later is installed, this
# renders the DomainKeys plugin redundant.
#
loadplugin Mail::SpamAssassin::Plugin::DKIM
dkim_timeout 5
Ce greffon utilise le module perl Mail::DKIM, qui doit être installé avant d'activer la configuration précédente. Si Mail::DKIM (ou l'une de ses dépendances) n'est pas installé,spamassassin démarrera mais, de manière très logique, les contrôles DK/DKIM ne seront pas exécutés :
spamd[24124]: Can't locate Mail/DKIM.pm in @INC (@INC contains ...) at /.../SpamAssassin/Plugin/DKIM.pm line 77.
spamd[24124]: plugin: failed to parse plugin (from @INC):
Can't locate Mail/DKIM.pm in @INC (@INC contains ...) at /.../SpamAssassin/Plugin/DKIM.pm line 77.
Pour vérifier si les contrôles sont correctement exécutés, il suffit d'envoyer un message à partir d'un système ayant mis en place la signature DK/DKIM des messages sortants (Yahoo ou GMail par exemple). A la réception de ce message, on observe (dans le journal d'activité de la messagerie) que la signature a été contrôlée :
amavis[30453]: (30453-01) SPAM-TAG -> No, score=-1.49 tagged_above=-2 required=5
tests=[AWL=-1.110, BAYES_00=-2.599, DKIM_SIGNED=0.001, DKIM_VERIFIED=-0.001, TVD_SPACE_RATIO=2.219]
ou dans les en-têtes du message en question :
X-Spam-Status: No, score=1.093 tagged_above=-2 required=5
tests=[AWL=-0.185, BAYES_20=-0.74, DKIM_SIGNED=0.001,
DKIM_VERIFIED=-0.001, HTML_MESSAGE=0.001,
MIME_HEADER_CTYPE_ONLY=0.56, MIME_HTML_ONLY=1.457]
Dans les deux exemples ci-dessus, SpamAssassin (appelé via Amavis) a bien détecté une signature DKIM (marqueur DKIM_SIGNED) et l'a vérifiée (marqueur DKIM_VERIFIED). Vous noterez que les modifications du score (dans la configuration par défaut de SpamAssassin) ne sont pas très importantes (un centième de point dans un sens ou dans l'autre).
Signature des messages sortants
[A COMPLETER]
Références
- RFC 4870 , Domain-Based Email Authentication Using Public Keys Advertised in the DNS (DomainKeys)
- RFC 4871 , DomainKeys Identified Mail (DKIM) Signature
- RFC 5016 : Requirements for a DomainKeys Identified Mail (DKIM) Signing Practices Protocol.
- DKIM Author Domain Signing Policy (DRAFT IETF)
- Le site de DKIM .