2.3. SMTP 检查

一旦 SMTP 对话开始,您可以对远程主机提供的命令和参数执行各种检查。例如,您需要确保 Hello 问候语中提供的名称是有效的。

然而,即使您决定在 SMTP 事务的早期拒绝传递尝试,您也可能不想立即执行实际的拒绝。相反,您可以使用 SMTP 事务延迟来拖延发送者,直到 RCPT TO: 之后,然后在此时拒绝邮件。

原因是某些恶意软件不理解 SMTP 事务早期的拒绝;它们会不断尝试。另一方面,如果 RCPT TO: 失败,它们中的大多数会放弃。

此外,这还提供了一个很好的机会来进行一些 延迟拒绝

2.3.1. Hello (HELO/EHLO) 检查

根据 RFC 2821,客户端发出的第一个 SMTP 命令应该是 EHLO(如果不支持,则为 HELO),后跟其主要的 完全限定域名。这被称为 Hello 问候语。如果没有有意义的 FQDN 可用,客户端可以提供用方括号括起来的 IP 地址:“[1.2.3.4]”。最后一种形式被称为 IPv4 地址“字面量”表示法。

可以理解的是,恶意软件 很少在 Hello 问候语中呈现自己的 FQDN。相反,来自恶意软件的问候语通常试图隐藏发送主机的身份,和/或在邮件头中生成混乱和/或误导性的“Received:” 踪迹。此类问候语的一些示例包括

2.3.1.1. 简单的 HELO/EHLO 语法检查

其中一些违反 RFC 2821 的行为既容易检查,又清楚地表明发送主机正在运行某种形式的 恶意软件。您可以拒绝此类问候语——可以直接拒绝,也可以在例如 RCPT TO: 命令之后拒绝。

首先,可以随意拒绝 Hello 问候语中的纯 IP 地址。即使您希望慷慨地允许 RFC 2821 授权、推荐和建议的所有内容,您也会注意到,当使用 IP 地址代替名称时,IP 地址应始终用方括号括起来。[1]

特别是,您可能希望向使用您的 IP 地址(或就此而言,您的主机名)介绍自己的主机发出措辞强烈的拒绝消息。它们显然在撒谎。也许您想使用非常长的 SMTP 事务延迟来拖延发送者以响应这样的问候语;例如,几个小时。

就此而言,我自己的经验表明,互联网上没有合法的站点使用 IP 地址字面量([x.y.z.w] 表示法)向其他互联网站点介绍自己。他们也不应该这样做;所有直接在互联网上发送邮件的主机都应该使用其有效的 完全限定域名。我遇到的唯一使用 IP 字面量的情况来自我本地局域网上的邮件用户代理,例如 Ximian Evolution,配置为使用我的服务器作为外发 SMTP 服务器(智能主机)。实际上,我只接受来自我自己的 LAN 的字面量。

您可能也可能希望拒绝不合格的主机名(没有句点的主机名)。我发现这些很少(但并非从不 - 这种双重否定怎么样)是合法的。

同样,您可以拒绝包含无效字符的主机名。对于互联网域名,只有字母数字字符和连字符是有效字符;连字符不允许作为第一个字符。(您可能还想考虑下划线是一个有效字符,因为从配置错误但最终善意的 Windows 客户端中看到这种情况非常常见)。

最后,如果您收到 MAIL FROM: 命令而没有首先收到 Hello 问候语,那么,有礼貌的人会先问候。

在我的服务器上,我拒绝未能通过任何这些语法检查的问候语。但是,拒绝实际上不会在 RCPT TO: 命令之后才发生。与此同时,我在每个 SMTP 命令(HELO/EHLOMAIL FROM:RCPT TO:)之后强制执行 20 秒的事务延迟。

2.3.1.2. 通过 DNS 验证 Hello 问候语

能够到达这一步的主机至少呈现了一个表面上可信的问候语。现在是时候通过 DNS 验证提供的名称了。您可以

  • 对提供的名称执行正向查找,并将结果与对等方的 IP 地址进行匹配

  • 对等方的 IP 地址执行反向查找,并将其与问候语中提供的名称进行匹配。

如果这两个检查中的任何一个成功,则名称已得到验证。

您的 MTA 可能具有执行此检查的内置选项。例如,在 Exim(参见 附录 A)中,您需要设置“helo_try_verify_hosts = *”,并创建基于“verify = helo”条件采取操作的 ACL。

与简单的语法检查相比,此检查在处理时间和网络资源方面成本更高。此外,与语法检查不同,不匹配并不总是表明是恶意软件;一些大型互联网站点,例如 hotmail.com、yahoo.com 和 amazon.com,经常呈现无法验证的 Hello 问候语。

在我的服务器上,如果我没有因为之前的检查而使用事务延迟来拖延发送者,我会对 Hello 问候语进行 DNS 验证。然后,如果此检查失败,我将从此时起对每个 SMTP 命令施加 20 秒的延迟。我还准备了一个 “X-HELO-Warning:” 标头,稍后我将其添加到邮件中,并用于增加 SpamAssassin 分数,以便在收到邮件数据后可能拒绝邮件。

2.3.2. 发件人地址检查

在客户端呈现 MAIL FROM: <地址> 命令后,您可以按如下方式验证提供的 信封发件人 地址。[2]

2.3.2.1. 发件人地址语法检查

提供的地址是否符合 <本地部分@域名> 格式?域名部分是否是语法上有效的 完全限定域名

通常,您的 MTA 默认执行这些检查。

2.3.2.2. 冒名顶替者检查

如果您和您的用户仅通过少数选定的服务器发送所有外发邮件,则可以拒绝来自其他主机的邮件,其中发件人地址的 “域名” 是您自己的域名。

此检查更通用的替代方案是 发件人策略框架

2.3.2.3. 简单的发件人地址验证

如果地址是本地地址,则 “本地部分”(@ 符号之前的部分)是否是您系统上的有效邮箱?

如果地址是远程地址,则 “域名”(@ 符号之后的部分)是否存在?

2.3.2.4. 发件人回拨验证

这是某些 MTA(如 Exim 和 Postfix)提供的机制,用于验证远程发件人地址的 “本地部分”。在 Postfix 术语中,它被称为 “发件人地址验证”

您的服务器联系发件人地址中提供的域名的 MX,尝试启动辅助 SMTP 事务,就像向该地址传递邮件一样。它实际上不发送任何邮件;相反,一旦远程主机接受或拒绝了 RCPT TO: 命令,您的服务器就会发送 QUIT

默认情况下,Exim 对此类回拨验证使用空信封发件人地址。目的是确定如果将 传递状态通知 返回给发件人是否会被接受。

另一方面,Postfix 默认为发件人地址 <postmaster@域名> 用于地址验证目的(域名取自$myorigin变量)。因此,您可能希望以与处理 NULL 信封发件人相同的方式处理此发件人地址(例如,避免 SMTP 事务延迟灰名单,但要求收件人地址中包含 信封发件人签名)。有关此内容的更多信息,请参见实现附录。

您可能会发现,仅此检查可能不适合作为拒绝传入邮件的触发器。有时,来自自动化服务的合法邮件(例如定期账单)是从无效的退回地址发送的。此外,垃圾邮件的一个不幸的副作用是,一些用户倾向于篡改其外发邮件中的退回地址(尽管这可能更常影响邮件本身中的 “From:” 标头,而不是 信封发件人)。

此外,此检查仅验证地址是否有效,而不是验证该地址是否是此特定邮件的真实发件人(但另请参见 信封发件人签名)。

最后,有报告称某些站点(例如 “aol.com”)会无条件地将它们发现发送发件人回拨请求的任何系统列入黑名单。这些站点可能是 乔工作 的频繁受害者,因此会收到大量发件人回拨请求。通过参与这些 DDoS(分布式拒绝服务)攻击,您实际上已将自己变成垃圾邮件发送者的棋子。

2.3.3. 收件人地址检查

您可能会说,这应该很简单。收件人地址要么有效(在这种情况下,邮件被传递),要么无效(在这种情况下,您的 MTA 默认会处理拒绝)。

让我们看一下,好吗?

2.3.3.1. 防止开放中继

不要将来自远程主机的邮件中继到远程地址!(除非发件人已通过身份验证)。

对于我们大多数人来说,这似乎是显而易见的,但显然这是一个经常被忽视的考虑因素。此外,并非每个人都完全掌握与电子邮件地址和传递路径相关的各种互联网标准(考虑 “百分号黑客域名”“感叹号 (!) 路径” 等)。

如果您不确定您的 MTA 是否充当 开放中继,您可以通过 “relay-test.mail-abuse.org” 对其进行测试。在服务器的 shell 提示符下,键入

telnet relay-test.mail-abuse.org

这是一项服务,它将使用各种测试来查看您的 SMTP 服务器是否似乎将邮件转发到远程电子邮件地址,和/或任何数量的地址 “黑客”,例如上面提到的那些。

防止您的服务器充当开放中继非常重要。如果您的服务器是开放中继,并且垃圾邮件发送者找到了您,您将立即被列入许多 DNS 黑名单。如果某些其他 DNS 黑名单的维护者找到了您(通过探测和/或根据投诉采取行动),您将被列入这些黑名单很长一段时间。

2.3.3.2. 收件人地址查找

对于我们大多数人来说,这似乎也很平庸。但事实并非总是如此。

如果用户的邮件帐户和邮箱直接存储在您的传入邮件交换器上,您可以简单地检查收件人地址的 “本地部分” 是否与有效的邮箱对应。这里没有问题。

在以下两种情况下,收件人地址的验证更加繁琐

  • 如果您的机器是收件人域的备份 MX。

  • 如果您的机器将您域的所有邮件转发到另一台(可能是内部)服务器。

收件人地址验证的替代方案是接受这些各自域内的所有收件人地址,这反过来意味着您或目标服务器可能必须为后来证明无效的收件人地址生成 传递状态通知。最终,这意味着您将生成附带垃圾邮件。

考虑到这一点,让我们看看如何在上面列出的场景中验证收件人。

2.3.3.2.1. 收件人回拨验证

这是某些 MTA(如 Exim 和 Postfix)提供的机制,用于验证远程收件人地址的 “本地部分”(有关其工作原理的描述,请参见发件人回拨验证)。在 Postfix 术语中,这称为 “收件人地址验证”

在这种情况下,服务器尝试联系最终目标主机,以在您反过来接受来自对等方的 RCPT TO: 命令之前验证每个收件人地址。

此解决方案简单而优雅。它适用于可能在最终目标主机上运行的任何 MTA,并且无需访问任何特定的目录服务。此外,如果该 MTA 碰巧对收件人地址执行模糊匹配(Lotus Domino 服务器就是这种情况),则此检查将准确反映收件人地址最终是否会被接受 - 这对于下面描述的机制可能并非如此。

请务必保留原始 信封发件人 以进行收件人回拨,否则来自目标主机的响应可能不准确。例如,如 仅接受真实用户的退回邮件 中所述,它可能会拒绝系统用户和别名的退回邮件(即没有信封发件人的邮件)。

在主要的 MTA 中,Exim 和 Postfix 都支持此机制。

2.3.3.2.2. 目录服务

另一个好的解决方案是目录服务(例如,一个或多个 LDAP 服务器),您的 MTA 可以查询该服务。最常见的 MTA 都支持 LDAP、NIS 和/或通常用于提供用户帐户信息的各种其他后端。

主要的症结在于,除非电子邮件的最终目标主机已经使用此类目录服务将用户名映射到邮箱,否则可能需要进行一些设置工作。

2.3.3.2.3. 复制的邮箱列表

如果以上选项都不可行,您可以退回到 “简易目录服务”,您将在其中定期将邮箱的当前列表从它们所在的机器复制到您的 MX 主机。然后,您的 MTA 将查阅此列表以验证传入邮件中的 RCPT TO: 命令。

如果托管您的邮箱的机器运行在某种 UNIX 或 Linux 版本上,您可以编写一个脚本来首先生成此类列表,可能从本地 “/etc/passwd” 文件中生成,然后使用 OpenSSH 套件中的 “scp” 命令将其复制到您的 MX 主机。然后,您可以设置一个 “cron” 作业(键入 man cron 以获取详细信息)来定期运行此脚本。

2.3.3.3. 防止字典攻击

字典攻击 是一个术语,用于描述 SMTP 事务,其中发送主机不断发出 RCPT TO: 命令,以探测基于常用名称(通常以 “aaron” 开头按字母顺序排列,但有时从字母表的后面开始,和/或随机开始)的可能收件人地址。如果您的服务器接受特定地址,则该地址将被添加到垃圾邮件发送者的武器库中。

一些站点,尤其是较大的站点,发现它们是此类攻击的频繁目标。从垃圾邮件发送者的角度来看,在大型站点上找到给定用户名的机会比在只有少数用户的站点上更好。

对抗字典攻击的一种有效方法是为每个失败的地址发出越来越多的事务延迟。例如,第一个不存在的收件人地址可以以 20 秒的延迟拒绝,第二个地址以 30 秒的延迟拒绝,依此类推。

2.3.3.4. 仅接受 DSN 的一个收件人

合法的 传递状态通知 应仅发送给一个收件人地址 - 触发通知的原始邮件的始发者。如果 信封发件人 地址为空,但有多个收件人,您可以断开连接。

注释

[1]

尽管此检查通常非常有效地清除垃圾邮件,但有报告称,有缺陷的 L-Soft listserv 安装使用列表服务器的纯 IP 地址进行问候。

[2]

一个特殊情况是 传递状态通知 和其他自动生成的响应中使用的 NULL 信封发件人地址(即 MAIL FROM: <>)。此地址应始终被接受。