Re: [exim] DKIM d= field and corresponding key

Top Page
Delete this message
Reply to this message
Author: Slavko
Date:  
To: exim-users
Subject: Re: [exim] DKIM d= field and corresponding key
Hi,

Dňa Thu, 14 Oct 2021 14:34:19 +0100 Andy Bennett via Exim-users
<exim-users@???> napísal:

> I have been trying to find good resources for how DKIM is commonly
> deployed on The Internet: all the DKIM RFCs and early guides seem to
> shift almost all of the policy decisions to the implementors and
> documentation from them seems to be sparse or confusing!


You can use whatever you want in the d= field, the only requirement for
DKIM is, that the TXT record for chosen domain (and selector) exists
and is valid. It have no more requirements, nor any relation with other
headers in mail nor SMTP commands.

But when you will use DMARC too, the requirements for DKIM is more
strict and the value of d= have to match RFC5322.From (header From:)
domain for strict match or have to be its subdomain for relaxed match.

I remember how hard was good resources/tutorial about setting DKIM with
exim, a will provide you my observations and settings (which can be
good or not).

To fulfill DMARC requirements i use:

    dkim_domain = ${domain:$h_from:}


This setting can be not appropriate for you, as when expansion returns
empty string (not valid domain in header or multiple From: headers),
the DKIM signing will not happen.

One can choose some more advanced expansion to set default/fallback
value, but i have forced valid and only one From: header elsewhere in
ACL, thus it is always valid in transport.

When expansion of dkim_domain was success, the domain value is
available in $dkim_domain variable, which then can be used in next
settings. Note, that the $dkim_domains was set from mail header, thus
it will be tainted and cannot be used directly to access in new
exim versions files (see latter).

Next is needed to choose valid selector for this domain. You can use
common selector for all domains, but i different per domain base, thus
i store mapping in file, eg. map-dkim:

    domain.tld:      selector
    ...


Or you can choose to use multiple selectors in it (e.g. for dual sign):

    domain.tld:      sel_rsa:sel_ed
    ...


And then i setup selector based on domain name lookup in this file:

    dkim_selector = ${lookup{$dkim_domain} lsearch{DKIMMAPPING}}


When domain is not found in this mapping, it returns empty string,
which means, that DKIM processing is stopped and no DKIM signature will
be added into mail. Thus using lookup filters "invalid" domains and in
the same step it de-taints the value of $dkim_domain. One can setup
some faillback value here, but i consider it as useless, as it can ends
with nonexistent TXT records, which is the same as not sign at all.

When expansion of dkim_selector returns some value, it is latter
accessible in $dkim_selector variable, which is not tainted (as result
of lookup).

Finally ou have to choose private key, i use keys in files, which are
stored in separate directory with access rights limited to exim's user
and they are stored in form:

    <selector>.<domain>.key


Then i use $dkim_domain and $dkim_selector variables to access them:

    dkim_private_key = ${lookup {$dkim_selector.$dkim_domain.key} \
                         dsearch,ret=full{DKIMDIR}}


Note of use the dsearch, to allow use of tainted $dkim_domain variabe.
Once again, if key file is not found, the expansion is empty and no
DKIM signing happen.

I use all other DKIM settings the same for all domains, thus i setup
them statically, but one can use the "expand" expansion for result of
DKIM mapping lookup and setup this mapping file eg. as this:

    domain.tld:      selector=sel_rsa:sel_ed cannon=...


Finally i found default headers list for signing as not optimal, i and
borrow settings from rspamd with conditional owersign and sign headers
(can be wrap) and adapted it for exim:

    dkim_sign_headers = +From:+Reply-To:+Subject:+To:+Cc\
        ${if def:h_Sender: {:+Sender}{}}\
        ${if def:h_Date: {:+Date}{}}\
        ${if def:h_Message-Id: {:+Message-Id}{}}\
        ${if def:h_Mime-Version: {:+Mime-Version}{}}\
        ${if def:h_Content-Description: {:+Content-Description}{}}\
        ${if def:h_Content-Id: {:+Content-Id}{}}\
        ${if def:h_Content-Type: {:+Content-Type}{}}\
        ${if def:h_Content-Type-Encoding: {:+Content-Type-Encoding}{}}\
        ${if def:h_In-Reply-To: {:+In-Reply-To}{}}\
        ${if def:h_References: {:+References}{}}\
        ${if def:h_Openpgp: {:+Openpgp}{}}\
        ${if def:h_Autocrypt: {:+Autocrypt}{}}\
        :=Resent-To:=Resent-Cc:=Resent-Date:=Resent-From:=Resent-Sender:=Resent-Message-Id\
        :=List-Archive:=List-Id:=List-Help:=List-Owner:=List-Unsubscribe:=List-Subscribe:=List-Post


> I have a low enough volume that Google Postmaster tools won't tell me
> anything about my domain.


You can enable DMARC rua reports to see auth results.

While i do not use gmail at all, i cannot tell what it means, but i
will guess that mentioned signature is added for its outgoing mails.
You have to setup own DKIM, if you are not using some smarthost which
cat do it for you.

Do not mix google's reputation into it. MTA often build own reputation
system, eg. my MTA/SPAM check has one, but i do not use DKIM for it.
Anyway, you will want to have own reputation, not the google one, which
is worst on my server and any non-whitelisted gmail sender ends in SPAM
folder due it...

I sue this settings for long time, i only adjust it to conform tainted
processing in recent versions and at least the RSA signing works as
expected (as reported by DMARC). I am not sure with ED25519 signing yet,
as i have not enough feedback, but testing tools shows that it is OK
too.

regards

--
Slavko
http://slavino.sk