级别: 初级
Brian Goetz, 首席顾问, Quiotix Corp
2002 年 9 月 17 日
多年来不请自来的电子邮件问题日渐严重地困扰着人们,但现在有了解决这一问题的办法。在本文中,David讨论并比较了几种主要的方法来自动消除不需要的电子邮件,同时,还介绍和测试了一些采用这些方法的流行的工具。
不道德的电子邮件发送者可以不费多大成本或根本不费成本地分发大量消息,而正常用户却被迫花费一些时间和精力从他们的邮箱中清除这些欺诈性的或不需要的邮件。在本文中,我描述了几种方法,这些方法用计算机代码来帮助消除不请自来的商业性电子邮件、病毒、特洛伊木马和蠕虫病毒以及怀有恶意的欺诈性电子邮件与其它一些不希望收到的和令人烦恼的电子邮件。在某种意义上,消除垃圾邮件最好的终极解决方案可能是通过立法来制止这种行为。然而,在此期间,即在法律的进步(如果有过的话)还未解决公众不断所受到的困扰之前,可以用代码开发一些工具作为过渡性的解决方案来处理这类问题。
从技术角度考虑 — 但也是常识 — 我们所说的“垃圾邮件”的含义通常比“不请自来的商业性电子邮件”的范畴要广;垃圾邮件包含了所有我们不需要的以及没有明确表明要发送给我们的电子邮件。这样的消息其本身并不总是具有商业性,而对于有些消息,很难说是我们所需要的。例如,我们不想感染上病毒(即使来自不谨慎的朋友);通常也不想收到连锁电子邮件(chain letter),即使这些邮件不是来要钱的;既不想收到来自陌生人的诱劝性的消息;也不想收到完全是欺骗性的邮件。在任何一种情况中,都能很清楚地确定邮件是否为垃圾邮件,许许多多人都曾收到过这样的邮件。
垃圾邮件的问题是,它会将正常的电子邮件淹没。以我的经历为例,几年前,我偶尔会收到了一封不请自来的消息,大概每天有一封或两封。与此相对照,在这个月中的每一天,我所收到垃圾邮件的数目是合法邮件的 很多倍。平均大概每收到 1 封正常的邮件就会得到 10 封垃圾邮件。从某些方面讲,我与一般人不同 — 作为一名公众撰稿人,我的电子邮件地址是公布给大家的;而且,我欢迎那些未曾谋面之人就我所发表的文章以及我的软件库给我发电子邮件,并且也确实经常收到这方面的电子邮件。遗憾的是,来自陌生人的电子邮件 — 谁也不知道这些邮件使用的是什么电子邮件应用程序、哪种 OS 以及本地自然语言等 — 不会马上明显地显示出它的目的;垃圾邮件发送者设法在这种含糊状态之下来发送他们的消息。对我来讲,我的时间是宝贵的,特别是每时每刻都有许多工作要做。
隐藏联系人信息
对于一些电子邮件用户,避免垃圾邮件的非常简单且合理的方法(而且这种方法也足够应付这个问题)是,只要牢牢地保护好电子邮件地址,不泄漏出去。对于这些人,只将电子邮件地址告诉给那些经过挑选的、可信的对方。另外需要注意的是,挑选电子邮件地址时,避免选用那些容易被猜出的名字以及选用字典里的单词,在将地址张贴到公共场合时,可以伪装地址,我们都见过巧妙地编码成以下形式的电子邮件地址:“<mertzHIDDEN@NOSPAM.gnosis.cx>”或“echo zregm@tabfvf.pk | tr A-Za-z N-ZA-Mn-za-m”。
除了隐藏地址之外,隐蔽的电子邮件使用者还常常使用一个或多个免费的电子邮件服务,他们将这些地址作为“用完即弃”的地址。如果自己对对方半信半疑但需要与之进行电子邮件通信,则可以将一个临时的电子邮件地址用上几天,然后,只要有垃圾邮件出现(自此之后,可能会有垃圾邮件源源不断地发送到此地址),就废弃这个地址。要保护好“只有心腹知己 ”才能知道的 真正地址。
我做过一次非正式的调查,在 Web 公告板(Web-board)、邮件列表、Usenet 等上讨论了垃圾邮件问题,我发现,有了这些基本的预防性措施,就足以保护这类电子邮件用户。
然而,对于我 — 以及对于其他许多人 — 这些方法根本不可能完全避免垃圾邮件。我有一个公开的电子邮件地址,出于许多理由,我必须公开这个地址。在我能控制的范围内, 确实利用了多个地址来检测“漏网”垃圾邮件的来源;但不幸的事实是,大多数垃圾邮件发送者可以用与合法邮件发送者相同的方法获取到我的电子邮件地址:象这篇文章一样,从文章的顶部获得地址列表,以及其它有关我地址方面的公开信息。
过滤软件一瞥
本文从特定的角度来研究过滤软件。对于正确识别垃圾邮件和合法消息这方面,我想了解这些不同的方法做得如何。为了回答这个问题,我没有将注意力特别放在配置过滤器应用程序,使之能使用各种“邮件传送代理(Mail Transfer Agents (MTA))”的细节上。在 MTA(譬如,Sendmail、QMail、Procmail、Fetchmail 以及其它邮件程序)的最佳配置方面,确实存在着许多奥妙。而且,许多电子邮件客户机都有自己的过滤选项和插件 API。幸运的是,我研究的大多数过滤器都带有相当出色的文档,里面讲述了如何配置它们以与各种 MTA 协同工作。
为了测试,我开发了两组消息集:垃圾邮件和合法邮件。实际上这是我从前几个月收到的邮件中抽取出的两组消息,但我又向其中添加了一个重要的消息子集,在这些消息中,有的来自几年前,这就扩大了测试范围。我不能确切地知道,在下个月的电子邮件中会包含什么,但过去的邮件已为以后的趋势提供了极好的线索。这听上去似乎很神秘,但我的意思是,我不希望把这些模式只限制于一些单词、短语和正则表达式等,这些也许能描述出最近电子邮件的特征,但却不能概括成这两种类型。
除了这两组电子邮件,我为那些工具开发了培训(training)消息集,以“了解”什么是垃圾邮件,什么不是垃圾邮件消息。这些培训消息集比较大,而且有一部分是与测试集不相交的。测试集中包含略少于 2000 条的垃圾邮件消息,合法消息的数目与此大致相同。而培训集中的消息是它们的两倍。
关于测试,这里有必要强调一下一般性的注意事项。在垃圾邮件过滤器中的“误否认”(False negatives)仅意味着一些不需要的消息进入了邮箱。这不是一件好事,但其本身没有多可怕。“误承认”(False positive)是指合法消息被误判为垃圾邮件。这可能 非常糟糕,因为一些合法邮件实际上很重要,甚至非常紧急,有时尽管这些消息是一些聊天性质的邮件,但我们也不希望丢失它们。大多数过滤软件能让您将受拒的消息保存在临时文件夹中,等待您去查看 — 但如果需要查看的文件夹中充斥着大量的垃圾邮件,那么这个软件的实用性会因此而削弱。
1. 基本的结构化文本过滤器
我所使用的电子邮件客户机能够根据特定邮件头域、一般性邮件头和/或正文中的简单字符串来对到来的电子邮件进行排序。这个功能非常简单,甚至不包含正则表达式匹配。几乎所有的电子邮件客户机都有这样的过滤能力。
在过去几个月中,我开发了少量的文本过滤器。这些少量的简单过滤器能正确捕获我所收到垃圾邮件中的 80%。遗憾的是,这些过滤器的“误承认”的发生率比较高 — 以至于我不时地需要手工来检查垃圾邮件文件夹中的 某些邮件。(我将可能的垃圾邮件进行分类,放在几个不同的文件夹中,然后保存它们以形成消息语言资料库(corpora)。)虽然各个用户之间具体的细节会有所不同,但对大多数读者来讲,这个通用的模式是很有用的:
- 集合 1:一些人或邮件列表在他们的邮件头上做了一些有趣的手脚,使得它们与众不同。我捕获邮件头中的某些内容(通常是 From:),并将其放在“白名单(whitelist)”中(“收件箱”或其它文件夹)。
- 集合 2:我执行以下垃圾邮件过滤器(没有按特定的顺序):
- 识别特定的恶意邮件发送者。
- 查找作为 From: 邮件头的“<>”。
- 查找邮件头中的“@<”(出于许多原因,许多垃圾邮件都有这个标记)。
- 查找“Content-Type: audio”。我不需要这个,只有 virii 病毒需要(具体情况因人而异)。
- 在邮件头中查找“euc-kr”和“ks_c_5601-1987”,我不懂这种语言,但出于某些原因,我收到了 大量韩国垃圾邮件(当然,对于真正的韩国读者,这条规则恐怕不太适合他)。
- 集合 3:存储那些已知是合法地址的消息。我有几条这样的规则,但它们都仅仅与文字 To: 域相匹配。
- 集合 4:查找那些在邮件头中具有合法地址,但通过上一个 To: 过滤器没有捕获到的消息。我发现,只要我的邮件地址出现在 Bcc: 域,其中有一串按字母顺序排列的地址(譬如,mertz1@……、mertz37@……等)时,那这封邮件肯定是不请自来的邮件。
- 集合 5:到此,所剩下的可能就是垃圾邮件(它可能有伪造的邮件头以避免被识别出发送者的身份)。
2.“白名单”/验证过滤器
对于垃圾邮件的过滤,有一种主动性相当强的技术,我想称之为“白名单加自动验证”方法。这里有几种工具可以实现带验证的“白名单”:TDMA 是一个深受大家喜爱的多平台开放源码工具;ChoiceMail 是一个针对 Windows 的商业性工具;其它大多数似乎都比较初级。(请参阅本文后面的 参考资料,那里有一些链接。)
“白名单”过滤器连接到 MTA,只有当接收者显式地同意接收,才会将邮件传到收件箱。其它消息会产生一个特殊的质询(challenge)响应给发送者。“白名单”过滤器的响应包含某种唯一的可以识别原始消息的代码,譬如,一个散列或序列标识。这个质询消息包含让发送者答复的指示,以便将其加到“白名单”中(这个响应消息必须包含由“白名单”过滤器生成的代码)。几乎所有的垃圾邮件信息中的回复地址信息都是伪造的,所以这个质询通常没有人会收到;但即便那些垃圾邮件发送者提供了有用的回复地址,但他们往往不会响应这个质询。当合法的发送者答复了这个质询之后,会将她/他的地址添加到“白名单”中,以便将来来自同一地址的消息会自动地通过检查。
虽然我没有用过这些工具,而只是自己做了些实验,但我认为,“白名单”/验证过滤器几乎可以 100% 地将垃圾邮件消息阻挡在外面。可以想象,垃圾邮件发送者会开始在他们的系统中加一个质询响应,但只要稍微使质询消息变得复杂些,就可以解决这个问题(例如,要求对代码做一点小小的人为改动)。而且,如果垃圾邮件发送者响应了质询,那么就会使那些寻求合法地抵御垃圾邮件的人们可以更容易地跟踪到他们。
“白名单”/验证过滤器这种做法给合法的发送者带来了额外的负担。由于有些通信者可能出于各种原因而无法响应质询,所以会带来“误承认”这种情况。在最好的情形下,合法发送者只需花费一点点精力即可。但在以下情况,发送者可能无法发送他们合法的消息:发送者具有不可靠的 ISP,防火墙的要求过于严格,发送者具有多个电子邮件地址,不能够理解英语(或者质询所使用的语言),或者发送者只是忽略了质询以及不想被质询所干扰。而且,有时合法的“通信者”根本不是人,而是不能够响应质询的自动响应系统。“白名单”/验证过滤器可能需要额外花精力来处理邮件列表注册、在线购买、网站注册以及其它“自动通信”。
3. 分布式适应性黑名单
垃圾邮件往往被定义为发送给大量接收方的邮件。实际上,几乎很少有垃圾邮件被定制为发送给个别接收方。然而,在缺少预先过滤的情况下,每个垃圾邮件的接收者必须按自己的“Delete”按钮来删除垃圾消息。分布式黑名单过滤器会让一个用户的“Delete”操作去警告其他许多用户,注意这个垃圾邮件消息。
象 Razor 和 Pyzor(请参阅 参考资料)这样的工具运行在服务器一端,服务器上存储了一些已知垃圾邮件的摘要。当 MTA 收到一条消息时,会调用分布式黑名单过滤器来确定这条消息是否是已知的垃圾邮件。这些工具运用一些智能化的统计技术来创建摘要,使得在垃圾邮件作了微小的变动或自动的变化(或仅仅是由于传输路由的变化而导致邮件头的更改)时,也不会防止识别消息的身份。此外,分布式黑名单服务器的维护者经常会专门创建一些“蜜罐”地址,以引诱垃圾邮件(但从不针对合法的通信)。在我的测试中,发现用 Pyzor,从 没有出现“误承认”这类情况。我认为用其它类似的工具(如 Razor)也不会出现这样的情况。
对此有些常识。即使那些有不良企图的发送者可以篡改合法消息,他们也不可能让 我的好消息样本向服务器报告 — 通常只有垃圾邮件是广泛分发的。 可以想象,被大量发送但又是合法的消息(譬如,developerWorks 时事通讯)可能会导致错误报告,但分布式黑名单服务器的维护者几乎肯定会检测到这一点,并快速地纠正这样的问题。
然而,正如由下面的 汇总表所显示,使用分布式黑名单时发生“误否认”的频率要比其它我所测试的技术多很多。Pyzor 的作者推荐将这个工具与其它技术相 结合使用,而不是作为单独的防线来抵御垃圾邮件。虽然,这似乎合乎情理,但对于识别邮件是否为垃圾邮件这一点,事实上还不清楚这样的组合过滤技术是否比单独使用那些技术要强。
此外,由于分布式黑名单需要与服务器进行对话以执行验证,所以,在对我的语言资料库做测试时,Pyzor 的执行效率要比其它技术慢得多。对于测试小流量的消息,这不是大问题,但对于高容量的 ISP,这可能是个问题。我还发现,每一千条查询中,总会出现几次网络超时,所以,我的结果有一些“错误”(error),而不是标出“spam”(垃圾邮件)或“good”(合法邮件)。
4. 基于规则的评定
在基于规则的垃圾邮件过滤技术方面, SpamAssassin 是最受大家喜爱的工具,它处于遥遥领先的地位。还有其它一些工具,但它们要么没有得到广泛地使用,要么没有得到积极的维护。对要识别的消息,SpamAssassin(及其它类似工具)评估了大量的模式 — 大多数是正则表达式。如果有匹配的模式,则增加消息分数,否则,则减少消息分数。如果消息分数超过某一特定的阈值,则将其视为垃圾邮件而过滤它;否则认为是合法。
一些评定规则基本上稳定不变 — 例如,伪造的头和自动执行的 JavaScript,几乎总是垃圾邮件的标志。因为垃圾邮件发送者所开发出的产品和诡计在不断变化,所以需要更新其它一些规则。今天的垃圾消息中,伟哥和非洲独裁者的后继者们也许还风行一时,但明天一些新品种的蛇油药品或色情作品可能会将挤占它们的位置。随着垃圾邮件的发展,SpamAssassin 也必须发展,以跟上它们的步伐。
SpamAssassin 的自述文件中有下列非常有力的声明:
在最近的测试中,SpamAssassin 区分垃圾邮件和非垃圾邮件的正确率达到了 99.94%。以后,SpamAssassin 一直会做得越来越好!
我的测试显示,它没有达到这个水平。根据我的语言资料库,SpamAssassin 大约会发生 0.3%“误承认”和 19%“误否认”的情况(这一比率非常高)。公平而论,这只是评估基于规则的过滤器,而没有针对分布式黑名单做选择性的检查。此外,我的垃圾邮件语言资料库中不都是纯的垃圾邮件 — 它还包括大量可能是病毒的附件(我没有打开这些附件做确认,但我知道它们不是我认可的消息)。SpamAssassin 的 FAQ 对查找病毒作了免责声明;而另一方面,在查找病毒方面,以下技术做得更好,所以,这份免责声明并不是那么引人注目。
在速度方面,SpamAssassin 比分布式黑名单运行得更快,因为分布式黑名单需要查询网络服务器。但它的速度还是远低于下面统计模型(使用本机数据结构,用解释型的 Python 编写的)的非优化版本。有关 SpamAssassin 的优缺点,请阅读“ Stamp out spam with SpamAssassin”( developerWorks,2002 年 9 月)。
5. 贝叶斯(Bayesian)单词分布过滤器
Paul Graham 于 2002 年 8 月写了一篇极具争议的文章。在“A Plan for Spam”(请参阅本文后面的 参考资料)中,Graham 提议建立垃圾邮件和非垃圾邮件单词的贝叶斯概率模型。Graham 的文章或者其它任何有关统计和概率的一般性文章都详细讲述了数学方面的背景知识,比我在这里讲得更透彻。
其大体思想是,在已知的垃圾邮件中,一些单词出现的频率较高,而在合法消息中,另一些单词出现的频率较高。运用一些众所周知的数学知识,对于每个单词,可以生成一个“垃圾邮件指示性概率”。根据消息中所包含的一组词,可以用另一个简单的数学公式来确定文本消息的整体“垃圾邮件概率”。
Graham 的想法有以下几个值得注意的好处:
- 可以从已分类消息的语言资料库中自动生成过滤器,而不需要人花费精力来制订规则。
- 可以根据个别用户特有的垃圾邮件和合法消息来进行定制。
- 可以通过少数几行代码来实现这个想法。
- 运行情况出奇得好。
乍一看,似乎这样的猜想合乎情理:即,象 SpamAssassin 这样用手工调整和耗费大量人力开发的规则要比漫无目的的自动方法更能准确地的预测出垃圾邮件。事实说明这种猜想完全错误。基本上,统计模型仅比基于规则的方法要好。附带的好处是,Graham 样式的贝叶斯过滤器还是比 SpamAssassin 更快和更简单。
在 Graham 的文章发表的这些天里 — 也许就在数小时里,许多人同时开始实现这个系统。我出于测试目的,使用了由我的通信者 John Barham 所创建的 Python 实现。我感谢他给我提供了这个实现。不过,由于数学原理是如此之简单,以至于每个其它的实现大都相同。
有一些数据结构和存储技术的问题会影响到各种工具的运行速度。但事实上预测的精确性取决于很少几个因素 — 最关键因素可能是所使用的词法技术,这些因素大都用来消除虚假的随机字符串。Barham 的实现仅在一个小的集合中(字母数字加一些其它字符)查看相对较短和不相交(disjoint)的字符序列。
6. 贝叶斯三元模型(trigram)过滤器
贝叶斯技术建立在单词模型上,其工作良好。这种单词模型的缺点之一是,电子邮件中采用的“单词”的数量实际上是无限制的。这个事实可能与我们的直觉相反 — 认为一旦全部包括了几乎所有的英文单词,您就可以一劳永逸,这似乎很合乎情理。从我以前对全文本索引的研究了解到,这完全是不现实的;“与单词类似的”字符序列的数量可能是接近无限,新的文本会不断地产生新的序列。对电子邮件来说,尤其是这样,电子邮件包括消息标识、内容分隔符、UU 和 base64 编码等等任意的字符串。从模型中丢弃单词有多种方式(最简单的方式是只丢弃出现频率非常稀少的单词)。
我决定研究一下,对于贝叶斯垃圾邮件过滤器,一个绝对有限的模型空间究竟工作得有多好。我明确地决定,我的概率模型使用三元模型,而不是“单词”。当然,这个想法不是凭空而来的;对于语言识别/区分、英语的密码唯一长度、模式频率和相关领域所进行的大量研究极力推荐将三元模型作为一个良好的单元。
沿着这条思路,我做了几个决定。其中最重要的选择是确定三元模型是什么。虽然这比识别一个“单词”要稍微简单些,但这完全是一种幼稚的方法 — 查找三字节的每个(重叠)序列的方法不是最优化的。尤其考虑到高位字符 — 虽然在多字节字符集(换句话说,CJK)出现的频率相对较高 — 会使三元模型的空间比只在 ASCII 范围中查找要大得多。进一步将三元模型空间限制在低位字符会产生较小的空间,但整体结果不是很好。
对于我的三元模型分析,我只利用了高差分三元模型作为消息分类器。但我只是用试错法(trial and error)才达到了“垃圾邮件”和“合法”三元模型所选定的数目。对垃圾邮件,我还用了临界概率,而不是任意概率:我发现了一个有趣的现象,“合法”语言资料库中没有一条消息的垃圾邮件概率是超过 .0071 的,而在 .99 概率范围内,只有两个“误承认”的情况。然而,将临界概率从最初的 0.9 降到 0.1,可以使我在“垃圾邮件”语言资料库中捕获更多的消息。出于速度方面的考虑,从每个候选消息中挑出不多于 100 个“令人感兴趣”的三元模型 — 改变这个数目,结果可能略微会有所变化(但不是很明显)。
结束语
给出了前面所描述的测试方法,让我们看一下具体的测试结果。在速度方面,虽然我没有定量的数据,但这张表是按照速度顺序来安排的,从最快到最慢。三元模型较快,Pyzor(网络查询)较慢。在评估技术中,正如我所说,我认为“误承认”这种情况最差,而“误否认”这种情况只是稍微有点差。每个单元中的数量表示,在对每个电子邮件(合法邮件和垃圾邮件中)正文所测试的每种技术,正确识别出的消息和错误识别出的消息的数目的对比。
表 1. 垃圾邮件过滤技术量化的准确度
技术 |
合法邮件语言资料库 (正确识别 vs.错误识别) |
垃圾邮件语言资料库 (正确识别 vs.错误识别) |
"The Truth" |
1851 vs.0 |
1916 vs.0 |
三元模型 |
1849 vs.2 |
1774 vs.142 |
单词模型 |
1847 vs.4 |
1819 vs.97 |
SpamAssassin |
1846 vs.5 |
1558 vs.358 |
Pyzor |
1847 vs.0(4 个错误) |
943 vs.971(2 个错误) |
参考资料
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文.
- TDMA 主页提供了更多有关“标记消息发送代理( Tagged Message Delivery Agent)”的信息。
- 您可以从 DigitalPortal Software 了解到更多有关 ChoiceMail的信息。
- Pyzor 是基于 Python 的分布式垃圾邮件目录/过滤器。
- Vipul 的 Razor 是一个非常流行的分布式垃圾邮件目录/过滤器。其它一些过滤器工具(譬如,SpamAssassin)可以随意地调用 Razor。
- SpamAssassin是最流行的基于规则的垃圾邮件过滤器。请阅读“ 用 SpamAssassin 消灭垃圾邮件”( developerWorks,2002 年 9 月),以了解更多这方面的内容。
- 请阅读 Paul Graham 的文章“ A Plan for Spam”。
- Eric Raymond 的“ bogofilter”快速实现了 Paul Graham 的想法。除了使用一些有效的数据表示和存储策略外,在确认什么可形成有意义的单词方面,bogofilter 尝试更智能化些。
- 我自己的 基于三元模型的分类工具仍处于早期 alpha 测试或原型级别。然而,欢迎您在其基础上做进一步的开发。这些工具是公开的,就象我在 developerWorks 文章中提到的所有工具一样。
- Lawrence Lessig 写了一些书和文章,对他戏称的“西海岸代码”和“东海岸代码”— 换句话说,指在华盛顿特区(以及其它地区)通过的法律和在硅谷(以及其它地方)所编写的软件 — 进行了深刻的对比。就 Lessig 的 Code and Other Laws of Cyberspace,我写了一篇 短评。要更多地研究这方面的内容,请参阅 Lessig 的网站。
- 在 developerWorks的 Linux 专区,查找 更多有关 Linux 的文章。
关于作者
|