[exim] Full SPF/DKIM/DMARC validation policies for Exim on C…

Top Page
Delete this message
Reply to this message
Author: Adrian (Aad) Offerman
Date:  
To: exim-users
Subject: [exim] Full SPF/DKIM/DMARC validation policies for Exim on CentOS 8 (feedback please)
Hello all,

I've been working on the implementation of SPF/DKIM/DMARC policies in
the configuration of Exim on CentOS 8 (8.1). It turns out that
everything is there (i.e. all functionality is compiled in in the
package that comes with the repository), but there are no policies at
all defined in '/etc/exim/exim.conf'.
(there are some 'dkim_disable_verify' and 'dmarc_disable_verify'
statements where DKIM/DMARC-validation should not take place, i.e. for
local/relayed/authenticated hosts; and SPF and DKIM are validated as
part of the (external) spam scan)

Please find below the policies that I've created and tested (checking
logs and headers of validating and non-validating messages in a test
environment that is, not in a volume/operational environment yet).

Any feedback on the polices themselves would be great. And maybe these
would be a good starting point to get some policies into the Exim
configuration that comes with CentOS, probably best with an on/off
switch variable.

Tnx, Adrian

________


For SPF validation:

acl_check_mail:

# Hosts are required to say HELO (or EHLO) before sending mail.
# So don't allow them to use the MAIL command if they haven't
# done so.

  deny condition = ${if eq{$sender_helo_name}{} {1}}
       message = Nice boys say HELO first


# reject messages from senders listed in these DNSBLs
deny dnslists = zen.spamhaus.org

  # 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


________


For DKIM validation:

acl_smtp_dkim = acl_check_dkim

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


________


For DMARC validation:

global:

# DMARC
dmarc_tld_file=/usr/share/publicsuffix/public_suffix_list.dat
dmarc_history_file=/var/spool/exim/opendmarc/history.dat
dmarc_forensic_sender=postmaster@???


added to acl_check_data:

# DMARC
warn    dmarc_status = quarantine
        !authenticated = *
        log_message = Message from $dmarc_used_domain failed sender's
DMARC policy; QUARANTINE
        control = dmarc_enable_forensic
        set acl_m_quarantine = 1
        # this variable to use in a router/transport
deny    dmarc_status = reject
        !authenticated = *
        message = Message from $dmarc_used_domain failed sender's DMARC
policy; REJECT
        control = dmarc_enable_forensic
warn    add_header = :at_start: ${authresults {$primary_hostname}}



changed in 'localuser' router:

#transport = local_delivery
transport = ${if =={$acl_m_quarantine}{1}
{local_delivery_quarantine}{local_delivery}}


added a new transport:

  local_delivery_quarantine:
    driver = appendfile
    #file = /var/mail/$local_part
    directory = /home/mail-quarantine/Maildir
    user = mail-quarantine
    home_directory = /home/mail-quarantine
    current_directory = /home/mail-quarantine
    maildir_format
    delivery_date_add
    envelope_to_add
    return_path_add
    group = mail
    mode = 0660