On 06/11/2020 11:53, Mark Elkins via Exim-users wrote:
I've got the following in exim.conf....
acl_check_dkim:
deny dkim_status = fail
message = DKIM validation failed: $dkim_verify_status
log_message = DKIM validation failed: $dkim_verify_status \
(address=$sender_address, domain=$dkim_cur_signer), \
signature is bad
defer dkim_status = invalid
message = DKIM signature invalid: $dkim_verify_status
log_message = DKIM signature invalid: $dkim_verify_status \
(address=$sender_address, domain=$dkim_cur_signer), \
invalid signature
# NOTE: dkim_status = none should never happen in this ACL
accept
# Add an X-DKIM header to the message
add_header = :at_start: X-DKIM: DKIM validation passed: \
(address=$sender_address domain=$dkim_cur_signer), \
signature is good
logwrite = DKIM validation passed
This is breaking some of my customers...
How can I soften the blow? - so they can get their incorrectly signed
emails from these broken servers (some of which live in my countries
banking system and are otherwise completely valid)
I've got something similar for SPF....
# SPF Checks
acl_check_mail:
# SPF validation
deny spf = fail : softfail
message = SPF validation failed: \
$sender_host_address is not allowed to send mail from \
${if def:sender_address_domain \
{$sender_address_domain}{$sender_helo_name}}
log_message = SPF validation failed\
${if eq{$spf_result}{softfail} { (softfail)}{}}: \
$sender_host_address is not allowed to send mail from \
${if def:sender_address_domain \
{$sender_address_domain}{$sender_helo_name}}
deny spf = permerror
message = SPF validation failed: \
syntax error in SPF record(s) for \
${if def:sender_address_domain \
{$sender_address_domain}{$sender_helo_name}}
log_message = SPF validation failed (permerror): \
syntax error in SPF record(s) for \
${if def:sender_address_domain \
{$sender_address_domain}{$sender_helo_name}}
defer spf = temperror
message = temporary error during SPF validation; \
please try again later
log_message = SPF validation failed temporary; deferred
# Log SPF none/neutral result
warn spf = none : neutral
log_message = SPF validation none/neutral
# Use the lack of reverse DNS to trigger greylisting. Some people
# even reject for it but that would be a little excessive.
warn condition = ${if eq{$sender_host_name}{} {1}}
set acl_m_greylistreasons = Host $sender_host_address \
lacks reverse DNS\n$acl_m_greylistreasons
accept
# Add an SPF-Received header to the message
add_header = :at_start: $spf_received
logwrite = SPF validation passed
I think I have to allow this sort of stuff through for now - but would
love it to come through with readable error messages for now - give
people a chance to fix their errors.
Many suggest that DKIM be used as part of wider DMARC and with layered
policy and the equivalent of 'soft fail' etc. however I developed my
DKIM support and processing very early on, i.e. early days of DKIM and
before DMARC, hence I have an implementation with our company policy
baked in.
We support several hundred domains and everything has a MySQL backend.
Mail processing is shared between three front-end relay boxes [relay1,
relay2 and relay3] with two on one site and one on a different site
which gives us server, site and power resilience. Relay1 is the primary
and holds the master database rel2 and rely3 replicate from it.
We have the concept of 'known signers' - these are sites (domains) that
we know correctly sign and therefor we can hard enforce, for example:
MariaDB [relay]> select * from dkim_known_signers limit 15;
+------+--------+------------------+
| id | active | domain |
+------+--------+------------------+
| 1 | 1 | ebay.com |
| 3 | 1 | paypal.com |
| 4 | 1 | paypal.co.uk |
| 2 | 1 | ebay.co.uk |
| 5 | 1 | yahoo.com |
| 6 | 1 | yahoo.co.uk |
| 7 | 1 | gmail.com |
| 8 | 1 | googlemail.com |
| 9 | 1 | google.com |
| 10 | 1 | facebook.com |
| 11 | 1 | facebookmail.com |
| 12 | 1 | fwd.facebook.com |
| 13 | 1 | spc.facebook.com |
| 14 | 1 | googlegroups.com |
| 15 | 1 | groups.io |
+------+--------+------------------+
We have the concept of 'whitelisted domains' - ones we will allow in
with broken DKIM (and potentially other broken stuff).
Our policy can be described:
if you are known good signer - test for good signatures only - drop
everything else
if you are white listed, let you in with bad signatures
if you are neither 'known signer' or 'whitelisted' and have a
signature treat it at face value:
pass => let you in
invalid => can't get public key => defer
fail => reject
if you don't have a signature, let you in
To get a sample of what's going on out there, Relay1 writes back all the
DKIM it sees to the database - this gives us an insight into what's
failing and why. We find house-hold names with misconfigured servers
including Microsoft, Amazon, HSBC, Plenty-of-Fish, Capita and government
departments.
In every case that I have investigated from our capture database there
has been a genuine problem at the other end.
You might care to pick some bits out of my DKIM ACL (below).
Mike
DKIM_WHITELIST_DOMAINS = select domain from dkim_whitelist_domains
domainlist dkim_whitelist_domains = ${lookup
mysql{DKIM_WHITELIST_DOMAINS}{${sg{$value}{\\n}{ : }} }}
DKIM_KNOWN_SIGNERS = select domain from dkim_known_signers where active=1;
domainlist dkim_known_signers = ${lookup
mysql{DKIM_KNOWN_SIGNERS}{${sg{$value}{\\n}{ : }} }}
###
### acl_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 domain
#
acl_check_dkim:
#
# start of DKIM debug message and clear macro
#
#
# Only do MySQL INSERT on Relay1 !!!
#
warn set acl_m_dummy = ${lookup mysql{INSERT INTO dkim_log
(status,reason,host,domain,identity,selector,algo) VALUES
('${quote_mysql:$dkim_verify_status}',
'${quote_mysql:$dkim_verify_reason}','${quote_mysql:$sender_fullhost}',
'${quote_mysql:$dkim_domain}', '${quote_mysql:$dkim_identity}',
'${quote_mysql:$dkim_selector}', '${quote_mysql:$dkim_algo}' )}}
log_message = 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_status = none:invalid:fail
message = Message from $sender_address_domain (known
signer) with invalid or missing signature
log_message = DKIM DENY: Rejected
$sender_address_domain is known signer (in database) but has
invalid/missing signature
accept sender_domains = +dkim_known_signers
dkim_status = pass
log_message = 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
# log_message = 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
log_message = 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
log_message = DKIM SKIP: Skipping DKIM checks for relay
host: $sender_fullhost
#
# skip DKIM checks on authenticated hosts (that we also relay for)
#
accept authenticated = *
log_message = 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
log_message = 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
log_message = 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
log_message = DKIM FAIL (BUT 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
log_message = DKIM FAIL (DENY):
domain=$sender_address_domain - message rejected!
#
# accept anything else (should never get here)
#
accept log_message = DKIM DEFAULT:
domain=$sender_address_domain - message accepted (at end of ACL)
--
## List details at https://lists.exim.org/mailman/listinfo/exim-users
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/