Docker 的价值在于把复杂的服务封装成可快速部署、可独立升级的容器,而反垃圾邮件系统恰好是这类复杂服务的典型代表。一套完整的反垃圾方案通常涉及内容过滤引擎、病毒扫描、DNS 黑名单查询、统计模型训练等多个组件,直接在宿主机上安装不仅依赖冲突多,而且升级时牵一发动全身。用容器化的方式来做,每个组件各司其职,出问题可以单独重启和替换,整体运维难度大幅下降。本文将从原理讲到落地,介绍如何用 Docker 搭建一套实用的反垃圾邮件体系。

垃圾邮件识别的核心技术原理
在动手部署之前,先理解反垃圾系统依赖的几项关键技术,这有助于后续调参和排查误报。第一类是 DNS 黑名单查询(DNSBL),邮件服务器在收到连接请求时,会把对方 IP 反向拼接后向黑名单服务发起 DNS 查询,如果命中说明该 IP 曾大量发送垃圾邮件。这类查询成本极低,能在连接阶段就拦截大量恶意来源。
第二类是内容统计过滤,代表是贝叶斯过滤器。系统通过预先学习垃圾邮件和正常邮件的样本,统计各类词语出现的概率,收到新邮件时综合计算它属于垃圾邮件的概率。贝叶斯过滤的优势在于越用越准,因为每个用户的邮件环境不同,自我学习的模型比通用规则更贴合实际。
第三类是协议层的身份验证,包括 SPF、DKIM 和 DMARC 三件套。SPF 记录声明哪些 IP 有权代表该域名发信;DKIM 通过密钥对邮件内容做数字签名,收件方验证签名判断邮件是否被篡改;DMARC 则把前两者的结果和处置策略绑定起来。大量钓鱼邮件伪造发件人,这类校验能直接识破。此外还有灰名单技术,首次收到的发件方先被临时拒绝,正常的邮件服务器会重试,而多数垃圾邮件软件不会,简单粗暴但有效。
为什么选择 Rspamd 以及镜像选型
开源反垃圾引擎里,SpamAssassin 老牌但性能一般,单进程架构在高并发场景容易成为瓶颈;Rspamd 用 C 语言编写,事件驱动架构,支持多核并行,性能明显更好,而且自带 Web 管理界面,可以直观查看每封邮件的打分明细。官方在 Docker Hub 上提供 rspamd/rspamd 镜像,更新频繁,是容器化部署的首选。
病毒扫描方面,ClamAV 镜像需要与 Rspamd 配合,通过 clamd 套接字方式通信。常用的做法是使用 clamav/clamav 官方镜像,并让两个容器共享一个卷,Rspamd 通过 Unix socket 调用 ClamAV 扫描附件中的恶意负载。
下面是一个典型的 Docker Compose 编排示例,包含 Rspamd 和 ClamAV 两个服务:
version: "3.8"
services:
rspamd:
image: rspamd/rspamd:latest
container_name: rspamd
hostname: rspamd
volumes:
- ./rspamd:/etc/rspamd/local.d
- ./dkim:/var/lib/rspamd/dkim
- ./clamsock:/var/run/clamav
ports:
- "11332:11332" # milter 接口
- "11334:11334" # Web 管理界面
restart: unless-stopped
clamav:
image: clamav/clamav:latest
container_name: clamav
volumes:
- ./clamsock:/var/run/clamav
restart: unless-stopped注意两个容器挂载了同一个 ./clamsock 目录,这就是 ClamAV 的 socket 共享通道,缺了这一步 Rspamd 会报无法连接病毒扫描器的错误。
与 Postfix 集成及关键配置
Rspamd 对外提供 milter 协议接口,Postfix 通过 milter 参数对接。假设 Postfix 也跑在容器里,只需在它的配置中加入指向 Rspamd 容器的地址:
postconf -e "milter_default_action = accept" postconf -e "smtpd_milters = inet:rspamd:11332" postconf -e "non_smtpd_milters = inet:rspamd:11332"
这里 rspamd 是 Compose 网络里的服务名,容器间可以通过服务名直接解析。接下来是 Rspamd 的本地配置,在 ./rspamd 目录中创建几个关键文件。先是 worker-normal.inc 定义主进程监听:
bind_socket = "0.0.0.0:11333";
然后是 antivirus.conf,启用 ClamAV 扫描:
clamav {
servers = "/var/run/clamav/clamd.ctl";
action = "reject";
symbol = "CLAMAV_VIRUS";
}把 action 设为 reject 表示发现病毒直接拒收,也可以改为 add header 仅打标记交由用户自行处理。灰名单的配置在 greylist.conf 中开启即可,默认策略对首次出现的发件组合延迟约一分钟再放行,重试的连接会跳过检查。建议对新部署的系统观察一至两周再逐步收紧规则,避免误伤正常业务邮件。
运行监控与误报处理
系统上线后,运维的重点是观察命中率和处理误报。Rspamd 自带的 Web 界面默认监听 11334 端口,出于安全考虑不要直接暴露到公网,建议通过 SSH 隧道访问:ssh -L 11334:localhost:11334 user@mailserver。界面的 History 页面能看到每封邮件各符号的得分明细,比如 SPF 失败、DNSBL 命中、贝叶斯概率值等,排查误报时一目了然。
遇到误报,先看是哪条规则给了高分。如果对方是企业邮件服务器被列入了较激进的黑名单,可以在 multimap.conf 中加白名单:
WHITELIST_SENDER {
type = "from";
map = "/etc/rspamd/local.d/whitelist_from.map";
symbol = "WHITELISTED_SENDER";
action = "accept";
}对应的 whitelist_from.map 文件里逐行写域名或邮箱即可。反过来,漏报的垃圾邮件可以通过 rspamc learn_spam 命令喂给贝叶斯模型学习,正常邮件则用 learn_ham,学习样本积累到几百封后,统计过滤的准确率会明显提升。
最后提醒几个容器化特有的细节:Rspamd 的统计模型和 DKIM 密钥都存在容器卷里,务必纳入备份策略,容器重建后没有这些数据,过滤效果会退化到初始状态;ClamAV 的病毒库更新依赖容器内定时任务,建议同时升级镜像本身以获得安全补丁;整套系统先以仅打标记模式运行观察一段时间,确认误杀率可接受后再切换为直接拒收,这样上线过程会平稳得多。