服务器 频道

Postfix反垃圾邮件技术

  【IT168 服务器学院】MTA的反垃圾邮件功能,实际上就是在MTA处理过程中对会话进行过滤。这个过滤不但过滤了发往自身的垃圾邮件,而且还防止了自身被恶意利用发送垃圾邮件。Postfix实现了目前所有主要的MTA过滤技术。。

  MTA过滤分为两类:邮件数据发送前过滤和邮件数据发送后过滤。

  一、数据前过滤

  数据前过滤是指在SMTP会话中,DATA指令发送前进行的过滤。在这个阶段,有四种不同子阶段的过滤:SMTP连接时过滤、HELO/EHLO指令过滤、MAIL FROM指令过滤和RCPT TO指令过滤。根据这四个子阶段接收到的信息的不同,它们也分别称作SMTP客户端限制、HELO/EHLO主机名限制、发送者地址限制和接收者地址限制。

  过滤默认是在RCPT TO指令后生效的,这是因为一些Windows上的邮件客户端不处理在RCPT TO指令前的过滤动作。可以通过将smtpd_delay_reject设置为no来使过滤动作立刻生效。这个参数还影响了在不同的指令上可以使用的过滤规则参数。

  1、过滤规则

  这四个子阶段的过滤是分别通过四个配置语句来指定过滤规则的。它们都接收一系列的规则参数列表,参数间可以用空格或逗号分隔开。在默认状态下smtpd_delay_reject的值是yes,它们可以接受所有支持的规则,不过需在RCPT TO指令后才能全部生效;如果把smtpd_delay_reject设置为no,它们只可以接受五个公共的规则参数、之前子阶段的过滤规则参数和该子阶段的规则参数。

  它们接受的公共的规则参数如下:

  permit

  允许该连接进行。该规则通常置于规则列表的最后面使规则更清晰。

  defer

  通知客户端现在不能继续会话,稍后再进行SMTP连接请求。这常用于服务器需要进行一些DNS检查,但是(由于DNS查询超时)没有及时获得结果时,通知客户端稍后再进行连接。该规则通常置于规则列表的最后面使规则更清晰。

  reject

  拒绝该连接请求。在这个阶段就断开了连接,有效的节约了垃圾邮件造成的带宽和处理能力的浪费。该规则通常置于规则列表的最后面使规则更清晰。

  拒绝动作默认不会在匹配了拒绝规则后就立刻断开连接,而是在rcpt to指令处理完之后再断开的,这是由于一些windows上有缺陷的邮件程序不处理在rcpt to指令前的发回的拒绝状态码。可以通过smtpd_delay_reject设置为no来立刻发送拒绝状态码断开连接。

  reject_code指定了拒绝的返回状态码(默认是554)。

  warn_if_reject

  改变其后规则的拒绝动作为警告,即如果其后存在满足拒绝的条件,并不实际拒绝,而是发出一条警告信息(reject_warning)到日志文件中(通常是/var/log/maillog)。它常用于在实际运行的邮件服务器上测试邮件过滤规则。

  reject_unauth_pipelining

  拒绝在Postfix支持指令流水线前发送SMTP指令流水线的客户端连接。指令流水线是一些邮件客户端为了快速发送邮件所采用的技术。

  以下就四个子阶段分别讲述过滤规则

  A、SMTP连接时过滤(SMTP客户端限制)

  Postfix可以在接受客户端的SMTP连接请求时进行过滤检查。

  通过Postfix的smtpd_client_restrictions指令可以指定这个阶段的过滤规则。这个阶段可用的过滤规则除公共规则外还有:

  reject_unknown_client

  拒绝客户的地址没有对应的DNS的A记录或PTR记录的连接。通常有些机器,尤其是个人拨号用户的机器没有对应的A记录或PTR记录,所以要注意漫游用户的使用(漫游用户是指不在$mynetworks中,比如在别的ISP拨号上网的用户。通常用SMTP认证来解决这个问题)。

  unknown_client_reject_code指定了拒绝的返回状态码(默认是450)。

  permit_mynetworks

  允许来自其IP地址属于$mynetworks所定义网络的客户端的连接。通常可用于ISP为自己的拨号用户提供SMTP服务时,通过$mynetworks参数指定自己的网络并允许自己的网络内的机器发送邮件。

  reject_rbl_client domain.tld和reject_rhsbl_client domain.tld

  拒绝来自属于RBL和RHSBL列表中的地址进行连接。通过检查一个IP地址或域名是否存在于domain.tld的RBL或RHSBL中,可以判断该客户端是否被列入了domain.tld的实时黑名单,从而决定是否接受连接。有关实时黑名单可以参考本站的【反垃圾邮件技术参考>>实时黑名单技术】。

  maps_rbl_reject_code指定了拒绝的返回状态码(默认是554)。

  check_client_access maptype:mapname

  搜索名为mapname的maptype类型的访问数据库。可以根据客户端的主机名、父域、IP地址或部分IP地址来匹配。关于访问数据库请参阅下面的附录。

  例子:

  smtpd_client_restrictions = hash:/etc/postfix/access,

  reject_rbl_client relays.ordb.org,

  reject_rhsbl_client dsn.rfc-ignorant.org,

  permit_mynetworks,

  reject_unknown_client

  其中relays.ordb.org和dsn.rfs-ignorant.org都是国外比较权威的免费RBL和RHSBL服务器。

  B、HELO/EHLO指令过滤(HELO/EHLO主机名限制)

  在接受了SMTP连接后,可以对HELO或EHLO指令所发送的信息进行过滤检查。

  有些邮件客户端在通讯时并不发送HELO/EHLO指令,可以通过smtpd_helo_required设置为yes强制要求发送HELO/EHLO指令(默认Postfix不要求发送HELO/EHLO)。

  通过Postfix的smtpd_helo_restrictions指令可以指定这个阶段的过滤规则。这个阶段可用的过滤规则除公共规则和smtpd_client_restrictions的规则外还有:

  reject_invalid_hostname

  拒绝无效格式的主机名的连接。

  invalid_hostname_reject_code指定了拒绝的返回状态码(默认是501)。

  reject_unknown_hostname

  拒绝未知的主机名的连接。所谓未知的主机名是指该主机没有DNS的A记录或MX记录。由于很多拨号用户的机器并没有对应的A记录或MX记录,所以要注意漫游用户的使用。

  unknown_hostname_reject_code指定了拒绝的返回状态码(默认是450)。

  reject_non_fqdn_hostname

  拒绝主机名不是FQDN格式(完全限定域名格式,即用点分隔开的包括域名和主机名的主机全名)的连接。

  non_fqdn_reject_code指定了拒绝的返回状态码(默认时504)。

  permit_naked_ip_address

  允许直接使用IP地址的连接。通常在HELO/EHLO中使用主机名而不是IP地址。

  check_client_access maptype:mapname

  搜索名为mapname的maptype类型的访问数据库。可以根据HELO/EHLO发送的主机名、父域来匹配。关于访问数据库请参阅下面的附录。

  C、MAIL FROM指令过滤(发送者地址限制)

  在接受了SMTP连接,客户端发送了HELO/EHLO指令后(该指令可选),应该通过MAIL FROM指令声明发送者的身份。可以对发送者身份进行过滤检查。

  按照RFC规范,在MAIL FROM指令和下面的RCPT TO指令中应该使用RFC 821格式的邮件地址(例如:<user@domain.tld>),但是由于有许多的邮件客户端的不规范,往往不使用标准的RFC 821格式。Postfix默认接受任何可以理解的邮件地址,如:丢失了地址里的一对尖括号、可以包含RFC 822格式的注释等。如果希望打开对RFC 821格式的限制,可以将strict_rfc821_envelopes设置为yes。

  通过Postfix的smtpd_sender_restrictions指令可以指定这个阶段的过滤规则。这个阶段可用的过滤规则除了公共规则和smtpd_client_restrictions的规则和smtpd_helo_restrictions的规则外还有:

  reject_unknown_sender_domain

  拒绝发送者邮件的域没有DNS的A记录或MX记录的连接。

  unknown_address_reject_code指定了拒绝的返回状态码(默认是450)。当进行DNS查询出现临时错误时(如查询超时)也总是返回450。

  reject_rhsbl_sender domain.tld

  拒绝发送者邮件的域属于RHSBL黑名单的连接。通过检查一个域名是否存在于domain.tld的RHSBL中,可以判断该客户端是否被列入了domain.tld的实时黑名单,从而决定是否接受连接。

  maps_rbl_reject_code指定了拒绝的返回状态码(默认是554)。

  check_sender_access maptype:mapname

  搜索名为mapname的maptype类型的访问数据库。可以根据发送者邮件的邮件地址、名字、域和父域来匹配。关于访问数据库请参阅下面的附录。

  reject_non_fqdn_sender

  拒绝发送者邮件的域不是FQDN格式的连接。

  non_fqdn_reject_code指定了拒绝的返回状态码(默认时504)。

  reject_sender_login_mismatch

  拒绝发送者在$smtpd_sender_owner_maps中所匹配的用户名和SASL登录名不一致的连接。

  D、RCPT TO指令过滤(接收者地址限制)

  在MAIL FROM指令后要通过RCPT TO指令指定邮件接收者。可以对接收者身份进行过滤检查。

  通过Postfix的smtpd_recipient_restrictions指令可以指定这个阶段的过滤规则。同以上的检查指令不同,为了避免开放转发,这个指令有默认值:permit_mynetworks,reject_unauth_destination。这个阶段可用的过滤规则除了公共规则和smtpd_client_restrictions的规则和smtpd_helo_restrictions的规则和smtpd_sender_restrictions的规则外还有:

  permit_auth_destination

  允许发往默认转发和默认接收的连接。

  Postfix默认转发以下的邮件:

  来自$mynetworks中地址发送的邮件

  发往$relay_domains中的域或其子域的邮件。但是不能包含邮件路由(如user@elsewhere@domain.tld)。

  Postfix默认接收最终投递目标符合如下条件的邮件:

  目标在$inet_interfaces

  目标在$mydestinations

  目标在$virtual_alias_domains

  目标在$virtual_mailbox_domains

  reject_unauth_destination

  拒绝不是发往默认转发和默认接收的连接。

  relay_domain_reject_code指定了拒绝的返回状态码(默认是554)。

  permit_mx_backup

  允许接收本地主机是邮件投递目标的MX地址的邮件。但是不能包含邮件路由(如user@elsewhere@domain.tld)。

  check_recipient_access maptype:mapname

  搜索名为mapname的maptype类型的数据库。可以根据接收者邮件的邮件地址、名字、域和父域来匹配。 关于访问数据库请参阅下面的附录。

  check_recipient_maps

  拒绝接收者不匹配如下列表的连接:

  $local_recipient_maps($mydestinations和$inet_interfaces)

  $virtual_alias_maps($virtual_alias_domains)

  $virtual_mailbox_maps($virtual_mailbox_domains)

  $relay_recipient_maps($relay_domains)

  空的$local_recipient_maps和$local_recipient_maps表示不对接收者地址进行过滤检查。

  Postfix默认在接收者检查列表的最后做check_recipient_maps检查。

  reject_unknown_recipient_domain

  拒绝接收者邮件的域没有DNS的A记录或MX记录的连接。

  unknown_address_reject_code指定了拒绝的返回状态码(默认是450)。当进行DNS查询出现临时错误时(如查询超时)也总是返回450。

  reject_rhsbl_recipient domain.tld

  拒绝接收者邮件的域属于RHSBL黑名单的连接。通过检查一个域名是否存在于domain.tld的RHSBL中,可以判断该客户端是否被列入了domain.tld的实时黑名单,从而决定是否接受连接。

  maps_rbl_reject_code指定了拒绝的返回状态码(默认是554)。

  reject_non_fqdn_recipient

  拒绝接收者邮件的域不是FQDN格式的连接。

  non_fqdn_reject_code指定了拒绝的返回状态码(默认时504)。

  permit_sasl_authenticated

  允许通过了SASL认证的用Х⑺陀始Mü齋ASL协议(包括SASL1和SASL2)实现的SMTP认证功能需要在编译Postfix时编译进SASL支持,并在main.cf中将smtpd_sasl_auth_enable设置为yes。有关SASL及如何在Postfix中实现SASL认证请参阅下面的附录。通过SASL认证可以对漫游用户提供发信支持,是关闭Open-Relay的重要手段。

  一个smtpd_recipient_restrictions的例子:

  smtpd_recipient_restrictions = reject_invalid_hostname,

  reject_non_fqdn_hostname,

  reject_non_fqdn_sender,

  reject_non_fqdn_recipient,

  reject_unknown_sender_domain,

  reject_unknown_recipient_domain,

  reject_unauth_pipelining,

  permit_mynetworks,

  reject_unauth_destination,

  check_client_access hash:/etc/postfix/client_checks,

  check_client_access regexp:/etc/postfix/client_checks.re,

  check_helo_access hash:/etc/postfix/helo,

  check_sender_access hash:/etc/postfix/sender,

  check_recipient_access regexp:/etc/postfix/recipient.re,

  reject_rbl_client relays.ordb.org,

  reject_rbl_client list.dsbl.org,

  reject_rbl_client sbl.spamhaus.org,

  reject_rbl_client blackholes.easynet.nl,

  reject_rhsbl_client dsn.rfc-ignorant.org,

  permit

  这里要注意,有可能由于对reject_non_fqdn_*和reject_unknown_*的检查而导致一些主机名没有正常解析的机器不能正确发信。另外,在应用这个规则前,可以在规则列表头加上warn_if_reject来检查一下。

  2、多阶段过滤和单阶段过滤

  由于一些windows上有缺陷的邮件程序不处理在RCPT TO指令前的发回的拒绝状态码,所以Postfix默认不会在匹配了拒绝规则后就立刻断开连接,而是在RCPT TO指令处理完之后再断开的。可以通过smtpd_delay_reject设置为no来立刻发送拒绝状态码断开连接(默认是yes)。

  视乎smtpd_delay_reject设置为yes或no的不同,Postfix的过滤有多阶段过滤和单阶段过滤两种形式。

  A、多阶段过滤

  当选项smtpd_delay_reject设置为yes时,过滤是分为多个阶段进行的。比如,即便在上一个子阶段该连接被判定为需要被拒绝,但是由于拒绝被延迟了,所以会接着进行本子阶段的过滤,如果在本子阶段又允许了该连接,那么上一个子阶段的拒绝结果就会覆盖。

  从结果上看,这相当于无论上一个子阶段的过滤结果如何,都会进行所有定义了的过滤规则。所以我们称之为多阶段过滤。其逻辑模型如下:

  STATUS = CLIENT:{rule1 || rule2 || ...} * HELO:{rule1 || rule2 || ...} * SENDER:{rule1 || rule2 || ...} * RECIEPIENT:{rule1 || rule2 || ...} * permit

  这里的“||”表示如果一个规则有返回值(即进行了匹配,无论返回permit还是reject)那么就不进行该子阶段的其后的规则检查。

  B、单阶段过滤

  当选项smtpd_delay_reject设置为no时,相当于把这四个子阶段的过滤规则都依序排列连接成一个单一的过滤规则列表。比如,如果在某个阶段该连接被判定为需要被拒绝,那么会立刻拒绝,而根本不处理其后规则和其后子阶段的规则。

  从结果上看,这相当于如果某个规则发生了匹配,那么其后的规则和子阶段都被短路了,就像只有一个子阶段的检查一样。所以我们称之为单阶段过滤。其逻辑模型如下:

  STATUS = CLIENT:{rule1 || rule2 || ...} || HELO:{rule1 || rule2 || ...} || SENDER:{rule1 || rule2 || ...} || RECIEPIENT:{rule1 || rule2 || ...} || permit

  这里的“||”表示如果一个规则或子阶段有返回值(即进行了匹配,无论返回permit还是reject)那么就不进行该子阶段的其后的规则和子阶段检查。

  在单阶段过滤中,由于smtpd_recipient_restrictions可以接受所有的数据前过滤的规则,所以通常会把所有的过滤规则都放在这里。注意在单阶段过滤,所有排在前面的过滤规则被先处理,而且会形成短路。比如,如果你在smtpd_client_restrictions里就应用了RBL服务,但是RBL里面有一个地址是你希望接收来自那里的邮件的,那么根本没有机会来检查发送者地址就会被拒绝了。解决地方法就是在smtpd_sender_restrictions(或smtpd_recipient_restrictions)中先做一个check_sender_access,然后再做RBL检查。

 

0
相关文章