Integração com Exim SPFBL

Leandro Carlos Rodrigues edited this page Nov 12, 2017 · 21 revisions

Para integrar o SPFBL no Exim, basta utilizar esta configuração completa como modelo:

### acl/30_exim4-config_check_mail
#################################

# This access control list is used for every MAIL command in an incoming
# SMTP message. The tests are run in order until the address is either
# accepted or denied.
#
acl_check_mail:


  .ifdef CHECK_MAIL_HELO_ISSUED
  deny
    message = no HELO given before MAIL command
    condition = ${if def:sender_helo_name {no}{yes}}
  .endif


  # Define SPFBL variables
  accept
    set acl_c_body_check = true
    set acl_c_malware_check = true
    set acl_c_whitelisted = false
    set acl_c_spamflag = false
    set acl_c_freeze = false
    set acl_c_reject = false
    set acl_c_blocklinked = false


### acl/30_exim4-config_check_rcpt
#################################

# This access control list is used for every RCPT command in an incoming
# SMTP message. The tests are run in order until the address is either
# accepted or denied.
#
acl_check_rcpt:


  # Accept if the source is local SMTP (i.e. not over TCP/IP). We do this by
  # testing for an empty sending host field.
  accept
    hosts = :
    control = dkim_disable_verify


  # Do not try to verify DKIM signatures of incoming mail if DC_minimaldns
  # or DISABLE_DKIM_VERIFY are set.
.ifdef DC_minimaldns
  warn
    control = dkim_disable_verify
.else
.ifdef DISABLE_DKIM_VERIFY
  warn
    control = dkim_disable_verify
.endif
.endif


  # The following section of the ACL is concerned with local parts that contain
  # certain non-alphanumeric characters. Dots in unusual places are
  # handled by this ACL as well.
  #
  # Non-alphanumeric characters other than dots are rarely found in genuine
  # local parts, but are often tried by people looking to circumvent
  # relaying restrictions. Therefore, although they are valid in local
  # parts, these rules disallow certain non-alphanumeric characters, as
  # a precaution.
  #
  # Empty components (two dots in a row) are not valid in RFC 2822, but Exim
  # allows them because they have been encountered. (Consider local parts
  # constructed as "firstinitial.secondinitial.familyname" when applied to
  # a name without a second initial.) However, a local part starting
  # with a dot or containing /../ can cause trouble if it is used as part of a
  # file name (e.g. for a mailing list). This is also true for local parts that
  # contain slashes. A pipe symbol can also be troublesome if the local part is
  # incorporated unthinkingly into a shell command line.
  #
  # These ACL components will block recipient addresses that are valid
  # from an RFC2822 point of view. We chose to have them blocked by
  # default for security reasons.
  #
  # If you feel that your site should have less strict recipient
  # checking, please feel free to change the default values of the macros
  # defined in main/01_exim4-config_listmacrosdefs or override them from a
  # local configuration file.
  # 
  # Two different rules are used. The first one has a quite strict
  # default, and is applied to messages that are addressed to one of the
  # local domains handled by this host.

  # The default value of CHECK_RCPT_LOCAL_LOCALPARTS is defined in
  # main/01_exim4-config_listmacrosdefs:
  # CHECK_RCPT_LOCAL_LOCALPARTS = ^[.] : ^.*[@%!/|`#&?]
  # This blocks local parts that begin with a dot or contain a quite
  # broad range of non-alphanumeric characters.
  .ifdef CHECK_RCPT_LOCAL_LOCALPARTS
  deny
    domains = +local_domains
    local_parts = CHECK_RCPT_LOCAL_LOCALPARTS
    message = restricted characters in address
  .endif


  # The second rule applies to all other domains, and its default is
  # considerably less strict.
  
  # The default value of CHECK_RCPT_REMOTE_LOCALPARTS is defined in
  # main/01_exim4-config_listmacrosdefs:
  # CHECK_RCPT_REMOTE_LOCALPARTS = ^[./|] : ^.*[@%!`#&?] : ^.*/\\.\\./

  # It allows local users to send outgoing messages to sites
  # that use slashes and vertical bars in their local parts. It blocks
  # local parts that begin with a dot, slash, or vertical bar, but allows
  # these characters within the local part. However, the sequence /../ is
  # barred. The use of some other non-alphanumeric characters is blocked.
  # Single quotes might probably be dangerous as well, but they're
  # allowed by the default regexps to avoid rejecting mails to Ireland.
  # The motivation here is to prevent local users (or local users' malware)
  # from mounting certain kinds of attack on remote sites.
  .ifdef CHECK_RCPT_REMOTE_LOCALPARTS
  deny
    domains = !+local_domains
    local_parts = CHECK_RCPT_REMOTE_LOCALPARTS
    message = restricted characters in address
  .endif


  # Deny unless the sender address can be verified.
  #
  # This is disabled by default so that DNSless systems don't break. If
  # your system can do DNS lookups without delay or cost, you might want
  # to enable this feature.
  #
  # This feature does not work in smarthost and satellite setups as
  # with these setups all domains pass verification. See spec.txt chapter
  # 39.31 with the added information that a smarthost/satellite setup
  # routes all non-local e-mail to the smarthost.
  .ifdef CHECK_RCPT_VERIFY_SENDER
  deny
    message = Sender verification failed
    !acl = acl_local_deny_exceptions
    !verify = sender
  .endif

  # Accept if the message comes from one of the hosts for which we are an
  # outgoing relay. It is assumed that such hosts are most likely to be MUAs,
  # so we set control=submission to make Exim treat the message as a
  # submission. It will fix up various errors in the message, for example, the
  # lack of a Date: header line. If you are actually relaying out out from
  # MTAs, you may want to disable this. If you are handling both relaying from
  # MTAs and submissions from MUAs you should probably split them into two
  # lists, and handle them differently.

  # Recipient verification is omitted here, because in many cases the clients
  # are dumb MUAs that don't cope well with SMTP error responses. If you are
  # actually relaying out from MTAs, you should probably add recipient
  # verification here.

  # Note that, by putting this test before any DNS black list checks, you will
  # always accept from these hosts, even if they end up on a black list. The
  # assumption is that they are your friends, and if they get onto black
  # list, it is a mistake.
  accept
    hosts = +relay_from_hosts
    control = submission/sender_retain
    control = dkim_disable_verify


  # Accept if the message arrived over an authenticated connection, from
  # any host. Again, these messages are usually from MUAs, so recipient
  # verification is omitted, and submission mode is set. And again, we do this
  # check before any black list tests.
  accept
    authenticated = *
    control = submission/sender_retain
    control = dkim_disable_verify
    hosts = 52.67.29.218 : 108.179.253.185 : 209.85.128.0/17 : 74.125.0.0/16 : 209.85.128.0/17 : 2607::f8b0::::/32 : 2a00::1450::4000::::/37


  # Insist that any other recipient address that we accept is either in one of
  # our local domains, or is in a domain for which we explicitly allow
  # relaying. Any other domain is rejected as being unacceptable for relaying.
  require
    message = ${run{/usr/local/bin/spfbl abuse $sender_host_address}{5.7.1 SPFBL relay not permitted}{relay not permitted}}
    domains = +local_domains : +relay_to_domains : \
              ${if exists{CONFDIR/hubbed_hosts}\
                   {partial-lsearch;CONFDIR/hubbed_hosts}\
              fail}


  # We also require all accepted addresses to be verifiable. This check will
  # do local part verification for local domains, but only check the domain
  # for remote domains.
  require
    verify = recipient


  # Verify recipients listed in local_rcpt_callout with a callout.
  # This is especially handy for forwarding MX hosts (secondary MX or
  # mail hubs) of domains that receive a lot of spam to non-existent
  # addresses.  The only way to check local parts for remote relay
  # domains is to use a callout (add /callout), but please read the
  # documentation about callouts before doing this.
  deny
    !acl = acl_local_deny_exceptions
    recipients = ${if exists{CONFDIR/local_rcpt_callout}\
                            {CONFDIR/local_rcpt_callout}\
                      {}}
    !verify = recipient/callout


  # CONFDIR/local_sender_blacklist holds a list of envelope senders that
  # should have their access denied to the local host. Incoming messages
  # with one of these senders are rejected at RCPT time.
  #
  # The explicit white lists are honored as well as negative items in
  # the black list. See exim4-config_files(5) for details.
  deny
    message = sender envelope address $sender_address is locally blacklisted here. If you think this is wrong, get in touch with postmaster
    !acl = acl_local_deny_exceptions
    senders = ${if exists{CONFDIR/local_sender_blacklist}\
                   {CONFDIR/local_sender_blacklist}\
                   {}}


  # deny bad sites (IP address)
  # CONFDIR/local_host_blacklist holds a list of host names, IP addresses
  # and networks (CIDR notation)  that should have their access denied to
  # The local host. Messages coming in from a listed host will have all
  # RCPT statements rejected.
  #
  # The explicit white lists are honored as well as negative items in
  # the black list. See exim4-config_files(5) for details.
  deny
    message = sender IP address $sender_host_address is locally blacklisted here. If you think this is wrong, get in touch with postmaster
    !acl = acl_local_deny_exceptions
    hosts = ${if exists{CONFDIR/local_host_blacklist}\
                 {CONFDIR/local_host_blacklist}\
                 {}}


  # Warn if the sender host does not have valid reverse DNS.
  # 
  # If your system can do DNS lookups without delay or cost, you might want
  # to enable this.
  # If sender_host_address is defined, it's a remote call.  If
  # sender_host_name is not defined, then reverse lookup failed.  Use
  # this instead of !verify = reverse_host_lookup to catch deferrals
  # as well as outright failures.
  .ifdef CHECK_RCPT_REVERSE_DNS
  warn
    condition = ${if and{{def:sender_host_address}{!def:sender_host_name}}\
                      {yes}{no}}
    add_header = X-Host-Lookup-Failed: Reverse DNS lookup failed for $sender_host_address (${if eq{$host_lookup_failed}{1}{failed}{deferred}})
  .endif


  # Defer multiple recipients if message is frozen.
  defer
    condition = $acl_c_freeze
    message = 4.7.1 SPFBL too many recipients in the same connection.
    log_message = SPFBL too many recipients.


  # Use SPFBL to perform SPF check.
  warn
    set acl_c_spfbl = ${run{/usr/local/bin/spfbl query '$sender_host_address' '$sender_address' '$sender_helo_name' '$local_part@$domain'}{ERROR: $value}{$value}}
    set acl_c_spfreceived = $runrc
  accept
    condition = ${if eq {$acl_c_spfreceived}{15}{true}{false}}
  deny
    message = 5.7.1 SPFBL $sender_host_address is not allowed to send mail from $sender_address. See http://spfbl.net/en/feedback
    log_message = SPFBL check failed.
    condition = ${if eq {$acl_c_spfreceived}{3}{true}{false}}
  defer
    message = 4.7.1 SPFBL transient error occurred when checking SPF record. See http://spfbl.net/en/feedback
    log_message = SPFBL check error.
    condition = ${if eq {$acl_c_spfreceived}{6}{true}{false}}
  deny
    message = 4.7.1 SPFBL one or more SPF records from $sender_host_address could not be interpreted. See http://spfbl.net/en/feedback
    log_message = SPFBL check unknown.
    condition = ${if eq {$acl_c_spfreceived}{7}{true}{false}}
  deny
    message = 5.7.1 SPFBL sender has non-existent internet domain. See http://spfbl.net/en/feedback
    log_message = SPFBL check nxdomain.
    condition = ${if eq {$acl_c_spfreceived}{13}{true}{false}}
  deny
    message = 5.7.1 SPFBL non-existent sender. See http://spfbl.net/en/feedback
    log_message = SPFBL check nxsender.
    condition = ${if eq {$acl_c_spfreceived}{21}{true}{false}}
  deny
    message = 5.7.1 SPFBL invalid sender indentification. See http://spfbl.net/en/feedback
    log_message = SPFBL check invalid.
    condition = ${if eq {$acl_c_spfreceived}{14}{true}{false}}
  defer
    message = 4.7.2 SPFBL $acl_c_spfbl
    log_message = SPFBL check listed.
    condition = ${if eq {$acl_c_spfreceived}{8}{true}{false}}
    condition = ${if match {$acl_c_spfbl}{^LISTED https?://}{true}{false}}
  defer
    message = 4.7.2 SPFBL temporarily blocked on this server. See http://spfbl.net/en/feedback
    log_message = SPFBL check listed.
    condition = ${if eq {$acl_c_spfreceived}{8}{true}{false}}
  deny
    message = 5.7.1 SPFBL $acl_c_spfbl
    log_message = SPFBL check blocked.
    condition = ${if eq {$acl_c_spfreceived}{10}{true}{false}}
    condition = ${if match {$acl_c_spfbl}{^BLOCKED https?://}{true}{false}}
  deny
    message = 5.7.1 SPFBL permanently blocked. See http://spfbl.net/en/feedback
    log_message = SPFBL check blocked.
    condition = ${if eq {$acl_c_spfreceived}{10}{true}{false}}
  deny
    message = 5.1.1 SPFBL the account that you tried to reach does not exist. See http://spfbl.net/en/feedback
    log_message = SPFBL check inexistent.
    condition = ${if eq {$acl_c_spfreceived}{19}{true}{false}}
  discard
    log_message = SPFBL check spamtrap.
    condition = ${if eq {$acl_c_spfreceived}{11}{true}{false}}
  defer
    message = 4.7.1 SPFBL greylisted message. See http://spfbl.net/en/feedback
    log_message = SPFBL check greylisting.
    condition = ${if eq {$acl_c_spfreceived}{12}{true}{false}}
  defer
    message = 4.3.1 SPFBL temporarily out of service. See http://spfbl.net/en/feedback
    log_message = SPFBL check timeout.
    condition = ${if eq {$acl_c_spfreceived}{9}{true}{false}}
  warn
    condition = ${if match {$acl_c_spfbl}{^(PASS |SOFTFAIL |NEUTRAL |NONE |FAIL |FLAG |WHITE |HOLD )}{true}{false}}
    set acl_c_spfblticket = ${sg{$acl_c_spfbl}{(PASS |SOFTFAIL |NEUTRAL |NONE |FAIL |FLAG |WHITE |HOLD )}{}}
  warn
    condition = ${if eq {$acl_c_spfreceived}{16}{true}{false}}
    set acl_c_spamflag = true
  warn
    condition = ${if eq {$acl_c_spfreceived}{18}{true}{false}}
    set acl_c_freeze = true
  warn
    condition = ${if eq {$acl_c_spfreceived}{20}{true}{false}}
    log_message = SPFBL out of service.
  warn
    condition = ${if eq {$acl_c_spfreceived}{20}{false}{true}}
    set acl_c_spfblticket = ${sg{$acl_c_spfblticket}{https?://.+/([0-9a-zA-Z_-]+)\\n}{\$1}}
  warn
    condition = ${if eq {$acl_c_spfreceived}{17}{true}{false}}
    set acl_c_whitelisted = true
  warn
    condition = ${if eq {$acl_c_spfreceived}{17}{true}{false}}
    domains = ${if exists{CONFDIR/domains_avoid_malware_check}\
                         {CONFDIR/domains_avoid_malware_check}\
                         {}}
    set acl_c_malware_check = false
  warn
    set acl_c_spfblticketset = $acl_c_spfblticket;$acl_c_spfblticketset
    set acl_c_spfblticketmap = $acl_c_spfblticketmap $local_part@$domain="$acl_c_spfbl"


  # Accept mail to postmaster in any local domain, regardless of the source,
  # and without verifying the sender.
  #
  accept
    condition = ${if eq {$acl_c_spfreceived}{20}{true}{false}}
    .ifndef CHECK_RCPT_POSTMASTER
    local_parts = postmaster
    .else
    local_parts = CHECK_RCPT_POSTMASTER
    .endif
    domains = +local_domains : +relay_to_domains : \
              ${if exists{CONFDIR/hubbed_hosts}\
                   {partial-lsearch;CONFDIR/hubbed_hosts}\
              fail}


  # Check against classic DNS "black" lists (DNSBLs) which list
  # sender IP addresses
  deny
    condition = ${if eq {$acl_c_spfreceived}{20}{true}{false}}
    dnslists = zen.spamhaus.org : b.barracudacentral.org : bogons.cymru.com
    message = $sender_host_address is listed at $dnslist_domain ($dnslist_value: $dnslist_text)


  # Use spfquery to perform a pair of SPF checks (for details, see
  # http://www.openspf.org/)
  #
  # This is quite costly in terms of DNS lookups (~6 lookups per mail).  Do not
  # enable if that's an issue.  Also note that if you enable this, you must
  # install "spf-tools-perl" which provides the spfquery command.
  # Missing spf-tools-perl will trigger the "Unexpected error in
  # SPF check" warning.
  deny
    condition = ${if eq {$acl_c_spfreceived}{20}{true}{false}}
    message = [SPF] $sender_host_address is not allowed to send mail from \
              ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}}.  \
              Please see \
              http://www.openspf.org/Why?scope=${if def:sender_address_domain \
              {mfrom}{helo}};identity=${if def:sender_address_domain \
              {$sender_address}{$sender_helo_name}};ip=$sender_host_address
    log_message = SPF check failed.
    !acl = acl_local_deny_exceptions
    condition = ${run{/usr/bin/spfquery.mail-spf-perl --ip \
                   ${quote:$sender_host_address} --identity \
                   ${if def:sender_address_domain \
                       {--scope mfrom  --identity ${quote:$sender_address}}\
                       {--scope helo --identity ${quote:$sender_helo_name}}}}\
                   {no}{${if eq {$runrc}{1}{yes}{no}}}}
  defer
    condition = ${if eq {$acl_c_spfreceived}{20}{true}{false}}
    message = Temporary DNS error while checking SPF record.  Try again later.
    !acl = acl_local_deny_exceptions
    condition = ${if eq {$runrc}{5}{yes}{no}}
  warn
    condition = ${if eq {$acl_c_spfreceived}{20}{true}{false}}
    condition = ${if <={$runrc}{6}{yes}{no}}
    add_header = Received-SPF: ${if eq {$runrc}{0}{pass}\
                                {${if eq {$runrc}{2}{softfail}\
                                {${if eq {$runrc}{3}{neutral}\
                                {${if eq {$runrc}{4}{permerror}\
                                {${if eq {$runrc}{6}{none}{error}}}}}}}}}\
                               } client-ip=$sender_host_address; \
                               ${if def:sender_address_domain \
                                {envelope-from=${sender_address}; }{}}\
                               helo=$sender_helo_name
  warn
    condition = ${if eq {$acl_c_spfreceived}{20}{true}{false}}
    log_message = Unexpected error in SPF check.
    condition = ${if >{$runrc}{6}{yes}{no}}


  # Check against DNSBLs which list sender domains, with an option to locally
  # whitelist certain domains that might be blacklisted.
  #
  # Note: If you define CHECK_RCPT_DOMAIN_DNSBLS, you must append
  # "/$sender_address_domain" after each domain.  For example:
  # CHECK_RCPT_DOMAIN_DNSBLS = rhsbl.foo.org/$sender_address_domain \
  #                            : rhsbl.bar.org/$sender_address_domain
  .ifdef CHECK_RCPT_DOMAIN_DNSBLS
  warn
    !senders = ${if exists{CONFDIR/local_domain_dnsbl_whitelist}\
                    {CONFDIR/local_domain_dnsbl_whitelist}\
                    {}}
    dnslists = CHECK_RCPT_DOMAIN_DNSBLS
    add_header = X-Warning: $sender_address_domain is listed at $dnslist_domain ($dnslist_value: $dnslist_text)
    log_message = $sender_address_domain is listed at $dnslist_domain ($dnslist_value: $dnslist_text)
  .endif


  # This hook allows you to hook in your own ACLs without having to
  # modify this file. If you do it like we suggest, you'll end up with
  # a small performance penalty since there is an additional file being
  # accessed. This doesn't happen if you leave the macro unset.
  .ifdef CHECK_RCPT_LOCAL_ACL_FILE
  .include CHECK_RCPT_LOCAL_ACL_FILE
  .endif


  #############################################################################
  # This check is commented out because it is recognized that not every
  # sysadmin will want to do it. If you enable it, the check performs
  # Client SMTP Authorization (csa) checks on the sending host. These checks
  # do DNS lookups for SRV records. The CSA proposal is currently (May 2005)
  # an Internet draft. You can, of course, add additional conditions to this
  # ACL statement to restrict the CSA checks to certain hosts only.
  #
  # require verify = csa
  #############################################################################


  # Accept if the address is in a domain for which we are an incoming relay,
  # but again, only if the recipient can be verified.

  accept
    domains = +relay_to_domains
    endpass
    verify = recipient


  # At this point, the address has passed all the checks that have been
  # configured, so we accept it unconditionally.

  accept


### acl/35_exim4-config_check_mime
#################################

# This access control list is used for every MIME part in an incoming
# SMTP message. The tests are run in order until the address is either
# accepted or denied.
#
acl_check_mime:

  # Accept if SPFBL ticket in undefined
  accept
    condition = ${if def:acl_c_spfblticketset {no}{yes}}


  # Decode MIME
  warn
    decode = $mime_filename


  # Reject HTML redirect
  deny
    message = 5.7.1 SPFBL the attachment has a HTML redirect command. See http://spfbl.net/en/feedback
    condition = ${if eq{$mime_content_type}{text/html}{true}{false}}
    mime_regex = <meta[^>]+http-equiv *= *"?refresh"?[^>]+>
    log_message = ${run{/usr/local/bin/spfbl malware "$acl_c_spfblticketset" "$mime_filename"}{SPFBL check redirect}{SPFBL ERROR: $value}}.
 

  # Reject JavaScript redirect
  deny
    message = 5.7.1 SPFBL the attachment has a JavaScript redirect command. See http://spfbl.net/en/feedback
    condition = ${if eq{$mime_content_type}{text/html}{true}{false}}
    mime_regex = <script[^>]+language *= *"?JavaScript"?[^>]+>
    mime_regex = window\\.location(\\.href *=|\\.replace\\()?
    log_message = ${run{/usr/local/bin/spfbl malware "$acl_c_spfblticketset" "$mime_filename"}{SPFBL check redirect}{SPFBL ERROR: $value}}.
 

  # Reject known executable file extensions.
  deny
    message = 5.7.1 SPFBL this message has executable attachment. See http://spfbl.net/en/feedback
    condition = ${if match {$mime_filename}{\\.(com|vbs|vbe|bat|pif|scr|prf|lnk|exe|shs|arj|hta|jar|ace|js)\$}{true}{false}}
    log_message = ${run{/usr/local/bin/spfbl malware "$acl_c_spfblticketset" "$mime_filename"}{SPFBL check executable}{SPFBL ERROR: $value}}.


  # Reject known executable file extensions inside compressed files.
  deny
    message = 5.7.1 SPFBL this message has executable attachment. See http://spfbl.net/en/feedback
    condition = ${run{/usr/local/bin/hasblackext2 "$mime_decoded_filename"}{false}{true}}
    log_message = ${run{/usr/local/bin/spfbl malware "$acl_c_spfblticketset" "$mime_filename"}{SPFBL check executable}{SPFBL ERROR: $value}}.
 

  # Check NFe XML
  warn
    log_message = SPFBL NFe found
    condition = ${if match {$mime_filename}{\\.xml\$}{true}{false}}
    condition = ${if match {${run{/usr/bin/xmllint --c14n "$mime_decoded_filename"}{$value}{}}}{\^<(nfeProc |cteProc |CompNfse)}{true}{false}}
    condition = ${if eq {${run{/usr/local/bin/spfbl white add $acl_c_spfblticket}{$runrc}{$runrc}}}{0}{true}{false}}
    set acl_c_whitelisted = true
    set acl_c_freeze = false


  # Check HTML href set
  warn
    set acl_c_mime_decoded_filename = null
  warn
    condition = ${if eq{$mime_content_type}{text/html}{true}{false}}
    set acl_c_mime_decoded_filename = $mime_decoded_filename
  warn
    condition = ${if eq{$mime_content_type}{text/plain}{true}{false}}
    condition = ${if < {$mime_content_size}{1m}{true}{false}}
    condition = ${if eq {${run{/usr/bin/txt2html --outfile "$mime_decoded_filename.html" "$mime_decoded_filename"}{$runrc}{$runrc}}}{0}{true}{false}}
    set acl_c_mime_decoded_filename = $mime_decoded_filename.html
  warn
    condition = ${if eq{$mime_content_type}{application/pdf}{true}{false}}
    condition = ${if < {$mime_content_size}{1m}{true}{false}}
    condition = ${if eq {${run{/usr/bin/pdftohtml -i -noframes "$mime_decoded_filename" "$mime_decoded_filename.html"}{$runrc}{$runrc}}}{0}{true}{false}}
    set acl_c_mime_decoded_filename = $mime_decoded_filename.html
  accept
    condition = ${if eq{$acl_c_mime_decoded_filename}{null}{true}{false}}
  warn
    condition = $acl_c_body_check
    set acl_c_body_check = ${if eq{$mime_content_type}{text/html}{false}{true}}
    set acl_c_body_file = $acl_c_mime_decoded_filename
{$acl_c_mime_decoded_filename}}
  warn
    set acl_c_hreflist = ${perl{geturldomainlist}}
    condition = ${if eq {${run{/usr/local/bin/spfbl link "$acl_c_spfblticketset" "$acl_c_hreflist"}{$runrc}{$runrc}}}{1}{true}{false}}
    log_message = SPFBL check blocklinked.
    set acl_c_blocklinked = true
  warn
    condition = ${if eq {$runrc}{5}{true}{false}}
    log_message = SPFBL check blacklinked.
    set acl_c_freeze = true
  warn
    condition = ${if eq {$runrc}{6}{true}{false}}
    log_message = SPFBL check blacklinked.
    set acl_c_spamflag = true


  # accept otherwise
  accept


### acl/40_exim4-config_check_data
#################################

# This ACL is used after the contents of a message have been received. This
# is the ACL in which you can test a message's headers or body, and in
# particular, this is where you can invoke external virus or spam scanners.

acl_check_data:

  # Deny unless the address list headers are syntactically correct.
  #
  # If you enable this, you might reject legitimate mail.
  .ifdef CHECK_DATA_VERIFY_HEADER_SYNTAX
  deny
    message = Message headers fail syntax check
    !acl = acl_local_deny_exceptions
    !verify = header_syntax
  .endif


  # require that there is a verifiable sender address in at least
  # one of the "Sender:", "Reply-To:", or "From:" header lines.
  .ifdef CHECK_DATA_VERIFY_HEADER_SENDER
  deny
    message = No verifiable sender address in message headers
    !acl = acl_local_deny_exceptions
    !verify = header_sender
  .endif


  # Complain message if sent to abuse account.
  discard
    condition = ${if eq {${lc:${address:$h_To:}}}{abuse@spfbl.net}{true}{false}}
    condition = ${if eq {${address:$h_From:}}{}{false}{true}}
    condition = ${if eq {${address:$h_From:}}{admin@spfbl.net}{false}{true}}
    condition = ${if eq {$h_In-Reply-To:}{}{false}{true}}
    condition = ${run{/usr/local/bin/spfbl abuse "In-Reply-To:$h_In-Reply-To:" "From:${address:$h_From:}"}{true}{false}}
    log_message = SPFBL abuse complain.


  # Accept messages from same network.
  warn
    log_message = SPFBL same network.
    condition = ${if eq {$acl_c_spfreceived}{15}{true}{false}}
  accept
    condition = ${if eq {$acl_c_spfreceived}{15}{true}{false}}


  # Deny if From or Reply-To is blocked in SPFBL.
  warn
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if eq {${run{/usr/local/bin/spfbl header \
                               '$acl_c_spfblticketset' \
                               'From:${address:$h_From:}' \
                               'Reply-To:${address:$h_Reply-To:}' \
                               'Message-ID:$h_Message-ID:' \
                               'Date:$h_Date:' \
                               'Subject:$h_Subject:' \
                               'List-Unsubscribe:${tr{$h_List-Unsubscribe:}{\n}{ }}'\
                          }{$runrc}{$runrc}}}{1}{true}{false}}
  deny
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if eq {$runrc}{1}{true}{false}}
    condition = ${if match {$value}{^BLOCKED https?://}{true}{false}}
    message = 5.7.1 SPFBL $value
    log_message = SPFBL check blocked.
  deny
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if eq {$runrc}{1}{true}{false}}
    message = 5.7.1 SPFBL blocked by unwanted content. See http://spfbl.net/en/feedback
    log_message = SPFBL check blocked.
  deny
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if eq {$runrc}{5}{true}{false}}
    message = 5.7.1 SPFBL rejected by suspect content. See http://spfbl.net/en/feedback
    log_message = SPFBL check reject.
  warn
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if eq {$runrc}{6}{true}{false}}
    set acl_c_whitelisted = false
    set acl_c_spamflag = true
    set acl_c_freeze = false
  warn
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if eq {$runrc}{7}{true}{false}}
    set acl_c_whitelisted = false
    set acl_c_spamflag = false
    set acl_c_freeze = true
  warn
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if eq {$runrc}{17}{true}{false}}
    set acl_c_whitelisted = true
    set acl_c_spamflag = false
    set acl_c_freeze = false


  # Accept messages from admin.
  accept
    condition = ${if def:acl_c_spfblticketset {$acl_c_whitelisted}{true}}
    condition = ${if eq {${address:$h_From:}}{admin@spfbl.net}{true}{false}}


  # Accept messages to abuse.
  accept
    condition = ${if eq {${lc:${address:$h_To:}}}{abuse@spfbl.net}{true}{false}}
    log_message = SPFBL abuse complain.


  # Deny if the message contains malware. Before enabling this check, you
  # must install a virus scanner and set the av_scanner option in the
  # main configuration.
  #
  # exim4-daemon-heavy must be used for this section to work.
  #
  deny
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if eq {$acl_c_spfreceived}{15}{$acl_c_malware_check}{true}}
    condition = ${if < {$message_size}{1m}{true}{false}}
    malware = *
    condition = ${if eq {${run{/usr/local/bin/spfbl malware \
                               '$acl_c_spfblticketset' \
                               '$malware_name'\
                          }{$runrc}{$runrc}}}{7}{false}{true}}
    message = 5.7.1 SPFBL this message was detected as possible malware. See http://spfbl.net/en/feedback
    log_message = SPFBL check malware.
  deny
    condition = ${if def:acl_c_spfblticketset {false}{true}}
    condition = ${if eq {$acl_c_spfreceived}{15}{$acl_c_malware_check}{true}}
    condition = ${if < {$message_size}{1m}{true}{false}}
    malware = *
    message = this message was detected as possible malware.
    log_message = malware.


  # Load body from HOLD messages at SPFBL.
  warn
    condition = $acl_c_freeze
    condition = ${if def:acl_c_spfblticketset {true}{false}}
    condition = ${if def:acl_c_body_file {true}{false}}
    condition = ${run{/usr/local/bin/spfbl body "$acl_c_spfblticketset" "$acl_c_body_file" "text/html"}{true}{false}}
    log_message = SPFBL body loaded


  # Add headers to a message if it is judged to be spam. Before enabling this,
  # you must install SpamAssassin. You also need to set the spamd_address
  # option in the main configuration.
  #
  # exim4-daemon-heavy must be used for this section to work.
  #
  # Please note that this is only suiteable as an example. There are
  # multiple issues with this configuration method. For example, if you go
  # this way, you'll give your spamassassin daemon write access to the
  # entire exim spool which might be a security issue in case of a
  # spamassassin exploit.
  #
  # See the exim docs and the exim wiki for more suitable examples.
  #
  # warn
  #   spam = Debian-exim:true
  #   add_header = X-Spam_score: $spam_score\n\
  #             X-Spam_score_int: $spam_score_int\n\
  #             X-Spam_bar: $spam_bar\n\
  #             X-Spam_report: $spam_report


  # This hook allows you to hook in your own ACLs without having to
  # modify this file. If you do it like we suggest, you'll end up with
  # a small performance penalty since there is an additional file being
  # accessed. This doesn't happen if you leave the macro unset.
  .ifdef CHECK_DATA_LOCAL_ACL_FILE
  .include CHECK_DATA_LOCAL_ACL_FILE
  .endif


  # accept otherwise
  warn
    authenticated = *
    condition = ${if eq {$h_In-Reply-To:}{}{false}{true}}
    log_message = ${run{/usr/local/bin/spfbl white sender "In-Reply-To:$h_In-Reply-To:"}{SPFBL white sender}{SPFBL $value}}.
  warn
    authenticated = *
    condition = ${if eq {$h_In-Reply-To:}{}{true}{false}}
    condition = ${if eq {${address:$h_To:}}{}{false}{true}}
    log_message = ${run{/usr/local/bin/spfbl white sender "${address:$h_To:}"}{SPFBL white sender}{SPFBL $value}}.
  accept
    authenticated = *
  accept
    condition = $acl_c_whitelisted
    add_header = X-Spam-Flag: NO
  accept
    condition = $acl_c_spamflag
    add_header = X-Spam-Flag: YES
  accept
    condition = $acl_c_freeze
    add_header = X-Spam-Flag: NO
    control = freeze/no_tell
  accept
    add_header = X-Spam-Flag: NO

A função "geturldomainlist" pode ser obtida dentro do arquivo "./run/exim.pl" deste projeto:

https://github.com/leonamp/SPFBL/blob/master/run/exim.pl

Basta copiar este arquivo na pasta /etc/exim/ e instalar o Perl e todas as dependências deste script:

apt-get install gcc make
cpan URI
cpan HTML::TreeBuilder
cpan Email::Valid
cpan Set::Scalar
cpan LWP::UserAgent
cpan HTTP::Request
cpan Data::Validate::URI

Certifique-se de que o arquivo /etc/exim4/conf.d/main/01_exim4-config_listmacrosdefs contenha a seguinte entrada:

perl_startup = do '/etc/exim4/exim.pl'

Para ativar a verificação do MIME, basta adicionar as seguintes linhas no arquivo /etc/exim4/conf.d/main/02_exim4-config_options:

# Defines the access control list that is run when an
# SMTP DATA command is received.
#
.ifndef MAIN_ACL_CHECK_MIME
MAIN_ACL_CHECK_MIME = acl_check_mime
.endif
acl_smtp_mime = MAIN_ACL_CHECK_MIME

Para ativar a verificação de antivírus, basta descomentar a seguinte linha do arquivo /etc/exim4/conf.d/main/02_exim4-config_options:

av_scanner = clamd:/var/run/clamav/clamd.ctl

Recomendamos a implementação do "clamav-unofficial-sigs" para tornar o Clamav mais efetivo:

https://github.com/extremeshok/clamav-unofficial-sigs

O script que procura por arquivos executáveis dentro de arquivos compactados pode ser obtido aqui:

https://github.com/leonamp/SPFBL/blob/master/run/hasblackext

Para converter os anexos de PDF em HTML, para verificação dos links internos do PDF, é necessário utilizar o pdftohtml:

apt-get install pdftohtml

Para verificar existência de NFe como anexo, é necessário utilizar o xmllint:

apt-get install libxml2-utils

Para que o Exim faça o roteamento para a pasta ".Junk" do destinatário, é necessário fazer uma pequena alteração no "directory" do transporte "maildir_home" da seção "transports":

begin transports
...
maildir_home:
  ...
  directory = $home/Maildir${if eq {$h_X-Spam-Flag:}{YES}{/.Junk}{}}
  ...

Se estiver usando a função HOLD do SPFBL, coloque esta linha no crontab para o MTA saber se deve descongelar a mensagem ou remover da fila:

*/10    * * * *         sudo spfbl holding > /dev/null
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.