On 1/1/2017 8:32 AM, Andrew C Aitchison wrote:
> On Sat, 31 Dec 2016, Ian Zimmerman wrote:
>
>> So, that section of the Spec says:
>>
>> Current DKIM verifiers may want to explicitly call the ACL for known
>> domains or identities. This would be achieved as follows:
>>
>> dkim_verify_signers = paypal.com:ebay.com:$dkim_signers
>>
>> This would result in acl_smtp_dkim always being called for "paypal.com"
>> and "ebay.com", plus all domains and identities that have signatures in
>> the message. You can also be more creative in constructing your
>> policy. For example:
>>
>> dkim_verify_signers = $sender_address_domain:$dkim_signers
>>
>> But I cannot see the point of doing either of these things.
>>
>> Either one of the prepended domains has a valid signature in the
>> message, or none has. One way or the other, the final result of running
>> acl_smtp_dkim for _all_ members of dkim_verify_signers is the same as if
>> nothing were prepended.
>>
>> At least if the only decision I want to make is "one of
>> dkim_verify_signers has a valid sig" versus "any other outcome".
>> If I were to consider invalid and failing sigs things would be
>> different.
>> Is _that_ why this "creative" hook exists?
>
> I think the docs were written before we knew how often things broke DKIM,
> and almost certainly before DMARC.
>
> IIUC the idea was that that writer/postmaster *knows* that paypal and
> ebay
> always sign with dkim, so an unsigned message allegedly from those hosts
> must be spam.
>
>
This is how we do it on our production servers:
1. Each relay host has a local copy of a MySQL database which is
replicated from a central master
2. One of the tables is called "dkim_known_signers" which contains a
list of domains for which we force verification (gmail.com, paypal.com,
et. al)
3. The global section of Exim config contains:
DKIM_KNOWN_SIGNERS = select domain from dkim_known_signers
where active=1;
domainlist dkim_known_signers = ${lookup
mysql{DKIM_KNOWN_SIGNERS}{${sg{$value}{\\n}{ : }} }}
as one of the domain lists.
4. We also support whitelisting for "known broken senders"
5. Our DKIM ACL is quite large and not terribly intuiative as there is
some negative-logic in here:
###
### ack_check_dkim: this ACL is used for checking DKIM
###
#
# acl_m2 set to zero on start for normal/full checks, set to 1 if
white-listed
#
acl_check_dkim:
#
# start of DKIM debug message and clear macro
#
warn set acl_m2 = 0
logwrite = DKIM START: domain=$sender_address_domain
possible_signer=$dkim_cur_signer status=$dkim_verify_status ${if
def:dkim_verify_reason {(reason=$dkim_verify_reason) }}
#
# strict checking on known signers...
#
deny sender_domains = +dkim_known_signers
# dkim_signers = +dkim_known_signers
dkim_status = none:invalid:fail
message = Message from $sender_address_domain (known
signer) with invalid or missing signature
logwrite = DKIM DENY: Rejected $sender_address_domain
is known signer (in database) but has invalid/missing signature
accept sender_domains = +dkim_known_signers
# dkim_signers = +dkim_known_signers
dkim_status = pass
logwrite = DKIM PASS: Accepted $sender_address_domain
is known signer and has good signature
add_header = :after_received:X-DKIM-Result:
Domain=$sender_address_domain Result=Good and Known Domain
#
# ignore noise where we have no signature
#
accept dkim_status = none
# logwrite = DKIM SKIP: Skipping DKIM checks - no
signature for: $dkim_cur_signer
#
# skip DKIM if domain whitelisted for DKIM, i.e. known good
domain that has broken DKIM
#
accept sender_domains = +dkim_whitelist_domains
logwrite = DKIM SKIP: Skipping DKIM checks for
whitelisted domain: $sender_address_domain
set acl_m2 = 1
#
# skip DKIM checks on hosts we relay for
#
accept hosts = +relay_from_hosts
logwrite = DKIM SKIP: Skipping DKIM checks for relay
host: $sender_fullhost
#
# skip DKIM checks on authenticated hosts (that we also relay for)
#
accept authenticated = *
logwrite = DKIM SKIP: Skipping DKIM checks for
authenticated host: $sender_fullhost
#
# defer when message not testable, e.g. can't get public key, etc.
#
defer dkim_status = invalid
message = Message from $sender_address_domain cannot be
verified
logwrite = DKIM DEFER: domain=$sender_address_domain
cannot obtain public key
#
# accept the message (correctly signed)
#
accept dkim_status = pass
sender_domains = $sender_address_domain
dkim_signers = $sender_address_domain
logwrite = DKIM PASS: domain=$sender_address_domain
signer=$dkim_cur_signer status=$dkim_verify_status
add_header = :after_received:X-DKIM-Result:
Domain=$sender_address_domain Result=Signature OK
#
# accept the message EVEN IF the signature FAILS! due to white
listing
#
accept condition = ${if eq {$acl_m2}{1}}
dkim_status = fail
sender_domains = $sender_address_domain
dkim_signers = $sender_address_domain
logwrite = DKIM FAIL (WHITELISTED):
domain=$sender_address_domain status=$dkim_verify_status - DKIM failed
but message accepted
add_header = :after_received:X-DKIM-Result:
Domain=$sender_address_domain Result=FAIL (but whitelisted)
#
# deny (strict) when message fails signature test *and* acl_m2
= 0 (not whitelisted)
#
deny condition = ${if eq {$acl_m2}{0}}
dkim_status = fail
sender_domains = $sender_address_domain
dkim_signers = $sender_address_domain
message = Message from has invalid DKIM signature
logwrite = DKIM FAIL (DENY):
domain=$sender_address_domain - message rejected!
#
# accept anything else (should never get here)
#
accept logwrite = DKIM DEFAULT: domain=$sender_address_domain
- message accepted (at end of ACL)
What this does for us is:
* force checking of known DKIM signers - reject email from known
signers that doesn't have a signature
* check signatures on all emails - when present
* return a 421 (defer) for email where a DKIM signature is present
but the public key cannot be fetched
* allow for whitelisting of broken hosts
* do something sane where there are two (or more) DKIM signatures
that may be in conflict
* provide lots of useful debug
What we find this that there are household names (like ASDA, Laithwaites
wines, and others that included a well known ISP) that can't do DKIM
properly - typically they sign outgoing emails and then forget to put
the public key in the DNS, have an out-of-date key in the DNS, are using
tge wrong selector or have a syntax error in the key data (doesn't parse).
As a result I have to refer them to the DKIM key checker at ProtoDave:
https://protodave.com/
The following shell snippet will weed out the broken senders from my log
entries:
grep DKIM mainlog | grep DEFER | cut -f6 -d ' ' | cut -f2 -d
'=' | grep . | sort | uniq
today's "Rogues Gallery" includes the following:
root@relay1:/etc/exim# grep DKIM /var/log/exim/mainlog | grep
DEFER | cut -f6 -d ' ' | cut -f2 -d '=' | grep . | sort | uniq
9bbj.com
almin.co.zw
ares.constituted300.site
b.e.iwantoneofthose.com
causeway.com
centiplex.net
dynamicplumbing.co.nz
email.crewclothing.co.uk
e.mail.halfords.com
email.hotelderby.be
*eu-west-1.amazonses.com*
financial-businessadvisory.com
grnetwork.org
hcqs.us
hns.ma
impactcorner.com
kingster.edu.in
kooshansr.ir
lists.epuk.org
mail157.atl21.rsgsv.net
mail164.atl221.rsgsv.net
mail237.atl61.mcsv.net
mail43.atl161.mcsv.net
manage.c21media.net
mediamasher.com
midaspack.com
mmmail032.co.uk
mol.go.th
mstat220.co.uk
nebulahub.com
*newsletter.laithwaites.co.uk*
*petsensedirect.co.uk*
phliks.com
reflexlearning.com
s1.hansindia.co.in
saibaque.com
savtastar.co.il
sendgrid.myfonts.com
server.theprogressteam.com
service.jimtrade.com
surabaya.go.id
thegfcc.org
thprom.ru
ukrs394972.pur3.net
USACOLIS.biz
useli.org
yogaforny.com
root@relay1:/etc/exim#
*sigh*
Mike