网关的黑白名单越加越多,怎么调优才能既拦得住又不误杀?
「加个白名单」这句话在不同上下文里指的是完全不同的四件事。把它们混在一个管理界面、一套流程里,是名单最终失控的根本原因。必须先在概念上分开:
- 连接级阻断名单。在 SMTP 会话早期、基于源地址决定是否继续对话。特点是成本极低(还没有接收报文)、粒度极粗(整个 IP 或网段)、误判代价高(整个来源被拒)。
- 内容评分因子。参与综合判定,不单独决定结果。特点是粒度细、可叠加、单条因子的误判可以被其他因子抵消。
- 投递白名单(跳过检测)。它绕过检测。这是四类中唯一会降低安全性的一类。
- 认证豁免。允许某来源跳过认证或对齐要求。它与投递白名单不同,影响的是身份验证而非内容检测,但危险性同样高。
管理上的第一步是给每条名单条目标注它属于哪一类。现实中大量条目是运维在处理某个具体投诉时随手加的,加的时候并不清楚自己动的是哪一层。Postfix SMTPD_ACCESS_README 官方文档 对访问控制表在 SMTP 会话不同阶段的作用位置有系统说明,是理解这一分层的很好参考。
RFC 5782 定义了基于 DNS 的黑名单与白名单的查询格式与约定,包括为了让运维方能验证列表是否正常工作而规定的测试地址。理解这个机制之后,选型时真正该问的问题是:
- 收录政策是什么?是基于实际观测到的滥用行为,还是基于策略性判断(例如整段动态地址、整个国家或地区)?后者的误判风险显著更高。
- 移除政策是什么?被误收录后多久能被移除、流程是否公开、是否收费。一个没有清晰移除流程的列表不应当用于阻断。
- 更新频率与陈旧条目的处理?长期不清理的列表会累积大量已经易主的地址。
- 可用性与降级行为?这一条最容易被忽略:当列表服务不可用或返回异常时,你的网关是「全部放行」还是「全部拒绝」?某些错误配置下,列表服务返回通配结果会导致所有邮件被拒。必须明确配置降级行为,并做过实际验证。
不要把「拦截量大」当成选型依据。拦截量大既可能说明列表有效,也可能说明它过于激进。真正该看的是误判率,而误判率只能通过自己环境的实测得到。
也不要对单一列表形成强依赖。合理做法是:少数几个政策保守、移除流程清晰的列表用于直接阻断;其余列表只作为评分因子参与综合判定。M3AAWG 已发布文档索引 中有若干关于名单使用与滥用处理的实践文档可作参考。
一条投递白名单的实际含义是:「来自这个来源的邮件,无论内容如何,都不检测。」如果这样表述,多数人不会轻易批准;但写成「把某某合作方加个白名单」,就变得很容易通过。
白名单的三个典型失效路径:
- 被白名单的来源自身失陷。合作方的邮件系统被攻破后,你的白名单就是一条直达的绿色通道。
- 基于可伪造的标识做白名单。基于
From信头域或显示名的白名单尤其危险,因为这两者都是可以任意填写的。白名单如果必须存在,应当基于经过认证的标识——例如通过且对齐的 DKIM 签名域(结合 RFC 7489 的对齐要求),而不是基于声明的地址。 - 永不过期。为三年前一次临时故障加的条目,至今仍在生效,且已无人知道它为什么存在。这就是一个永久后门。
据此,白名单的管理要求应当明显严于黑名单:
- 每条必须有申请人、业务理由、有效期。无有效期的条目一律不批。
- 到期自动失效而不是自动续期。需要继续使用的重新申请。
- 尽可能缩小范围。白名单应当限定到具体收件人或具体邮件类型,而不是全局放行。
- 定期全量复核。NIST SP 800-53 Rev. 5《Security and Privacy Controls for Information Systems and Organizations》 在配置管理与访问控制相关的控制族中对基线配置与最小权限有系统化要求,白名单复核可纳入同一节奏。
- 白名单变更要有独立审计。它是最值得被监控的一类配置变更。
这是一个影响深远但经常被配置反了的点。SMTP 提供了在会话内直接拒绝的能力,RFC 5321 定义了响应码的语义:5 开头表示永久失败,4 开头表示临时失败(发送方应当稍后重试)。RFC 3463 进一步定义了增强状态码,用于更精确地表达失败原因。
在会话内拒绝的好处是决定性的:
- 拒绝责任留在发送方。由发送方的系统生成退信并告知其用户,这是正确的责任归属。
- 不产生退信散射。如果先接收再退信,而信封发件人是伪造的(这在垃圾邮件中是常态),那么退信会发给一个无辜的第三方。大量这样的退信会让你自己被列入阻断名单,从受害者变成滥用源。
- 误判可被发送方立即感知。合法发送方会立刻看到明确的拒绝原因,而不是邮件石沉大海。
配套要求:
- 拒绝原因文本要可读、可行动。写清楚是什么策略拒绝的,以及如果认为是误判该联系哪里。「Message rejected」这样的文本对解决问题毫无帮助。
- 区分永久拒绝与临时拒绝。对不确定的情况用临时失败,让发送方重试,为人工复核留出时间;只有确信的才用永久拒绝。
- 确实需要生成退信时,遵循 RFC 3464 定义的 DSN 格式,使发送方系统能自动解析。
任何检测系统都有误判。决定运维质量的不是误判率本身,而是误判被发现和被修正的速度。缺少这套机制时,用户的应对方式是绕过系统——改用个人邮箱、改用即时通讯发文件,这比误判本身危害大得多。
需要建立的四件事:
- 用户可见的隔离区与自助释放。让用户能看到自己被隔离的邮件并自行释放低风险类别。这一项能消解绝大多数误判投诉,且成本很低。要注意的是高风险类别(如含可执行内容的附件)不应允许自助释放。
- 明确的申诉入口与响应时限。入口要在通告与隔离通知中反复给出。
- 误判样本回流。被释放的邮件应当自动成为调优的输入,而不是处理完就丢。没有回流机制,同一个误判会反复发生。
- 对外可达的滥用与联系入口。RFC 2142 定义了
abuse@与postmaster@等标准职能邮箱;当外部发送方被你误拒时,这是他们唯一能找到你的方式。必须确保这些地址真实有人处理,且不被自家策略拦截。如需接收结构化的滥用报告,RFC 5965 定义了相应的可扩展格式。
名单与策略的调整往往在压力下进行——某个重要邮件被拦了、某类垃圾邮件突然涌入。压力下的变更最需要约束。
- 一次只改一件事。同时调整多项后无法判断效果来自哪一项,也无法精确回滚。
- 先灰度。新策略先作用于一小部分收件人或先只记录不拦截,观察一个完整业务周期后再全量。「只记录不拦截」这个中间态的价值被严重低估了——它能在零风险的前提下暴露绝大多数误判。
- 每次变更都要有记录:改了什么、为什么、谁批的、如何回滚。回滚方法必须在变更前就写下来,而不是出事后再想。
- 定期做减法。规则库只增不减必然走向不可维护。设定固定的复核节奏,清理无有效期的条目、长期未命中的规则、以及已被更通用规则覆盖的条目。
- 把收件人侧的个性化规则与网关策略分开管理。RFC 5228 定义的 Sieve 提供了标准化的用户级过滤语言,用户的个性化需求应当在这一层解决,而不是通过在网关上加全局例外来满足单个用户。这是控制网关规则膨胀最有效的一条组织性措施。
参考:RFC 5782《DNS Blacklists and Whitelists》,J. Levine,2010 年 2 月 ;RFC 5321《Simple Mail Transfer Protocol》,J. Klensin,2008 年 10 月 ;RFC 3463《Enhanced Mail System Status Codes》,G. Vaudreuil,2003 年 1 月 ;RFC 3464《An Extensible Message Format for Delivery Status Notifications》,K. Moore、G. Vaudreuil,2003 年 1 月 ;RFC 5965《An Extensible Format for Email Feedback Reports》,Y. Shafranovich 等,2010 年 8 月 ;RFC 2142《Mailbox Names for Common Services, Roles and Functions》,D. Crocker,1997 年 5 月 ;RFC 7489《Domain-based Message Authentication, Reporting, and Conformance (DMARC)》,M. Kucherawy、E. Zwicky 编,2015 年 3 月 ;RFC 5228《Sieve: An Email Filtering Language》,P. Guenther 编、T. Showalter,2008 年 1 月 ;M3AAWG 已发布文档索引 ;Postfix SMTPD_ACCESS_README 官方文档 ;NIST SP 800-177 Rev. 1《Trustworthy Email》 ;NIST SP 800-53 Rev. 5《Security and Privacy Controls for Information Systems and Organizations》
