From c7280055a83085b3d3efd5a9296a1bea4923315c Mon Sep 17 00:00:00 2001 From: jvolkenant Date: Fri, 25 Dec 2020 14:22:24 -0800 Subject: [PATCH] Implement SPF/DMARC checks, add spam weight to those mails (#1836) --- setup/dkim.sh | 26 ++++++++++++++++++++++ setup/spamassassin.sh | 50 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/setup/dkim.sh b/setup/dkim.sh index 5bd3237..05221b2 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -64,6 +64,32 @@ tools/editconf.py /etc/opendmarc.conf -s \ "Syslog=true" \ "Socket=inet:8893@[127.0.0.1]" +# SPFIgnoreResults causes the filter to ignore any SPF results in the header +# of the message. This is useful if you want the filter to perfrom SPF checks +# itself, or because you don't trust the arriving header. This added header is +# used by spamassassin to evaluate the mail for spamminess. + +tools/editconf.py /etc/opendmarc.conf -s \ + "SPFIgnoreResults=true" + +# SPFSelfValidate causes the filter to perform a fallback SPF check itself +# when it can find no SPF results in the message header. If SPFIgnoreResults +# is also set, it never looks for SPF results in headers and always performs +# the SPF check itself when this is set. This added header is used by +# spamassassin to evaluate the mail for spamminess. + +tools/editconf.py /etc/opendmarc.conf -s \ + "SPFSelfValidate=true" + +# AlwaysAddARHeader Adds an "Authentication-Results:" header field even to +# unsigned messages from domains with no "signs all" policy. The reported DKIM +# result will be "none" in such cases. Normally unsigned mail from non-strict +# domains does not cause the results header field to be added. This added header +# is used by spamassassin to evaluate the mail for spamminess. + +tools/editconf.py /etc/opendkim.conf -s \ + "AlwaysAddARHeader=true" + # Add OpenDKIM and OpenDMARC as milters to postfix, which is how OpenDKIM # intercepts outgoing mail to perform the signing (by adding a mail header) # and how they both intercept incoming mail to add Authentication-Results diff --git a/setup/spamassassin.sh b/setup/spamassassin.sh index d6c8b83..989bbff 100755 --- a/setup/spamassassin.sh +++ b/setup/spamassassin.sh @@ -67,6 +67,56 @@ tools/editconf.py /etc/spamassassin/local.cf -s \ "add_header all Report"=_REPORT_ \ "add_header all Score"=_SCORE_ + +# Authentication-Results SPF/Dmarc checks +# --------------------------------------- +# OpenDKIM and OpenDMARC are configured to validate and add "Authentication-Results: ..." +# headers by checking the sender's SPF & DMARC policies. Instead of blocking mail that fails +# these checks, we can use these headers to evaluate the mail as spam. +# +# Our custom rules are added to their own file so that an update to the deb package config +# does not remove our changes. +# +# We need to escape period's in $PRIMARY_HOSTNAME since spamassassin config uses regex. + +escapedprimaryhostname="${PRIMARY_HOSTNAME//./\\.}" + +cat > /etc/spamassassin/miab_spf_dmarc.cf << EOF +# Evaluate DMARC Authentication-Results +header DMARC_PASS Authentication-Results =~ /$escapedprimaryhostname; dmarc=pass/ +describe DMARC_PASS DMARC check passed +score DMARC_PASS -0.1 + +header DMARC_NONE Authentication-Results =~ /$escapedprimaryhostname; dmarc=none/ +describe DMARC_NONE DMARC record not found +score DMARC_NONE 0.1 + +header DMARC_FAIL_NONE Authentication-Results =~ /$escapedprimaryhostname; dmarc=fail \(p=none/ +describe DMARC_FAIL_NONE DMARC check failed (p=none) +score DMARC_FAIL_NONE 2.0 + +header DMARC_FAIL_QUARANTINE Authentication-Results =~ /$escapedprimaryhostname; dmarc=fail \(p=quarantine/ +describe DMARC_FAIL_QUARANTINE DMARC check failed (p=quarantine) +score DMARC_FAIL_QUARANTINE 5.0 + +header DMARC_FAIL_REJECT Authentication-Results =~ /$escapedprimaryhostname; dmarc=fail \(p=reject/ +describe DMARC_FAIL_REJECT DMARC check failed (p=reject) +score DMARC_FAIL_REJECT 10.0 + +# Evaluate SPF Authentication-Results +header SPF_PASS Authentication-Results =~ /$escapedprimaryhostname; spf=pass/ +describe SPF_PASS SPF check passed +score SPF_PASS -0.1 + +header SPF_NONE Authentication-Results =~ /$escapedprimaryhostname; spf=none/ +describe SPF_NONE SPF record not found +score SPF_NONE 2.0 + +header SPF_FAIL Authentication-Results =~ /$escapedprimaryhostname; spf=fail/ +describe SPF_FAIL SPF check failed +score SPF_FAIL 5.0 +EOF + # Bayesean learning # ----------------- #