A.7. 添加 SPF 检查

这里我们介绍两种不同的方法来使用 Exim 检查 Sender Policy Framework 记录。除了这些显式机制之外,SpamAssassin 套件将在不久的将来(大约 2.70 版本)纳入更复杂的 SPF 检查,通过为各种 SPF 结果分配加权分数。

虽然我们可以acl_mail_from ACL 中尽早执行此检查,但有一个问题会影响此决定:SPF 与传统的电子邮件转发不兼容。除非转发主机实施 SRS,否则您最终可能会拒绝转发的邮件,因为您从一个未被授权的主机接收邮件,根据 Envelope Sender 地址的域名的 SPF 策略。

为了避免这种情况,我们需要查阅一个用户特定的主机列表,从中应该接受转发的邮件(如 豁免转发邮件 中所述,将在后面介绍)。这只有在 RCPT TO: 之后才有可能,当我们知道收件人的用户名时。

因此,我们将在任何灰名单检查和/或最终的accept语句之前,在 acl_rcpt_to 中添加此检查。

A.7.1. 通过 Exiscan-ACL 进行 SPF 检查

Tom Kistner 的最新版本Exiscan-ACL补丁(参见 先决条件)具有对 SPF 的原生支持。[1] 用法非常简单。一个spfACL 条件被添加,并且可以与任何关键词进行比较pass, fail, softfail, none, neutral, err_permorerr_temp.

在任何灰名单检查和/或最终的accept语句之前,在 acl_rcpt_to 中,插入以下代码片段

  # Query the SPF information for the sender address domain, if any,
  # to see if the sending host is authorized to deliver its mail.
  # If not, reject the mail.
  #
  deny
    message     = [SPF] $sender_host_address is not allowed to send mail \
                  from $sender_address_domain
    log_message = SPF check failed.
    spf         = fail


  # Add a SPF-Received: header to the message
  warn
    message     = $spf_received

如果发件人地址的域名的所有者不允许从调用主机发送邮件,则此语句将拒绝邮件。有些人认为这给了域名所有者过多的控制权,甚至到了搬起石头砸自己的脚的地步。一个建议的替代方案是将 SPF 检查与其他检查结合起来,例如发件人呼叫验证(但请注意,与之前一样,如果您通过智能主机发送您的外发邮件,则这样做毫无意义)

  # Reject the mail if we cannot verify the sender address via callouts,
  # and if SPF information for the sending domain does not grant explicit
  # authority to the sending host.
  #
  deny
    message     = The sender address does not seem to be valid, and SPF \
                  information does not grant $sender_host_address explicit \
                  authority to send mail from $sender_address_domain
    log_message = SPF check failed.
    !verify     = sender/callout,random,postmaster
    !spf        = pass


  # Add a SPF-Received: header to the message
  warn
    message     = $spf_received

A.7.2. 通过 Mail::SPF::Query 进行 SPF 检查

Mail::SPF::Query是官方的 SPF 测试套件,可从 http://spf.pobox.com/downloads.html 下载。Debian 用户,安装libmail-spf-query-perl.

Mail::SPF::Query软件包附带一个守护进程 (spfd),它监听 UNIX 域套接字上的请求。不幸的是,它没有附带 "init" 脚本来自动启动此守护进程。因此,在以下示例中,我们将使用独立的 spfquery 实用程序来发出我们的 SPF 请求。

如上所述,在任何灰名单检查和/或最终的accept语句之前,在 acl_rcpt_to 中插入以下代码

  # Use "spfquery" to obtain SPF status for this particular sender/host.
  # If the return code of that command is 1, this is an unauthorized sender.
  #
  deny
    message     = [SPF] $sender_host_address is not allowed to send mail \
                  from $sender_address_domain.
    log_message = SPF check failed.
    set acl_m9  = -ipv4=$sender_host_address \
                  -sender=$sender_address \
                  -helo=$sender_helo_name
    set acl_m9  = ${run{/usr/bin/spfquery $acl_m9}}
    condition   = ${if eq {$runrc}{1}{true}{false}}

注释

[1]

Debian 用户:截至 2004 年 7 月 14 日,包含在exim4-daemon-heavy软件包中的 Exiscan-ACL 版本尚不支持 SPF。在此期间,您可以选择其他 SPF 实现;安装libmail-spf-query-perl.