A-A+

postfix反垃圾邮件

2013年02月28日 综合技术 暂无评论 阅读 1,204 次

“不请自来的大宗邮件”(Unsolicited Bulk E-mail,UBE),或“不请自来的广告邮件”(Unsolicited Commercial E-mail,UCE),就是一般俗称的“垃圾邮件”(spam),寄件人没有事先征得收件人的同意,就擅自寄送大量(烦人的)邮件给一大群陌生的收件 人,这样的行为称为“滥发垃圾邮件”,而专门干这种事的人,叫做“垃圾邮件发送者”(spammer)。垃圾邮件之所以存在,是因为寄送成本便宜。邮递量 从几百人增加到几千人并不会增加太多成本,所以,来邮件发送者的目标就是尽量收集多的邮件地址。

垃圾邮件的本质

大部分的垃圾邮件都是商业广告,但是这些广告绝大部分都是唬人的骗局。垃圾邮件发送者才不在乎邮件内容是否能引起收件人的兴趣,而且他们的信息通常就是谎 言,若有其事的宣称收件人曾经跟他们公司有过怎样的关系,或是从天而降的伙伴那时得知你需要什么信息,所以特地写信给你云云。。。。。简直是鬼话连篇。有 些信息被刻意便造成煞有介事的样子,让你误以为有两个正在进行某种交易,谈论到他们的产品或服务有多么好,而你是因为他们不小心寄错邮件所以才会收到邮 件。。。。。。总之,他们想尽办法意图勾起你贪小便宜的心,而诱使你上当。
垃圾邮件经常提供“我不要再收到这样的邮件”的提示,比方说,要求你回信到某个邮箱,或是到某个网页填写你的邮件地址,或是点击一个含有特殊查询字符串的网址等。
然而,这样的选退机制本身通常也是骗局,垃圾邮件发送者利用这种方法来确定你的邮件地址确实有效的,而且你是属于那种比较容易受骗上当的人。换言之,如果你真的傻傻的遵照指示执行,换来的只是被更多垃圾邮件发送者知道你的邮件地址,而你也将会收到更多的垃圾邮件。
垃圾邮件发送者通常是试图隐藏他们的行踪的线索,避免被人逆向追查出来。假的回信地址与捏造的邮件标题,是最常使用的伎俩。他们在Internet上到处 搜寻没有妥善特定的系统,好让他们能够匿名寄出大量垃圾邮件。更高明的技术是入侵防备不当的系统,植入他们刻意设计的秘密relay server。此外,垃圾邮件的内容通常经过特殊编码或是安插随机字母,试图通过过滤程序的分析。
垃圾邮件发送者使用的某些伎俩,其副作用甚至必滥发垃圾邮件的行为本身更糟糕。就“漫无目标法”而言,他们不管邮件地址实际存在与否,而盲目的将垃圾邮件 送到他们认为可能存在的邮件地址。另一种“字典攻击法”则是预先收集所谓的“人名”,并从DNS查出各网域的MX服务器,集中寄出垃圾邮件到成功可能性最 高的邮件地址。两种伎俩都会无端造成受害系统的额外负担。

垃圾邮件的问题

虽然小规模的垃圾邮件似乎不是什么大问题,但是在Internet上,这却是相当严重的问题,甚至被认为是电子商务的杀手。一个为几百人或几千人提供邮件 服务的系统,如果每人每天都收到几百份垃圾邮件,那这个系统就快要瘫痪了。垃圾邮件的发送成本很低,但是垃圾邮件受害人却要付出真实的代价,这显然是不公 平的,因为垃圾邮件无端的占据了收件人的邮箱配额,浪费收件人的磁盘空间与网络带宽。
垃圾邮件带来的另一项损害是浪费技术支持人员的时间。虽然技术人员或管理员刻意帮助用户清理被塞爆的邮箱,但是,垃圾邮件的量有时候大到系统甚至无法胜任 其原来的任务。垃圾邮件的这种副作用,无异于刻意的“拒绝服务攻击”。就算没严重到这种地步,夹杂在正常邮件中的垃圾邮件还是会干扰用户的阅读,如果垃圾 邮件太多,甚至容易使人忽略重要邮件或误删正常邮件。
关于垃圾邮件的一项重要课题,在于如何处理寄给不明用户的邮件。有些邮件系统在发现收件地址无效时,当场就予以拒收(reject),邮件没机会进入队 列;有些系统则必须先收下邮件,然后才当成“无法投递的邮件”而退信,而这些退信很容易就塞满队列,进而干扰合法邮件的递送。由于垃圾邮件的回复地址通常 是无效的,所以退信不能立刻寄出去,而会在队列里待上好一阵子,在服务器尝试了多次无谓的递送之后,才会因为过期而被移除队列。
垃圾邮件发送者还有一种令人发指的恶行,他们会冒充无辜第三者的名义来滥发垃圾邮件,使得该受害者收到大量的退信通知。大量滥发垃圾邮件时,发信系统势必 时常遭到退信。当垃圾邮件发送者使用别人的open relay滥发垃圾邮件时,如果放任让退信或拒收通知函寄送到管理员邮箱,势必会引起管理员的警觉,一旦管理员关闭掉open relay或修补系统漏洞之后,他们将不能再继续使用该系统滥发垃圾邮件。因此,他们冒用无辜第三者的邮件地址为发信地址,使退信通知送到该无辜地址,借 此延后管理员发觉系统被滥用的时间。而那位被冒用名义的无辜受害人将收到上千甚至上百万封退信通知。这种情况我们称之为“背黑锅”,因为受害人并未参与滥 发垃圾邮件的恶行。在大多数情况下,摆脱黑锅的唯一办法是放弃那个地址,改用另一个新地址。

开放转发(open relay)

如果你的系统不得不服务来自Internet的客户端,你有责任避免系统成为开放转发,以免垃圾邮件发送者使用你的系统来转发垃圾邮件。open relay是一种特殊的邮件系统,这类系统不限制客户端的位置,也不查证邮件是否寄给直辖网域,就原意收下并代为转寄到最终目的地。在垃圾邮件还不泛滥的 年代,邮件系统管理员多半愿意提供转发服务,好让他们的用户不管旅行到世界哪一个角落,都能通过他们的服务器寄信。因此,开放转发服务是当时的smtp服 务器软件(sendmail 8之前得安版本)的默认配置。然而,随Internet的普及,立意很好的open relay现在反而成为垃圾邮件跳板的代名词。因为对于邮件的终点站而言,这类邮件看起来就像是直接从open relay发出的一样,垃圾邮件发送者就是利用此一特性来隐藏真实的发信地点。现在,几乎所有新一代的smtp软件都默认配置都会限定转发功能的服务对 象,而postfix当然也不例外。
倘若你的系统被当成open relay使用,最可能出现的症状是寄信效率明显变低,因为它正忙着寄送大量的垃圾邮件,无暇递送合法用户的正常邮件。如果你愿意让自己的系统成为垃圾邮 件的帮凶,你还得小心有心人利用你的open relay来攻陷其他系统。而且在你的系统转发了大量的垃圾邮件之后,你的网络将有很高的机率被列入黑名单,到那时候,将有许多站点拒收来自于你的网络的 全部邮件--包括垃圾邮件与合法邮件。

辨别垃圾邮件

只要你的系统不被当成open relay使用,至少刻意放心它不会被用来攻击其他系统,而你下一步,应该是保护自己以及你的用户,想办法尽量减少收到垃圾邮件。理论上,邮件服务器应该 能够拒收任何看起来像垃圾邮件的邮件。然而,虽然人类有能力一眼就认出垃圾邮件,但是要求计算机精确认出垃圾邮件而不发生误判,根本是不可能的。实际上, 一旦你开始拒收垃圾邮件,必定有可能将合法邮件按误当在门外。
拒收被误当成垃圾邮件的合法邮件,这种事件我们称之为误判。你的垃圾邮件抵制措施要尽量达成两个相互违背的目标;尽可能挡掉可疑的垃圾邮件和尽可能降低误 判机率。你采取的管制措施越严格,发生误判的风险就越高。要采取严格到何种程度的管理措施,取决于发生误判所造成的严重性有多高。对于完全不容许误判的环 境(比方说,专用来接收客户订单的邮件系统),只能采取最宽松的管制,也就是接收所有的垃圾邮件。相对的,如果不在乎误判或是能够事先协调好用户,则可疑 采取最严格的管制;只有事先特许的个人才能使用邮件系统,也就是所谓的“白名单”。事先批准似乎过于严苛,但是,当垃圾邮件问题已经严重到不可收拾的地 步,白名单已经成为越来越普遍的选择。
计算机要如何判断来信是否为垃圾邮件?主要判定依据有二,首先是“邮件来源”,其次是“信息内容”。前者是在收信期间检查送信方是否为已知的垃圾邮件来 源,或是其寄信行为是否符合滥发垃圾邮件的条件。后者是在收下邮件后,检查信息内容是否包含可被判定为垃圾邮件的字眼或其他条件。先不管实行细节上的困 难,只要邮件管理员能够预先设想到各种判定技术的盲点,就能够兼顾“尽可能挡掉可疑的垃圾邮件”与“尽可能降低误判机率”这两项彼此违背的目标。

依据客户端判别垃圾邮件

这里所谓的“客户端”是指在smtp交互过程中的寄信方。如你所知,在smtp对话过程中,服务器端(收信方)可得到对方的ip地址、主机名称与邮件地 址。这些信息片断都可以用来与一组已知的黑名单比对,借此决定应该接收还是拒收邮件。被列在黑名单中的系统,有可能真的是垃圾邮件发送者拥有的主机,但也 有可能是无辜的open relay系统,目前,Internet上已经很难找到“刻意为了提供转发服务而架设的服务器主机”,大部分的open relay多半是倒霉的、无辜的或无知的管理员所架设的系统,open relay并非他们的本意。但不管是哪一种情况,如果你发现某特定对象经常给你寄垃圾邮件,你可以考虑将对方列入黑名单。不过,依据ip地址、主机名称或 邮件地址来判定垃圾邮件,最大的问题是这类信息都可被假造。虽然伪造ip地址需要非常高的技术,但是信封地址是很容易假造的。

dns-based黑名单
为了抑止Internet上垃圾邮件的日益泛滥,各种自发性的抵制技术与网络服务应运而生,其中一类颇有争议的技术称为“dns-based黑名单”或 “实时黑名单”。这类技术的原理,是将已知的open relay或垃圾邮件来源记录在一个动态数据库,并通过DNS系统开放给MTA server查询。他们的构想是抢先一步提供预判结果给合法的MTA server,减轻邮件管理员自己维护黑名单的负担。以往,垃圾邮件发送者还会使用自己的系统来滥发垃圾邮件,或是搜寻open relay来转发垃圾邮件;近年来,这群人的行为越来越猖狂,他们几乎已经不再使用自己的系统发垃圾邮件,而是寻找有机可乘的受害系统,植入可让他们滥发 垃圾邮件的代理软件,而被胁持的系统能够甚至可能被用来发动DOS攻击。有些机构的DNSBL专门提供这类非自愿的垃圾邮件转发的查询服务。
通常,RBL系统的查询服务是通过dns提供的。对于每一个被认定为垃圾邮件来源的ip地址,在rbl所有者的网域空间里都有一个对应的PTR记录, MAT在收信期间向RBL系统查询客户端的ip地址,借此决定应该接收还是拒收邮件。举例来说,假设有一家(虚构的)RBL服务机构,他们的网域名称为 nospam.example.com,位于192.168.254.31的主机已经被他们认定为垃圾邮件来源,于是,nospam公司在他们的网域空间 里创建一个dns ptr记录,31.254.168.192。nospam.example.com当192.168.254.31主机连接到你的postfix系统, postfix可查询该ip地址是否在nospam.example.com网域下有一个PRT记录,如果有,表示该ip地址已被认定为垃圾邮件来源, postfix可当场拒绝该主机的寄信要求。
在你决定使用DNSBL服务之前,必须非常谨慎小心。有许多被用来转发垃圾邮件的open relay系统,它们本身也提供服务给一般的正常用户。你虽然挡掉了来自这些系统的垃圾邮件,但也挡掉了源自同系统能够的合法邮件。此外,将是否收信的决 定权交给无责任的第三方,由别人决定谁能够谁不能够寄信给你的用户,是一种推卸责任的行为。但如果你真的深受垃圾邮件之害,在你研究出适当的抵制方法之 前,DNSBL服务确实能够帮上忙。如果你决定使用某家公司的服务,请务必仔细检视他们的服务条款与政策。再一次的,你在“尽可能挡掉可疑的垃圾邮件”与 “尽可能降低误判机率”之间取得平衡点。

依据内容判别垃圾邮件

除了以客户端判别条件之外,邮件内容通常也可作为供判别垃圾邮件的特征。垃圾邮件时常出现某些特定的广告语。依据邮件内容来辨识垃圾邮件,并非没有误判的 可能。想像一下,如果你经常收到大量关于低率房贷的垃圾邮件,你可能会想要挡掉含有类似“lomorratetgagewest”词组的邮件。当然,这样 确实可挡掉不少垃圾邮件,但是,你可能也挡掉了银行同意核发低利率贷款给你的朋友的通知信。
判别技术的困难处
不管以客户端还是邮件内容作为判别依据,垃圾邮件发送者总是有办法找到办法避过你的抵制措施。合法邮件与垃圾邮件之间,总是一有段难以理清的模糊地带。当你努力收集黑名单的同时,垃圾邮件发送者也正在寻找新的代罪羔羊(这种无辜系统的数量之多,远超过你的想像)。
你可能发现,在你收到的垃圾邮件中,有许多具有相同的回信地址。当然,你确实可使用回信地址来阻挡垃圾邮件,但是,他们多半采用“边打边跑”战术。他们先 向免费邮件网站申请一个邮箱,然后使用该地址送出千万封垃圾邮件,过了几天之后,他们便放弃原来的邮箱,另外再申请一个新邮箱。所以,被你列入黑名单的回 信地址,过不了几天就不会再出现了。
就算是专门的内容过滤系统,也必须随垃圾邮件发送者的干扰伎俩而调整。举例来说,很多滤信软件会挡掉正文含有 “viagra”字样的邮件,于是,垃圾邮件发送者便将HTML注释标记嵌在这类关键词句中--将“viagra"改成“vi<!--oxo-- >agra",借此避开过滤程序的字符串比对条件。如果你调整过滤条件,挡掉含有html注释标记的邮件(好主意!虽然有点风险),过几天,你会发 现他们又换花招了,含有vlagra或 vi@gra字样的垃圾邮件将闯入你的系统,于是,你又被迫增加新的过滤条件。因此,如果你决心向垃圾邮件发送者宣战,你最好有个心里准备,这会是一场长 期抗战。

反垃圾邮件的措施

一般来说,侦测到垃圾邮件之后,你有下列几种选择:
在smtp对话过程中,当场拒收垃圾邮件。于第一时间把垃圾邮件挡在大门之外确实是个好主意,因为垃圾邮件不会进到邮箱,而你也不必担心后续的处理工作, 发信会承担处理拒信错误的善后工作。然而,如果你的站点不能够容忍拒收合法邮件的后果,或许你应该考虑第二种选择。
暂时将可疑的垃圾邮件另外存储在专用邮箱,再研究一套事后程序来处理它们。比方说,定期检阅被集中起来的可疑垃圾邮件,确定其中没有合法邮件之后才一并删 除。虽然这样可确保不错失任何合法邮件,但是却可能耽搁合法邮件的时效性,除非你的站点有足够的人力(与财力)请人专门检阅可疑的垃圾邮件。此外,事后的 检阅工作相当无聊,而且有道德风险(万一看到不该看的邮件,怎么办?)。因此,你应该考虑将垃圾邮件存放在个别用户能看到的专用邮箱。不过,这需要用户改 用IMAP协议来收信,如果你的用户都使用pop协议收信,这可能不是个好办法。
注:  由于MUA软件多半具有HTML自动译码能力,所以,大多数收件人看到的依然是“viagra”,而感觉不到HTML注释标记造成的差异。
将可疑的垃圾邮件打上某种特殊标记,投递到用户的正常邮箱,由用户收下邮件后自行判断。比方说,用户可用他们的MUA或MDA软件设定一个过滤条件,将含 有特殊标记的可疑垃圾邮件与正常邮件分开存储。这种技术的好书,在于用户可自己决定如何处理垃圾邮件,即不会错失合法邮件,也不必担心私密邮件曝光。 postfix目前没内置可标示垃圾邮件的机制,但是postfix可疑搭配外部的内容过滤程序,由外部程序处理垃圾邮件的分析与标示事宜。
分析垃圾邮件是件沉重的负担,如果运行MTA的机器还有充足资源来分析垃圾邮件,那么,在第一关就挡掉垃圾邮件通常是最理想的选择。但如果需要较大的灵活 性,将过滤工作交给MDA或MUA层来执行或许比较合理。不过,更理想的选择是前两种技术的结合:在MTA层挡掉明显的垃圾邮件,将可疑的邮件交给MDA 或mua层处理。
在协助辨识垃圾邮件来源、拒收垃圾邮件的功能方面,postfix是相当优秀的工具。用postfix阻挡垃圾邮件所需的资源,远低于外部过滤程序所胥的资源。如果你担心误判合法邮件,postfix还提供了一写补救的措施。

postfix的挡信机制

本章的其余内容讨论阻挡垃圾邮件的技术层面的问题,解释postfix提供的UBE检查机制。按照UBE的判别依据,postfix提供的检查机制可分四大类:
客户端判别规则
postfix提供四种检查客户端身份的参数,每一种参数都可设定一系列决定如何响应客户端的限制条件。如果条件成立,可能的响应动作包括ok(收下邮 件)与reject(当场拒收)。例如,你可疑设定一条检查规则。挡掉来自特定ip地址的邮件。相对的,如果条件不成立,则由后续条件继续处理(这种结果 通常以DUNNO表示)。
语法检查参数
postfix内置一系列专用检查语法的参数,可用来核验客户端的smtp对话内容是否符合标准规定。由于垃圾邮件发送者通常不遵守标准规定,则对于不符合规定的客户端或邮件,你可以要求postfix予以拒收。有些语法检查参数也可作为客户端判别规则。
内容检查
你可以将一组描述垃圾邮件特征的正则表达式写在查询表中,要求postfix依据样式表来检查邮件的标题与正文内容。
自定义过滤规则
你可将一系列内置的限制条件组织成新的过滤规则。
设定postfix的垃圾邮件标识参数时,你还必须指定如何处理被辨认出来的垃圾邮件。一般而言,postfix可以当场拒收,或是收下邮件但是暂存在另一个队列,或是交给外部过滤程序去处理。

客户端判别规则

下列过滤规则可设定一系列对客户端信息的限制条件:
smtpd_client_restrictions
smtpd_helo_restrictions
smtpd_sender_restrictions
smtpd_recipient_restrictions
smtpd_data_restrictions
上述的每一项参数,分别用于检查smtp对话过程中的特定阶段。在每一个阶段,客户端分别提供不同类型的信息。potfix依据你给各规则设定的限制条件来检查这些信息。

smtp对话过程(简述)

首先,一个smtp client通过socket连接到postfix。由于是socket方式连接,所以postfix在建立连接时就可以知道客户端的ip地址。 smtpd client_restrictions让你可依据客户端的ip地址或主机名称来决定是接收还是拒收该信息。连接成功后,客户端送出HELO命令来显示自 己(送信方)的主机名称。postfix依据smtpd_helo_restrictions的限制条件来检查这个主机名称,借此决定应该收下还是拒收邮 件。
下一步,客户端发出mail from命令来显示寄件人的邮件地址,接着以一个rcpt to命令来表明收件人的邮件地址。寄件人与收件人的邮件地址的限制条件,分别设定在smtpd_sender_restrictions与 smtpd_recipient_restrictions中。
如果到DATA命令为止之前的一切都可以接收,客户端就可以开始传送邮件的内容。邮件内容分成两部分,前半部是标题,由header_check过滤;后 半部是正文(body),由check_body过滤。如果最后的标题与正文检查也过关,postfix就收下信息,并交给适当的MDA执行投递操作。
注:  很多垃圾邮件发送者在HELO步骤送出的是“收信方”的主机名称,任何遵守规定的smtp client都不会这样做,所以你可以在smtp_helo_restrictions设一个限制条件,禁止对方使用我们的主机名称。

设定限制条件

当你设定postfix的UBE限制条件时,不一定要将它们分别设定给不同的参数,可以集中在同一个参数中,而对其他参数不加任何限制。如果你的mail.cf没有设定UBE过滤规则,则postfix的默认配置看起来就像这样:
smtpd_client_restrictions =
smtpd_helo_restrictions =
smtpd_sender_restrictions =
smtpd_recipient_restrictions =
permit_mynetworks, reject_unauth_destination
这使得只有局域网上的主机可以通过postfix来转发邮件,而其他系统一律不允许,除非它们的信是寄给postfix所辖网域的用户。
postfix 提供一组内置的限制条件,而你也可以用访问表(access map)来定义自己的限制条件。许多人第一次面对postfix的UBE限制条件时,常误以为某些条件只能用于特定过滤规则,其实不然。你必须记住一个重 要概念:任何限制条件都可以用于任何过滤规则。虽然逻辑上check_helo_access条件应该是设定给 smtpd_heko_restrictions,但其实它也可以被用于smtpd_sender_restrictions或任何其他过滤规则。 postfix的这种设计,主要是为了让你可以更有灵活性的安排限制条件的顺序。
限制条件与对应的受检信息
限制条件                                                         客户端提供的受检信息
reject_rbl_client                                                   客户端的ip地址或主机名称
reject_rhsbl_client
reject_unknown_client
chkec_client_access type:mapname               HELO提供的主机名称
permit_naked_ip_address
reject_invalid_hostname
reject_non_fqdn_hostname
reject_unknown_hostname
check_helo_access type:mapname               MAIL FROM提供的寄件人邮件地址
rejct_non_fqdn_sender
reject_rhsbl_sender
reject_unknown_sender_domain
check_sender_access type:mapname         RCPT TO提供的收件人邮件地址
permit_auth_destination
permit_mx_backup
reject_non_fqdn_recipient
reject_unauth_destination
reject_unknown_recipient_domain
check_recipient_access type:mapname
reject_unauth_pipelining                                  DATA命令
permit                                                                    无条件批准
reject                                                                     无条件拒绝
defer                                                                     无条件延迟
warn_if_reject                                                 将原本的reject动作改成wrn(需放在其他条件之前,不能单独使用)
reject_unauth_pipelining                                禁止非授权客户端使用pipelining命令
从形式上看限制条件大致可分为三类。第一类是内置条件,它们的名称以permit_和reject_开头,不需要额外自变量。第二类为自定义条件,它们的 名称类似check_*_access,需要一个type:mapname自变量,其中mapname是访问表(access table)的名称。在技术上,访问表与一般的postfix查询表没两样,同样都是由一系列的key-value组合而成;在用途上,访问表供管理员定 义自己的过滤规则;索引键描述客户端的匹配条件,对应值描述如何处理符合条件的客户端。第三类为通用条件,它们没有额外自变量,也不检查任何信息,用于直 接改变邮件的处理流程,或是改变其他限制条件的作用。
内置限制条件的工作流程
每一种内置限制条件(reject_和permit_系列),分别检查不同的客户端信息,postfix依据检查结果决定如何处理邮件。处理方式包括: ok、reject以及dunno。当你在同一个过滤规则中列出多个限制条件时,postfix依照它们的排列顺序来进行检查过程。检查过程中,如果某条 件的检查结果为reject,则postfix会立刻拒收邮件;如果检查结果为ok,则略过同一过滤规则中的其余条件,继续检查下一个过滤规则,直到所有 规则都检查完毕或是出现reject结果为止。请注意,按照上述流程,即使邮件在某条件的检查结果是ok,该邮件仍有机会被另一个过滤规则的条件予以 reject。总而言之,任何条件都可以拒收邮件,但邮件必须通过所有过滤规则才会被收下。如果邮件通过一整组过滤规则都没有得到明确结果(全部都是 dunno),postfix的默认行为是收下邮件。
当过滤规则的检查结果为reject时,postfix的默认行为并不是真的当场拒收,除非客户端已经送出recp to命令。换言之,即使postfix在客户端送出helo命令时就决定拒收,它也会先响应ok,等到客户端送出rcpt to命令之后才会响应reject。postfix这样的默认行为设计,主要是顾虑到某些smtp client在对话过程中不会检查服务器端的响应码,而盲目的送出信息。对于这种情况,如果在第一时间就送出reject响应码,结果只是使得连接时间比 原本应有的时间更长,而且会在日志文件里留下好几笔警告记录。将reject时间延迟到recp to之后的另一个好处是postfix可获得足够的客户端信息,而日志文件留下的记录也比较完整。如果你想改变延迟reject时机的行为,让 reject动作在第一时间发生,你可将main.cf的smtpd_delay_reject设成成no:
smtpd_delay_reject = no
如果你能完全掌握控制postfix server的周围环境,而且事先确定所有的smtp client都遵守规则,则可容许postfix在第一时间拒收问题邮件;否则,默认行为还是比较理想的。
测试新条件
反垃圾邮件是一项长期的工作,垃圾邮件发送者的花招层出不穷,管理员也需要定期修正或增加新的限制条件。然而,新条件的效果很难完全事先预测,如果没经过 实际测试,很难知道新条件是否会误判合法邮件。问题是,如果要等到真的发生误判才能知道效果,这代价未免也太大。为此,postfix提供了一个参数,让 你用来测试新限制条件:
sotf_bounce = yes
在sotf_bounce模式下,硬性拒绝码(5xx)会被改成软性拒绝码(4xx)。对smtp client而言,5xx代表服务器端彻底拒绝请求,即使下次再尝试寄出同一封邮件,服务器端也不会接受。所有,收到5xx响应码的客户端不会继续尝试同 样的动作。另一方面,4xx代表服务器端只是暂时拒绝请求,客户端下次仍有机会成功寄出邮件,所以smtp client会保留邮件以等待下次寄送时机。利用sotf_bounce模式来测试新条件,即使发生误判,只要我们能实时更正,被误判的smtp client就有机会寄出它的信。
每增加一条你没把握的新限制条件,都可以打开soft_bounce模式,然后观察日志文件,看看是否发生误判,并调整条件设计,等一切都妥当之后,再关掉sotf bounce模式。
另一个有用的条件测试工具是warn_if_reject修饰符。将这个修饰符放在限制条件之前,该条件原本的reject动作都被改成warn。也就是 说,smtp client不会被挡在门外,但是postfix会在日志文件里留下一笔警告记录,表示该条件发生作用了。如果你不确定新条件在实际环境下会造成什么后 果,但是又不喜欢soft_bounce模式那种全面性的影响,你可以用warn_if_reject。来测试新条件,等到确定新条件的效果符合预期之 后,再拿掉warn_if_reject修饰符。举例来说:
smtpd_recipient_restrictions =
permit_mynetworks
reject_unauth_destination
warn_if_reject   reject_invalid_hostname
reject_unknown_recipient_domain
reject_non_fqdn_recipient
在此例中,如果客户端使用helo命令送出了一个无效的主机名称,postfix仍然会容许对方送出邮件(如果没被其他条件挡掉的话),但是会在日志文件留下一笔警告记录。

一个简单实例
在继续深入研究如何定义限制条件之前,让我们先看一个简单例子:
smtpd_recipient_restrictions =
permit_mynetworks
reject_unauth_destination
reject_invalid_hostname
reject_unknown_sender_domain
这个例子对默认配置扩充了两个额外限制条件: reject_unauth_destination以及reject_invalid_hostname。当客户端建立连接时,若它来自 mynetworks或mynetworks_restrictons过滤规则也就跟着结束,不再检查其他条件;如果客户端来自外界网络, permit_mynetworks不会返回ok,也不会返回reject,而是返回dunno,于是postfix接着检查 reject_unauth_destination。
如果邮件的收件人不在postfix所辖的网域(由mydestination定义), reject_unauth_destination返回 reject;否则返回dunno。假设这次的结果是dunno,postfix会接着检查reject_invalid_hostname,如果客户端 使用HELO命令提供的主机名称是无效的,这项检查的结果是reject;如果有效,则为dunno。最后,postfix检查 reject_unknown_sender_domain,如果客户端在mail from提供的邮件地址的网域部分是无效的(用DNS查不出来),则检查结果是reject。如果邮件能顺利通过上述四项限制条件而不发生任何 reject,postfix就会收下邮件,并交给适当的MDA处理。

定义限制条件

依据检查对象的不同,限制条件可分为六大类型,分述如下:
访问表
名称为check_*_access形式的限制条件,依据访问表所列的ip地址、主机名称或邮件地址来决定postfix应该采取拒收还是接受。
客户端参数
有些限制条件是依据配置文件里的一般信息而非访问表来检查客户端的资格。例如,先前的permit_mynetworks条件就是检查客户端是否来自mynetworks或mynetworks_style定义的网络。
严格语法检查
某些限制条件要求postfix非常严格的贯彻smtp标准。由于垃圾邮件发送者经常刻意违反smtp标准,所以这类可挡掉大量的垃圾邮件。
dns检查
利用dns系统提供的信息来审查客户端是否诚实。垃圾邮件发送者最常出没在那些没有妥善设定好dns的网络,适当运用这类规则条件,确实刻意大量减少垃圾 邮件。然而有许多合法邮件也是来自dns没有设好的网络,所以误判的机会也很高。除非你反对垃圾邮件抱非常积极的态度。否则不应该过度依赖dns检查。
实时黑名单
实时黑名单(RBL)是一种依附在dns系统下的网络服务,供MTA实时查询客户端是否来自恶名昭彰的垃圾源。虽然postfix也提供RBL client支持,但是这种服务仍有争议性。
通过限制条件
无条件拒绝(reject)或收下邮件(permit),或是改变其他条件的行为(warn_if_reject)。这类条件通常出现在整组过滤规则的最后,作为该组规则的默认行为。
接下来的六小节分别详细说明上述六种限制条件。

访问表

任何涉及客户端资格的检查限制条件,都需要你提供一个访问表(access map)。访问表也是postfix查询表的一种,同样都是由一系列key-value组成,只不过访问表的索引键是客户端标识信息(ip地址、邮件地 址、主机名称等),而对应值是处理动作(ok或reject)
check_client_access maptype:mapname
check_client_access指向一个含有ip地址、网络地址、主机名称、从属网域名称的访问表。设定此限制条件时,postfix先从dns 系统反查出客户端ip地址的完整主机名称(PTR记录),并自己分析出主机名称与从属网络,然后以这些信息与访问表中的每一个索引键比对,如果发现相符的 索引键,则采取对应值所指定的处理动作。
check_helo_access  maptype:mapname
check_helo_access所指的访问表含有主机名称与从属网域,用于比对客户端在helo命令中显示的主机名称。如果发现相符的索引键,则postfix执行对应值所指定的处理动作。
check_recipient_access maptype:mapname
check_recipient_access指向一个含有邮件地址、网域名称、人名的访问表,用于比对客户端在rcpt to命令中提供的收件地址。如果发现相符的索引键,则postfix执行对应值所指定的处理动作。
check_sender_access maptype:mapname
check_sender_access指向一个含有邮件地址、网域名称、人名的访问表,用于比对客户端在mail from命令中提供的寄件人邮件地址。如果发现相符的索引键,则postfix执行对应值所指定的处理动作。
check_sender_access 和check_recipient_access这两种限制条件都是用来检查客户端提供的邮件地址。这两者所使用的访问表,可包含完整的邮件地址,也可能 只有网域名称或是只有人名部分。对于完整邮件地址,必须完全符合才算条件成立;如果只有网域名称部分,则该网域与所有子网域的邮件地址相符都算;如果只有 人名部分,则不管任何网域,只要人名相符就算条件成立。
check_client_access和check_helo_access两者要检查的数据都是ip地址与主机名称,访问表的索引键刻意是数字形式的ip地址,也刻意是网络地址(10、10.12或10.12.154)。
访问表的对应值是发现相符的索引键之后,postfix应该采取的动作。可能的动作如下:
ok
通过当前过滤规则的检查,postfix继续检查下一组过滤规则。
reject
reject message-text
拒收邮件。你刻意另外加注一段简短信息,说明拒绝服务的理由,这段信息会连同拒绝码一起返回给客户端,并且被记录在postfix的日志文件里。 access_map_reject.code参数定义所有check_*_access限制条件的默认拒绝码, maps_rbl_reject_code参数定义reject_maps_rbl的默认拒绝码,两者的默认值都是554。
dunno
停止检查当前的访问表,假装没找到符合的项目。postfix会继续检查下一个限制条件。
filter transport:nexthop
将邮件转交给指定的内容过滤器。你必须像设定传输表那样,指定一个传输方法(transport)与其下一步。(nexthop)
hold
hold message-text
将邮件放在保留队列(hold queue)。如果你加注一段简短信息,则postfix会将这段信息记录在日志文件里;否则只记录一般信息。被扣留的邮件会一直留在队列里,直到有人删除它或是将它释放给适当的mda处理。
discard
discard message-text
要求postfix收下邮件后立刻丢弃,但是让客户端误以为它已成功送出邮件。如果你加注一段简短信息,则postfix会将这段信息记录在日志文件里; 否则只记录一般信息。别轻易尝试discard动作,除非你已经谨慎考虑过可能的后果。暗自丢掉邮件的行为,有违邮件系统的设计初衷。虽然丢掉垃圾邮件是 理所当然的动作,但万一发生误判,势必无法挽回已经消息的合法邮件,而且有损用于对于internet e-mail的信任。
4xx message-text
返回指定的拒绝码与信息给客户端,表示暂时拒收邮件。400-499范围内的拒绝码代表服务器端暂时性问题,客户端应该先保留邮件,下次再尝试传送。
5xx message-text
返回指定的拒绝码与信息给客户端,表示彻底拒收邮件。500-599范围内的拒绝码代表服务器端不管怎样都不会收下邮件,客户端应该发出退信通知给原寄件人。
访问表的索引键也可以是“正则表达式”。一般而言,使用正则表达式来描述访问表是一种浪费,因为postfix已经有分析邮件地址、网域名称、ip地址的能力,所以正则表达式带来的好处并不多。但如果要检查邮件的内容(标题或正文),正则表达式就非常好用。

应该使用4xx或5xx来阻挡垃圾邮件?

阻挡垃圾邮件时,有两种拒绝码可以选择。4xx范围内的拒绝码代表其是暂时性问题,客户端下次还有成功寄出邮件的机会;5xx范围内的拒绝码代表永久性错误,要求客户端不必再试。
乍看之下,5xx显然是阻挡垃圾邮件的优先选择,因为我们要求垃圾邮件发送者彻底死心。然而,4xx其实也有优点,因为假设发生了误判事件,而你在查阅日 志文件时发现了这件事,这时候还有补救机会,只要能实时修正导致误判的过滤规则,就还有机会收到该封被误判的合法邮件。但如果使用4xx阻挡垃圾邮件,而 你的网域里还有其他mx备用服务器,假设备用系统没有挡掉垃圾邮件,那么,你的暂时性拒绝动作,将导致mx备用系统的队列里充斥着大量寄不出去的垃圾邮 件。
在填写你访问表时,你应该依据被挡掉的对象、原因以及你的信心来选择适当的拒绝码。但无论如何,切忌一件事:垃圾邮件发送者不会理会你的拒绝码,因为他们 本来就是不守规矩的人,期待它们遵守没有法律约束力的smtp协议,无异于缘木求鱼;换言之,不要天真的以为一切都在你的掌控之下。
现在增加了恋歌要检查访问表的限制条件,所以必须另外准备两个访问表文件,一个是client_access文件,其内容如下:
10.157            reject
192.168.76.23         reject
currentmail.com         reject
另一个文件是sender access,其内容看起来应该类似这样:
hardsell@example.com            reject
marketing@                  reject
specialis.digital-letter.com         reject
准备好这两个文件之后,记得使用postmap将它们转换成适合postfix查询的数据库格式:
postmap /etc/potfix/client_access
postmap /etc/postfix/sender_access
以后每次修改访问表,都要重复一次上述动作。
其他客户端条件限制
在内置限制条件,其中有部分是依据“postfix本身的配置信息”与“客户端提供的信息”的比较结果来决定处理动作,这类条件不需要访问表。
permit_auth_destintion
如果收件地址位于postfix的辖区,则批准请求。所谓"postfix的辖区“,包括mydestination、inet_interfaces、 virtual_alia_maps或virtual_mailbox_maps以及relay_domain所列的网域及子网域,而且收件地址不能包含 任何“发信方指定的投递路径”(例如:user@example.com@example.net)。如果收件地址不符合 permit_auth_destination条件,则它返回dunno而非reject,所以postfix可继续检查后续的限制条件。
permit_mynetworks
如果客户端的ip地址位于mynetworks参数所列的任何地址范围内,则批准请求。我们经常使用此条件将本地客户端排除在UEB过滤规则之外,让他们可无条件使用postfix server来转发邮件。
reject_unauth_destination
如果收件地址不位于postfix的辖区,则拒绝请求。postfix的辖区包括mydestination、inet_interfaces virtual_alias_maps或virtual_mailbox_maps以及relay_domain所列的网域以及子网域,而且收件地址不能 包含任何发信方的投递路径(例如:user@example.com@xample.net)。本条件的拒绝码为 relay_domains_reject_code,其默认值是554。
严格语法条件
在内置限制条件,有部分是以“客户端在smtp对话过程提供的信息是否符合标准“为判断依据的。这类条件可侦测出大量垃圾邮件,但是发生误判的机会也很 高。你应该研究你收到的垃圾邮件与真实邮件之间的差异(或共同处),才会知道哪些条件可以使用(或不可使用)。如果你事先知道哪些寄件人可能被误判,建议 你将他们列入白名单里。
reject_invalid_hostname
如果客户端在helo命令提供的主机名称不是有效的主机名称,则返回invalid hostname_reject_code参数指定的拒绝码(默认值为501)。大多数合法寄件人都应该会提供有效主机名称。
reject_non_fqdn_hostname
如果客户端在helo命令提供的主机名称不是RFC要求的完整形式(fqdn),则返回non_fqdn_reject_code参数指定的拒绝码(默认值为504),并非所有合法寄件人都会提供fqdn完整名称(尤其是windows系统)
reject_non_fqdn_recipient
如果客户端在rcpt to命令提供的收件地址的网域部分,不是rfc要求的完整形式(fqdn),则返回non_fqdn_reject_code参数指定的拒绝码(默认值为504)。大部分合法寄件人提供的收件地址应该都有fqdn完整名称。
reject_non_fqdn_sender
如果客户端在mail from命令提供的寄件人邮件地址的网域部分,不是rfc要求的完整形式,则返回non_fqdn_reject_code参数指定的拒绝码(504)
reject_unauth_pipelining
流水线操作(pipelining)是一种加速处理大宗邮件的技术,其原理是容许客户端一次送出多个smtp命令。协议要求客户端必须先检查服务器端是否 支持pipelining,才可以开始流水线操作,但是有些mua与mta不遵守规定,它们在还没确定服务器端是否同意pipelinging之前,就开 始流水线操作。postfix支持流水线操作,而你可用reject_unauth_pipelinging立刻拒绝那些不遵守规定的smtp client。

dns限制条件

dns限制条件确定客户端所在的网络以及信封上的邮件地址,是否有可查验的dns信息。如果邮件管理员总是能取得有效的dns信息,internet e-mail系统的可用度将获得普遍提升,因为垃圾邮件发送者将难以遁形。不幸的,dns系统是网管人员最常疏忽的一环,有许多合法用户所在的网络并没有 可兹查验的dns信息,因此,完全依赖dns来过滤垃圾邮件,反而成了不切实际的想法。你应该研究你所收到的垃圾邮件与真实邮件的本质,看看哪些限制条件 既能够阻挡最多的垃圾邮件,而误判机率又不令人担心。如果你事先知道哪些寄件人可能被误判,建议你将他们列入白名单里,以免受到dns限制条件的影响。
reject_unknown_client
当一个smtp client通过socket建立连接时,postfix server可从socket连接知道客户端的ip地址。设定reject_unknown_client限制条件时,如果postfix从dns查不出 客户端ip地址的PRT记录,则会拒绝服务;如果能从dns查出主机名称,则postfix还会使用该主机名称再向dns查出其对应的ip地址,若查出的 ip地址不符合socket连接提供的远程ip地址,则postfix也会拒绝服务。此限制条件的拒绝码定义在 unknown_client_rejct_code参数(450)。实际上,reject_unknown_client确实可挡掉很多垃圾邮件,但是 挡掉的合法邮件可能更多,因为有很多网络并没有妥善维护他们的dns数据库,internet上一大半ip地址查不出prt记录,其中包括合法用户所在的 网络。
reject_unknown_hostname
如果helo命令提供的主机名称既没有a记录,也没有mx记录,则拒绝服务并返回unknown_hostname_reject_code参数指定的拒 绝码(450)。实际上,有许多客户端的helo所提供的主机名称不是完整形式,就会被这个条件挡在门外。
reject_unknown_recipient_domain
如果rcpt to命令提供的收件人地址,其网域部分查不出有效的nds a或mx记录,则以unknown_address_reject_code参数定义的拒绝码拒绝服务(450)
reject_unknown_sender_domain
如果mail from命令提供的寄件人地址,其网域部分查不出有效的dns a或mx记录,则以unknown_address_reject_code参数定义的拒绝码拒绝服务(450)
实际上,由于mail from地址是退信通知的收件地址,所以要求客户端提供一个已知的有效网域名称是非常合理的请求。一般合法用户应该都能够提供正确地址。而捏造mail from地址也是垃圾邮件发送者常用的伎俩之一,所以我们强烈建议你加上此限制条件。
上述四个限制条件都使用unknown_*_reject_code参数来决定拒绝码,而且这些参数的默认值都是450。如果你修改这些默认值, postfix会改用你指定的拒绝码,但是有一个例外;如果postfix从dns系统查不出数据,是因为dns server暂时性的故障(这种事常有)而非dns server真的回复查不出数据,则postfix扔会使用450拒绝码,而非你指定的值。
实时黑名单
实时黑名单(real-time blacklist,RBL)是一种专为抵制垃圾邮件而设计的网络服务,让smtp server可通过dns系统实时查询客户端是否为垃圾源。由于这种服务依附于dns系统,所以也称为dnsbl。在使用dnsbl服务之前,你必须先挑 选一家值得信赖的服务提供者,有些机构提供免费服务,但也有些管理员要求付费。postfix提供下列三种关于dnsbl的限制条件,分别用于支持不同技 术的dnsbl服务。
reject_rbl_client      rebprovider.domain
将客户端ip地址(例如1.2.3.4)颠倒顺序(成为4.3.2.1),搭配rbl管理员的网域名称(例如dnsbl.example.com)构成一 个主机名称(成为4.3.2.1.dnsbl.example.com),然后以此主机名称向dns系统查询,如果能查出一笔a记录,表示该ip地址已被 列入黑名单,则postfix会当场拒收邮件。
reject_rhsbl_client      rblprovider.domain
如果客户端的主机名称在指定的rblprovider.domain网域下有一笔a记录,则拒绝服务。
reject_rhsbl_sender      rblprovider.domain
如果寄件人的邮件地址的网域部分,在指定的rblprovider.domain网域下有一笔a记录,则拒绝服务。
应不应该使用dnsbl服务,是一个见仁见智的问题,虽然有些dnsbl管理员勤于维护他们的dns数据库,但由于宽带接入服务的兴起,使得很多垃圾邮件发送者有了新的藏身之处,而且更加捉摸不定,使得rbl抵制技术的效果大打折扣。
通用限制条件
除了针对特定信息的检查条件之外,postfix还提供了四个可用于任何过滤规则的限制条件,它们适合放在过滤规则的最后,作为该组规则的默认处理政策。
permit
批准收下邮件。postfix不再继续当前的过滤规则,但是会跳到下一组过滤规则
reject
无条件拒收。postfix不再继续处理任何过滤规则。
defer
婉拒请求,客户端被告知稍候再试。

模拟限制条件组合的检查流程
在目前所介绍的范围内,我们可以用一组简单的helo限制条件为例,模拟四种不同情况下的检查流程。假设smtpd_helo_restrictions过滤规则被设定成下列两项条件:
smtpd_helo_restrictions =
check_helo_access hash:/etc/postfix/helo_access
reject_invalid_hostname
其中,helo_access访问表的内容为:
greatdeals.example.com      reject
oreillynet.com            ok
现在,假设有四个客户端分别连接到postfix,并送出了四种不同的helo命令,让我们分别分析postfix在这四种状况下的反应:
helo example
第一个条件是check_helo_access,所以postfix先检查此条件指定的helo_access访问表。查表结果找不到指定的 example主机名称,所以它接着检查reject_invalid_hostname条件。由于example不是符合标准规定的完整主机名称,所以 postfix当场拒收。
helo greatdeals.example.com
postfix先检查check_helo_access条件指定的helo_access访问表,结果找到greatdeals.example.com的记录,而其对应动作是reject,因此,postfix当场拒绝收信。
helo oreillnet.com
postfix先检查check helo_access条件指定的helo——access访问表,结果找到oreillynet.com的对应动作是ok,所以postfix停止处理 smtpd_helo_restrictions的其余条件,接着检查smtpd_sender_restrictions过滤规则。
helo mail.ora.com
postfix先检查check_helo_access条件指定的helo_access访问表,结果找不到mail.ora.com,所以接着检查 reject_invalid_hostname条件;由于mail.ora.com是符合标准规定的主机名称。所以postfix继续检查 smtpd_sender_restrictions过滤规则。

smtp语法规范参数

smtp是相当宽松的协议,有些smtp client/server的对话过程甚至比协议本身要求更宽松。为此,postfix提供两个参数,让你自己决定是否要求严格遵守smtp协议的对话过 程与语法。第一个参数是smtp_helo_required,它决定是否要求smtp client以helo或ehlo动作为开场白。按照smtp rfc的规定,smtp clients连接到server后的第一句话必须是helo或ehlo。
默认情况下,postfix对客户端抱持宽容态度,容许客户端不严格遵循smtp协议。但如果你设定smtpd_helo_required = yes,而客户端见面不打招呼,则postfix将拒绝服务。
smtp rfc也明确规范了信封地址的格式,正常情况下,postfix几乎接受任何有意义的信封地址,但是,如果你设定了strict_rfc821_envelopes = yes,则没有提供正确格式地址的客户端将被挡在门外。
实际上,要求对方必须提供helo/ehlo或许是个好主意,因为大部分的客户端至少都会遵守smtp协议的基本对话过程。但并非所有客户端都提供符合标准格式的邮件地址,如果要求太严格,可能会错失一些合法邮件。

内容检查

直接让postfix将垃圾邮件过滤的最后机会,是检查邮件内容本身。postfix提供了四个检查邮件内容的参数:
header_checks检查标题
mime_header checks检查标题的mime相关字段
nested_header_checks检查夹带附件的标题
body_checks检查邮件的正文
内容检查的影响是全面性的,要么全部邮件都必须受检,否则就全部都不检查。也就是说,该阶段已经没有机会让特定寄件人或收件人绕过检查。
内容检查可能是阻挡垃圾邮件最有效的手段,但是如果你不熟悉正则表达式或者没有时间收集垃圾邮件样本来分析,你应该考虑使用专门检测垃圾邮件的外部过滤程序,例如spamassassin。
上述四个参数都需要你提供一个查询表,其中含有“模式”(pattern)与“动作”(action)。这些模式(即“正则表达式”)是用来比对邮件内容里的字符串,如果发现符合模式的字符串,postfix就执行对应的动作。默认的模式匹配原则是不区分大小写字母。

设定内容检查参数

在默认情况下,如果你没有设定mime_header_checks和nested_header_checks参数,它们将与 header_checks共享同一个查询表。如果你想将其区分开来,则必须分别提供不同的查询表给它们。设定检查参数时,必须先注明正则表达式的语法格 式(regexp代表postfix的标准正则表达式语法,pcre代表perl兼容的语法)以及模式表的完整路径。例如:
header_checks = regexp:/etc/postfix/header_checks
body_checks = regexp:/etc/postfix/body_checks
模式表的索引键是描述比对特征的正则表达式,此正则表达式本身必须放在一对分隔符(通常是/)之间,例如:
/match pattern/               reject
典型的header_checks模式表看起来类似下面这样:
/free mortgage quote/                reject
/repair your credit/                        reject my credit is very good
/take advatage now/                      reject
如果标题里出现任何上述字符串(机会最大的字段是subject:),则予以拒收。postfix会将拒收事件连同你提供的信息记录在日志文件里,客户端 也会见到你提供的信息。因此,如果有任何人寄信给你,表示有能力恢复你的信用记录,他将被拒绝,并得到“my credit is very good”这样的回复。

内容检查的响应动作
模式表的对应值,是符合比对条件后的响应动作以及一段可用可无的文字信息。如果比对条件成立,你指定的信息不仅会被传给客户端,也会被记录在日志文件;如果你没提供信息,则postfix使用默认信息。以下是可能的各种响应动作:
reject  message-text
如果模式匹配成功,则拒收邮件,并且将message-text传送客户端。
warn message-text
模拟拒收动作。不会真的拒收,只将message-text记录在日志文件中,并停止比对后续模式。当你想测试表达式的匹配效果时,可利用warn来避免误判合法邮件。
ignore
删除符合模式的标题字段或整行文字。这项动作常用来删除某些敏感信息。比方说,如果你不希望寄到外地网络的邮件包含内部网络的信息,就可利用这种办法。不 过,使用这项功能时请务必小心,因为大部分的标题字段都有其作用,有些更是smtp协议标准的硬性规定。此外,保留完整标题有助于追查电子邮件的问题。
hold message-text
将整封邮件放在保留队列(hold queue)。
discard    message
要求postfix假装接收邮件,但其实偷偷丢掉。有时候,专发垃圾邮件的软件根本不理睬响应码,即使你用5xx予以回拒,它还是照送不误,这会导致联机 时间比直接收下信息所需的时间更长。discard就是专门为应付这种技术而设计的机制。此外,discard也能有效解决迂回攻击的问题。而且,如果有 无辜用户的邮件地址被用来当成垃圾邮件发信者地址,也可以用discard来没收邮件,以免无辜受害者收到退信通知。
filter transport:nexthop
先将邮件排入队列,然后转交给指定的外部过滤程序。
模式表不同于访问表,你不能使用特殊响应码,也不能自定义限制条件。

模式匹配

执行标题检查时,标题里的每一个字段都要依序与模式表里的正则表达式匹配。如果字段内容跨越多行,在比对之前,它们会先被合并成一行,postfix先从 模式表里的第一个正则表达式开始比对,只要发现字段符合某正则表达式,整个比对过程就立刻结束,并执行该正则表达式对应的动作。只有在所有字段都不符合所 有模式的请客下,整个标题才算通过检查。
执行正文检查时,body_checks指定的模式表里的每一个正则表达式,依序与正文里的每一文字行比对,每次只比对一行。如果发现符合模式的字符串,整个比对过程立刻结束,执行此模式所对应的动作。
如果要比对的文字行超过长度上限,postfix会将它们拆成符合长度限制的段落,分段检查。文字行的字符数上限由line_length_limit参 数决定,其默认值为2048。如果标题的总长度超过header_size_limit(默认值为100k)postfix也是以同样原则分段处理。最 后,如果正文总长度超过body_checks_size_limit(默认值为50k),postfix不会检查超过限制的部分。这项限制相当有用,因 为可避免postfix去扫描整个文件。
有些管理员运用header_checks来进行简单的病毒过滤。例如,使用下列正则表达式可挡掉夹带危险文件的邮件:
/name ?="?.*.{bat|scr|com|dll|exe|hta|pif|vbs}"?/         reject
如果你的postfix系统要服务许多windows系统的计算机,上述模式或许能帮你的用户群减少不少困扰,但同时也阻断了“交流正常 程序文件”的机会。请注意,这个模式的防毒效果有限,因为我们还漏掉了一些扩展名,不足以阻挡所有windows可执行文件,况且有许多pc客户端不用扩 展名就可以直接运行文件。
下面是一个典型的body_checks模式文件的内容:
/increase your sales by/                      reject
/in compliance (with|of) strict/            reject
/lowest rates.*!/                                    reject
/[:alpha:]<!--.*-->[:alpha:]/                     reject suspicious embedded html comments
前两个模式很简单,不再解释。第三个模式挑出任何含有“lowest rates”字样且其后跟着任何文字(.*)以及一个感叹号(!)的字符串,例如“we have our lowest rates in 40 years!”)。最后一个模式检查是否有html注释嵌在字句中间,例如“via<!--ooxx->gra“。垃圾邮件发送者常用这种技 巧试图通过过滤程序,但是,这也成为垃圾邮件的绝佳特征,因为一般的正常邮件多半不包含html注释,就算有,也不会刻意夹在字句中间。
使用postmap工具可以测试写好的正则表达式。假设msg.txt是一个垃圾邮件样本文件,我们可用下列方式将它导入postmap:
postmap -q - regexp:/etc/postfix/body_checks < msg.txt
postfix会显示出符合模式的字符串,以及对应该模式的动作。
每个站点面临的垃圾邮件源都不太一样,你应当研究收到的垃圾邮件,根据你自己的研究结果来写出适当的过滤模式。编写正则表达式时一定要相当谨慎,如果设计 不当,可能会严重降低服务器的效率。另一个潜在的问题在于没有任何邮件可以绕过内容检查,即使邮件已通过所有smtpd_*_restrictions过 滤规则的检验,甚至已被纳入白名单,最后仍有可能被header_checks与body_checks挡在门外。
在你设计判别垃圾邮件的过滤规则时,请留心用户群之间需求与心态。有些人对垃圾邮件深恶痛绝,甚至宁愿承担较高的误判风险;有些人则宁可多收一些垃圾邮 件,也不愿意错失任何真实邮件。被你挡掉的化妆品广告邮件,有可能是某位女同事订阅的电子报。如果无法兼顾所有人的要求,且必须分别位不同用户设定不同的 过滤规则时,则最好不要在mta做这件事,应该考虑使用特殊的mda,例如procmail,maildrop,或任何能依用户类别来选择过滤规则的软 件。
倘若你真的希望在postfix解决不同用户的争议,则postfix提供了分级机制,可针对不同收件人使用不同的过滤规则。

自定义过滤条件组合

为了满足不同层次的观众,政府设计了电影分级制度;同样的,为了满足不同用户的需求,postfix也提供了分级制度,让你可依据用户的身份来选择适当的 过滤条件组合。postfix的分级机制称为“规范等级”(restriction class),这是非常强大的工具,让你能更灵活运用postfix的垃圾邮件过滤条件。如果你的用户需要不同松紧程度的过滤条件组合,或是有一两位用户 需要与众不同的过滤规则,投资时间研究如何设定规范等级决定是值得的。
具体做法如下:
1。 定义多组“规范等级”,每个等级都有自己的专属名称,不同的等级各由松紧不等的限制条件组合而成。
2、制作一个访问表,索引键是用户的标识信息(通常是邮件地址),对应值是该用户适用的限制等级的名称。
3、在一般的smtp_*_rrestrictions过滤规则中,加上一条检查访问表的条件。任何check_*_access条件都可以用来检查访问 表,换言之,你可以依据客户端(check_client_access)、寄件人(check_sender_access)或收件人 (check_recipient_access)来执行分级过滤。

规范等级实例

为了举例说明,假设我们有两组用户:一组是电信警察,以打击垃圾邮件发送者为职责,研究垃圾邮件是他们的专业;另一组人是八卦部队,如果让他们收到垃圾邮件,天下只会更乱而已。
很显然,这两组人不能共享相同的过滤规则,否则一定会出事。为了满足这两种极端的要求,我们拟定了两级规范,分别命名为“spamlover”与“spamhater”。所有规范等级的名称都必须列在smtpd_restriction_classes参数,像这样:
smptd_restriction_classes = spamlover, spamhater
接下来,我们当初怎样设定一般的smtpd_*_restrictions过滤规则,现在就可以怎样定义我们的规范等级。以下是spamhater的定义,其限制条件相当严格:
spamhater =
reject_invalid_hostname
reject_non_fqdn_hostname
reject_unknown_sender_domain
reject_rbl_client      nospam.example.com
下面是spamlover的定义,只有一个简单的permit(无条件批准)
spamlover = permit
当然,现实环境中不太可能遇到如此极端的情况,你应该视实际情况调整规范等级的定义,增加或减少某些限制条件。
现 在,我们已经完成新规范等级的声明与定义,下一步,我们要制作一个访问表,让postfix知道哪些人适合哪些规范等级。由于我们的规范等级是针对不同用 户而设计的,所以访问表的索引键是收件人的邮件地址,而对应值是用户适合的规范等级。假设这个访问表的名称是per_user_ube,它的内容看起来应 该类似这样:
per_user_ube

abelard@example.com         spamhater
heloise@example.com         spamlover
最后,要求postfix在审核收件人限制时,检查你指定的访问表:
permit_mynetworks
reject_unauth_destination
check_recipient_access hash:/etc/postfix/per_user_ube
一 切就绪后,每当外界有人写信给abelard@example.com,postfix先执行一遍正常的默认过滤规则,在遇到 check_recipient_access时,它会检查指定的收件人访问表,并查出abelard@example.com适用的规范等级为 spamhater,然后执行spamhater定义的限制条件。如果spamhater下的任何条件都返回reject,postfix就拒收邮件;否 则就将邮件交给适当的mda处理。外界写给heloise@example.com的邮件也是依照同样的过程来处理,如果postfix所执行的规范等级 为spamlover,会无条件收下任何邮件。

反垃圾邮件实例

至此,我们已经涵盖postfix的所有垃圾邮件的抵制机制,现在可以举一个具体实例来总结本章的讨论。由于每个站点面对的网络环境与实际需求都不一样,所以我们不可能设计一个面面俱到的配置文件,也无法给你太多具体建议。反垃圾邮件的main.cf配置文件样本
smtpd_restriction_classes =
spamlover
spamhater
spamhater =
reject_invalid_hostname
reject_non_fqdn_hostname
reject_unknown_sender_domain
reject_rbl_client   nospam.example.com
spamlover = permit
smtd_helo_required = yes
smtpd_client_restrictions =
check_client_access  hash:/ect/postfix/client_access
smtpd_helo_restrictions =
reject_invalid_hostname
check_helo_access hash:/etc/postfix/helo_access
smtpd_sender_restrictions =
reject_non_fqdn_sender
reject_unknown_sender_domain
check_sender_access hash:/etc/postfix/sender_access
smtpd_recipient_restrictions =
permit_mynetworks
reject_unauth_destination
reject_non_fqdn_recipient
reject_unknown_recipient_domain
smtpd_data_restrictions =
reject_unauth_pipelining
header_checks = /etc/postfix/header_checks
body_checks = /etc/postfix/body_checks
这 个例子需要好几个访问表,你应该分析实际收到的垃圾邮件,收集垃圾邮件发送者的ip或邮件地址,创建你自己的访问表。不过,就经验来 说,check_helo_access和check_sender_access的效果有限,阻挡不了太多的垃圾邮件。基本上,垃圾邮件发送者有无限多 的邮件地址与主机名称可以使用,每次你更新了访问表之后,他们又从别的地方冒出来,让你疲于奔命。况且,主机名称与发信者地址太容易捏造了,而且他们时常 假冒来自拥有大群合法用户的大型网站,使你防不胜防。
虽然挡不住精明的垃圾邮件发送者,但是阻挡垃圾邮件发送者的效果还挺不错。有些家伙不懂变 化,总是千篇一律的使用相同信息,对付这种连干坏事也没有脑筋的垃圾邮件发送者,访问表是最好的武器。有些在线营销服务发送信息真实的广告信,而且也遵守 规定的提供真实的选退机制,让你决定是否愿意继续收到广告信。然而,如果你不相信那些听都没有听过的公司的选退机制,你可用mail from或helo的信息来阻挡他们的广告信,而不要冒着让他们有机会证实你的邮件地址的风险。当然,有些站点恶名远扬,你完全不想再见到他们,不管他们 是否诚实、提供选退机制,你都可以直接挡掉它们的垃圾邮件。
此外,有许多垃圾邮件假冒它们来自某些小国家。如果你确定不可能会收到来自马尔代夫共 和国的合法邮件,你可以将该国的顶层网域名称填入访问表,一举阻断所有假冒来自该地址的垃圾邮件。然而,如果你的邮件系统服务很多用户,你或许不应该如此 武断,将你个人的独断意识强加在每位用户身上。焉知你的用户没有住在马尔代夫的亲戚?或是特别喜欢到该国度假?

给我留言

Copyright © 2011-2016 零下二十四度Theme By  Ality  京ICP备16007547号   关于本站

用户登录