Postfix 规限
<<TableOfContents: execution failed [Argument "maxdepth" must be an integer value, not "[1]"] (see also the log)>>
敬请注意: |
注意:本文档是为 CentOS 5 而撰写的。它的内容对 CentOS 6 或较后版本也许并不准确。 |
1. 引言
假如你遵从基本的 postfix 指南,你便能创建一台简单的 postfix 邮件服务器发放及接收电邮。不过,你多数已经发现这台 postfix 邮件服务器会接收所有电邮,连同垃圾邮件也亳无保留地接受。据估计,互联网上发放的所有电邮当中,超过 80% 的电邮是垃圾邮件,又名为「未经同意的大量电邮(UBE)」或「未经同意的大量电邮(UCE)」,因此它们对任何一位邮件管理员来说都是个重大的挑战。本指南将会以独立单元的方式查看 postfix 所提供、用来对付垃圾邮件的一些规限,让读者能够在基本的 postfix 指南之上按首选来加插它们。
2. Postfix 与垃圾邮件
互联网主要建基在信任这个原则之上,而 UBE 正是滥用这份信任来发放大量的垃圾邮件。当我们把任何形式的规限加诸在电邮时,我们便偏离了信任的原则,也会冒着规限或阻塞合法电邮的风险。故此我们所实施的规限必须保守,并且要彻底地测试及监视它们。你的用户会感激你限制垃圾邮件的数量,但他们不会因为阻塞了合法的电邮来多谢你。
我们会利用 3 种 postfix 规限类型来查看连接到邮件服务器的客户端所提供的信息:
- smtpd_helo_restrictions
- smtpd_sender_restrictions
- smtpd_recipient_restrictions
庆幸地,很多垃圾邮件发放者懒得严格地遵从 RFC 指引,所以我们能够通过以上的规限类型来辨认显而易见的垃圾邮件,并且在它们进入邮件服务器前拒绝它们。在垃圾邮件进入服务器前拒绝它们不但能够减省带宽,更可以减除邮件服务器进一步处理它们所须的资源。
规限的运作方式是通过处理一堆规则来决定 postfix 对每封邮件所要采取的行动。可能的结果包括 OK(没有问题)、REJECT(拒绝)或 DUNNO(不知道)。规限是按它们的排列次序来运算的。只要有一条规则返回 REJECT,该邮件便会立即被拒绝和不再被处理。假若有一条规则返回 OK,同类的规则便不会再被运算,而下一组的规则会开始被运算,直至该邮件成功地通过全部规则类型或被其其中一条规则所拒绝。所有,举个例说,某邮件可能从 smtpd_sender_restriction 取得 OK,但依然可以被其后的 smtpd_recipient_restriction 规则所拒绝。因此,我们须要给予我们的规限规则详细考虑。如果一个邮件并未被任何规则所拒绝,缺省的政策是接纳该邮件。
要更清楚理解各种规限类型及它们如何被运用,让我们 telnet 进入我们的邮件服务器和寄一封电邮给自己,并更深入地查看 smtp 的运作:
telnet 192.168.0.2 25 # Comments Trying 192.168.0.2... Connected to 192.168.0.2 (192.168.0.2). Escape character is '^]'. 220 mail.example.com ESMTP Postfix # <-smtp_client_restrictions HELO mail.example.com # <-smtp_helo_restrictions 250 mail.example.com # MAIL FROM:<ned@example.com> # <-smtp_sender_restrictions 250 2.1.0 Ok # RCPT TO:<ned@example.com> # <-smtp_recipient_restrictions 250 2.1.5 Ok # DATA # <-smtp_data_restrictions 354 End data with <CR><LF>.<CR><LF> # To:<ned@example.com> # <-header_checks From:<ned@example.com> # Subject:SMTP Test # This is a test message # <-body_checks . # 250 2.0.0 Ok: queued as 301AE20034 QUIT 221 2.0.0 Bye Connection closed by foreign host.
smtpd 的 helo、sender 及 recipient 规限的主要优点就是它们在电邮的上下文被发放/接收之先已经可以被运算,因此潜在的垃圾邮件可以在 smtp 进程的早段被拒绝,而不必占用额外带宽及/或处理器的资源。让我们一起看某些规限的实例来明白它们的用途。所有规限都被加进 /etc/postfix/main.cf 这个 postfix 主分配文件。
3. 客端身份规限
当一台客端系统连接到我们的邮件服务器时,它必须利用 HELO 指令来辨明身份。很多垃圾电邮发放者会尝试跳过这一步、传送不合理的错误数据、或者刻意地混淆身份来夺得访问权。无论如何,我们可以安全地拒绝那些设置上有严重错误或刻意地混淆身份的客户端。
# /etc/postfix/main.cf # HELO 规限: smtpd_delay_reject = yes smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks, reject_non_fqdn_helo_hostname, reject_invalid_helo_hostname, permit
注: Postfix 2.2(CentOS 4)分别采用 reject_non_fqdn_hostname 及 reject_invalid_hostname。
第一行(smtpd_delay_reject)容许 smtp 继续进行对话直至接收上下文时才拒绝它,这个用意是要让我们能记录完整的寄件者及收件者数据。这亦是采用 helo_restrictions 的一个先决条件。第二行(smtpd_helo_required)拒绝来自不能辨明身份的系统的邮件。
我们的 smtpd_helo_restrictions 在第三行开始。permit_mynetworks 告诉 postfix 接纳来自获信任、定义在 mynetworks 中的机器,这样来自我们信任的客户端的电邮便不须再通过其它 helo 规限的检查。如果 HELO 指令所提供的主机名称并非如 RFC 指引所要求的完整域名,reject_non_fqdn_helo_hostname 将会拒绝那些连接。拒绝那些不愿正确地辨认自己的客户端的连接请求是绝对安全的。同样道理,要是 HELO 的主机名称语法不正确,reject_invalid_helo_hostname 将会拒绝那些连接请求。最后我们容许邮件接受进一步的过滤。
还有一个不时会采用的高级选项就是 reject_unknown_helo_hostname,它拒绝的邮件就是那些不能以 helo 指令提供拥有 DNS A 或 MX 记录的主机名称。然而这个设置必须小心使用,因为它会拒绝那些来自合法、但暂时遇上 DNS 问题的系统的邮件,导致误报出现。
4. 寄件者规限
下一步就是通过寄件者规限来过滤不合法的寄件者:
# /etc/postfix/main.cf # 寄件者规限: smtpd_sender_restrictions = permit_mynetworks, reject_non_fqdn_sender, reject_unknown_sender_domain, permit
同样地,我们首先容许来自我们的网络的寄件者(permit_mynetworks)。接下来的两行拒绝那些寄件者电邮地址不整全或不存在的邮件,因为没有实在理由要接纳他们的邮件。reject_non_fqdn_sender 会按 RFC 的要求拒绝那些 MAIL FROM 地址并非完整域名的电邮。reject_unknown_sender_domain 会拒绝那些没有 DNS A 或 MX 记录的 MAIL FROM 地址,与及拥有异常 MX 记录的地址,例如记录内含有零长度的 MX 主机名称。reject_unknown_sender_domain 的回复码是 450(稍后再试),用来应付暂时性的 DNS 问题。此外,由于 MAIL FROM 是退回邮件的地址,接收来自不明网域的邮件是不合情理的。最尾一行容许邮件接受下阶段的过滤。
5. 收件者规限
到此刻,我们可以确定客端机器并非胡乱设置,而寄件者至少有机会是合法的。最后的步骤就是查看客户端是否有权限发放到指定的收件者,并且套用一些外置、非 postfix 的检查在所剩无几、能达至这个步骤的邮件。
# /etc/postfix/main.cf # 收件者规限: smtpd_recipient_restrictions = reject_unauth_pipelining, reject_non_fqdn_recipient, reject_unknown_recipient_domain, permit_mynetworks, reject_unauth_destination, check_sender_access hash:/etc/postfix/sender_access, reject_rbl_client zen.spamhaus.org, reject_rbl_client bl.spamcop.net, check_policy_service unix:postgrey/socket, permit
postfix 支持一个名为流水线的技术,通过同时发出多个 smtp 指令来加快传递大量的电邮。这个协议要求客户端先检查服务器是否支持流水线。很多垃圾邮件的寄件者为要尽快发送他们的邮件,会不等候批准便发出一连串的指令。reject_unauth_pipelining 阻止那些进行大量邮寄的软件滥用流水线来加快发送电邮。
接下来的数行应该有点面善,用来拒绝送往不存在或不可能存在网域的邮件。首先我们按 RFC 的要求拒绝那些 RCPT TO 地址不是完整域名的邮件(reject_non_fqdn_recipient),然后假如我们邮件服务器并非收件者的终极目的地、RCPT TO 地址没有 DNS A 或 MX 记录、又或者 MX 记录异常,邮件都会被拒绝。reject_unknown_recipient_domain 的回复码是 450(稍后再试),用来应付暂时性的 DNS 问题。同样地,permit_mynetworks 告诉 postfix 接纳我们网络上的本地用户连接。
接着那行,reject_unauth_destination,是极之重要的,因为它告诉 postfix 假如邮件的收件网域并非由本地管理,而我们又不是该网域的后备服务器,但不要接纳这些邮件。没有这一行,我们的服务器便会成为一个公开的转发站。
下一个设置,check_sender_access,让我们可以利用 MAIL FROM 栏的完整或部份电邮地址及网域来实践白名单及黑名单,通过对照一个访问列表来返回 OK 或 REJECT 值。首先我们必须创建这个对照表,在本样例中它是 /etc/postfix/sender_access 这个纯文本档:
# /etc/postfix/sender_access # # 配对 MAIL FROM 栏内的寄件者用的黑/白名单。样例…… # myfriend@example.com OK junk@spam.com REJECT marketing@ REJECT theboss@ OK deals.marketing.com REJECT somedomain.com OK
我们从上面样例会看见邮件可以根据 MAIL FROM 栏内的完整电邮地止、任何网域的用户名称、网域或局部网域来放进黑名单或白名单。请留意这些都只是例子,而普遍来说你不应该将自己的网域放进白名单内,因为垃圾邮件寄件者多数会把寄件人地址改为你的网域。创建了 sender_access 档后,你必须执行 postmap 这个指令在它之上来创建一个供 postfix 采用的索引版本(你也须在每次更改该文件后重复这步骤):
postmap /etc/postfix/sender_access
这是我们的最后一个 postfix 内置检查。馀下来的检查会查询外置来源或工具程序。
接着我们会进行一些实时的黑名单(RBL)检查。RBL,又名为 DNS 黑名单(DNSBL),是一个由第三方提供 IP 地址列表的服务,而这些 IP 正进行某类型非法活动,例如:发放垃圾邮件或病毒等不良内容。reject_rbl_client 这行会导致 postfix 利用所枚举的数据库进行检查,并拒绝那些来不良源头的电邮。由于这些检查涉及一个 DNS 对照,论资源它们是相对地「昂贵」,因此最好把它们放在检查的结尾,通过事先去除多数的垃圾邮件来减低它们发生的次数。同样地,我们顺理成章地把先枚举最有效的数据库,旨在减省拒绝一封(垃圾)邮件所需的对照次数。
网上有很多 DNSBL,你选用的数量及供应者亦适随尊便,但你应该定时查看你的日志来复核它们的効率(提示:安装 postfix-pflogsumm 这个组件并使用 pflogsumm 这个指令来分析你的 postfix 日志)。请留意采用 DNSBL 会引入误报的可能性,因为我们依赖列表维护者加入不法地址的政策。有些効率十分高、有些做不了什么、有些拒绝合法邮件的数量与垃圾邮件同样多。读者可参详 http://stats.dnsbl.com/ 取得更多数据及各 DNSBL 的即时数据。
最后一个检查,check_policy_service,是用来执行一个附加的应用程序或脚本,这个例子采用了连结到 unix 通讯端的 postgrey。postgrey 可以高效率地清除垃圾邮件,而且有份独立的指南专门关于 postgrey 在 postfix 邮件服务器上的安装。我们极力鼓励读者接着便阅读该指南。
6. 总结
在这份指南里我们看见如何用 postfix 的规限来拒绝电邮来自明显设置上错误的客户端,及那些没理由发放电邮到我们服务器的人。我们刻意地实施保守的规限,目的为要防止误报及确保能在任何 postfix 安装下应用。postfix 的规限,尤其是拒绝没有完整域名的 helo 主机名称,能拦截多达 30% 的垃圾邮件,而利用 1 至 2 个优良的 DNSBL 能拦截剩下的垃圾邮件的 90% 或以上。再配合 greylisting 等过滤技术,理论上绝大部份(~99%)的垃圾邮件都可以在进入邮件服务器之先被过滤掉,从而节省带宽及处理的资源。这份指南旨在补充基本的 postfix 指南。
7. 鸣谢
本篇文章的灵感及内容源自 Kirk Strauser 在 http://www.freesoftwaremagazine.com/articles/focus_spam_postfix 以「相同方式共享 2.5 通用版」刊登的杰出指南
……
Translation of revision 29