强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第 6 章:反垃圾邮件策略

第 6 章:反垃圾邮件策略

反垃圾邮件不是一道墙,而是多层防线的协同作战。


6.1 反垃圾邮件架构

6.1.1 多层防御体系

邮件到达
    │
    ▼
┌───────────────────────┐
│ 第 1 层:连接级过滤    │  ← RBL、连接速率限制、灰名单
│ • 客户端 IP 黑名单     │
│ • PTR 记录检查         │
│ • 灰名单延迟           │
└───────────┬───────────┘
            │
            ▼
┌───────────────────────┐
│ 第 2 层:信封级过滤    │  ← 发件人/收件人验证
│ • SPF 验证            │
│ • 发件人域名验证       │
│ • 收件人存在性验证     │
└───────────┬───────────┘
            │
            ▼
┌───────────────────────┐
│ 第 3 层:内容级过滤    │  ← SpamAssassin、病毒扫描
│ • 垃圾邮件评分         │
│ • 病毒扫描(ClamAV)   │
│ • 附件过滤             │
└───────────┬───────────┘
            │
            ▼
┌───────────────────────┐
│ 第 4 层:投递后处理    │  ← 用户反馈、学习
│ • 用户标记垃圾邮件     │
│ • Bayesian 学习        │
│ • 白名单管理           │
└───────────────────────┘

6.1.2 防御层次对比

层次工具/技术检查点性能影响误判率
连接级RBL、灰名单SMTP 连接阶段
信封级SPF、发件人验证MAIL FROM/RCPT TO极低
内容级SpamAssassin邮件正文
投递后Bayesian用户邮箱

6.2 RBL 黑名单检查

6.2.1 什么是 RBL

RBL(Real-time Blackhole List)是实时更新的 IP 黑名单数据库,记录了已知的垃圾邮件发送源。

6.2.2 常用 RBL 服务

RBL 服务DNS 查询地址说明免费/付费
Spamhaus ZENzen.spamhaus.org综合黑名单免费查询
SpamCopbl.spamcop.net社区驱动免费
Barracudab.barracudacentral.org商业级免费查询
SpamRATSall.spamrats.com综合免费
PSBLpsbl.surriel.com被动收集免费

6.2.3 配置 Postfix 使用 RBL

# /etc/postfix/main.cf — RBL 检查配置

smtpd_recipient_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    reject_unknown_sender_domain,
    reject_unknown_reverse_client_hostname,
    reject_rbl_client zen.spamhaus.org,
    reject_rbl_client bl.spamcop.net,
    reject_rbl_client b.barracudacentral.org,
    reject_rhsbl_reverse_client dbl.spamhaus.org,
    reject_rhsbl_sender dbl.spamhaus.org,
    permit

# RBL 拒绝信息自定义
smtpd_reject_footer = \nFor more info, visit https://example.com/mail-policy

6.2.4 RBL 配置参数

# 拒绝来自 RBL 的连接
reject_rbl_client zen.spamhaus.org

# 带白名单的 RBL 检查
check_client_access hash:/etc/postfix/rbl_whitelist,
reject_rbl_client zen.spamhaus.org

# 不同响应码的 RBL 检查
reject_rbl_client zen.spamhaus.org=127.0.0.2    # 仅拒绝 SBL
reject_rbl_client zen.spamhaus.org=127.0.0.4    # 仅拒绝 XBL
# /etc/postfix/rbl_whitelist — RBL 白名单
# 豁免特定 IP 的 RBL 检查
203.0.113.50     OK
10.0.0.0/8       OK
trusted.com      OK

# 生成数据库
sudo postmap /etc/postfix/rbl_whitelist

6.3 灰名单(Greylisting)

6.3.1 灰名单原理

灰名单工作流程:
┌────────────────────────────────────────────────┐
│ 1. 首次收到邮件时,临时拒绝(4xx 错误码)        │
│ 2. 合法的邮件服务器会在稍后重试                  │
│ 3. 垃圾邮件发送器通常不会重试                    │
│ 4. 重试的邮件被接受并记录到白名单                │
│ 5. 后续同三元组的邮件直接放行                    │
└────────────────────────────────────────────────┘

三元组 = (客户端 IP, 发件人地址, 收件人地址)

6.3.2 安装 Postgrey

# 安装 Postgrey
sudo apt install -y postgrey

# 启动服务
sudo systemctl enable --now postgrey

# 检查服务状态
sudo systemctl status postgrey

6.3.3 配置 Postfix 使用灰名单

# /etc/postfix/main.cf

smtpd_recipient_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    check_policy_service inet:127.0.0.1:10023,    # Postgrey
    reject_rbl_client zen.spamhaus.org,
    permit

6.3.4 Postgrey 配置

# /etc/default/postgrey

# 启动参数
POSTGREY_OPTS="--inet=127.0.0.1:10023 --delay=300 --max-age=35"

# 参数说明:
# --inet: 监听地址和端口
# --delay: 首次拒绝后的等待秒数(默认 300)
# --max-age: 白名单记录保留天数(默认 35)
# --greylist-text: 自定义拒绝信息

6.3.5 灰名单白名单管理

# /etc/postgrey/whitelist_clients — 客户端 IP 白名单
# 豁免大型邮件服务(它们的重试机制可靠)
# 格式:IP 或域名正则
/^.*\.google\.com$/
/^.*\.microsoft\.com$/
/^.*\.amazonaws\.com$/
/^.*\.outlook\.com$/

# /etc/postgrey/whitelist_recipients — 收件人白名单
# 这些收件人的邮件不经过灰名单
[email protected]
[email protected]

# 重启 Postgrey 生效
sudo systemctl restart postgrey

6.4 SpamAssassin

6.4.1 安装 SpamAssassin

# 安装 SpamAssassin 和相关组件
sudo apt install -y spamassassin spamc

# 创建专用用户
sudo useradd -r -s /usr/sbin/nologin spamd

# 启动 SpamAssassin 守护进程
sudo systemctl enable --now spamassassin

# 检查服务状态
sudo systemctl status spamassassin

6.4.2 配置 Postfix 使用 SpamAssassin

# 方法 1:使用 Content Filter(推荐)

# /etc/postfix/main.cf
content_filter = spamassassin

# /etc/postfix/master.cf — 添加过滤器
spamassassin unix - n n - - pipe
  user=spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
# 方法 2:使用 Amavis(集成反垃圾和防病毒)

sudo apt install -y amavisd-new

# /etc/postfix/main.cf
content_filter = smtp-amavis:[127.0.0.1]:10024

# /etc/postfix/master.cf
smtp-amavis unix - - n - - smtp
  -o smtp_data_done_timeout=1200
  -o smtp_send_xforward_command=yes
  -o disable_dns_lookups=yes
  -o max_use=20

6.4.3 SpamAssassin 规则配置

# /etc/spamassassin/local.cf — 本地配置

# 基础设置
required_score 5.0                    # 垃圾邮件判定阈值
report_safe 0                         # 0: 附件形式,1: 替换正文
use_bayes 1                           # 启用 Bayesian 学习
bayes_auto_learn 1                    # 自动学习
bayes_auto_learn_threshold_nonspam 0.1  # 非垃圾阈值
bayes_auto_learn_threshold_spam 7.0     # 垃圾阈值

# 白名单/黑名单
whitelist_from *@trusted.com
blacklist_from *@spam-domain.com

# 自定义规则
header LOCAL_SPAM_SUBJECT  Subject =~ /免费.*中奖/
score LOCAL_SPAM_SUBJECT 5.0

body LOCAL_SPAM_BODY  /点击这里领取奖金/
score LOCAL_SPAM_BODY 3.0

# DNS 检查
skip_rbl_checks 0
use_razor2 1                          # 启用 Razor2
use_pyzor 1                           # 启用 Pyzor

6.4.4 SpamAssassin 评分阈值

分数含义处理建议
< 5.0正常邮件正常投递
5.0 - 10.0可疑邮件标记为垃圾邮件
10.0 - 15.0高度可疑隔离或拒绝
> 15.0几乎确定是垃圾直接拒绝

6.4.5 更新 SpamAssassin 规则

# 手动更新规则
sudo sa-update

# 设置自动更新(cron)
sudo tee /etc/cron.d/spamassassin-update << 'EOF'
30 4 * * * root /usr/bin/sa-update && /usr/bin/systemctl reload spamassassin
EOF

# 检查规则版本
sa-update --lint

6.5 Postfix 内置过滤

6.5.1 发件人验证

# /etc/postfix/main.cf

# 拒绝发件人域名不存在
smtpd_sender_restrictions =
    reject_unknown_sender_domain,
    reject_non_fqdn_sender,
    reject_sender_login_mismatch

# 拒绝发件人域名无 MX 记录
smtpd_sender_restrictions =
    reject_unknown_sender_domain

# 限制发件人格式
smtpd_sender_restrictions =
    reject_non_fqdn_sender

6.5.2 HELO/EHLO 验证

# 拒绝无效的 HELO/EHLO
smtpd_helo_restrictions =
    permit_mynetworks,
    reject_invalid_helo_hostname,
    reject_non_fqdn_helo_hostname,
    reject_unknown_helo_hostname

# 自定义 HELO 检查
smtpd_helo_restrictions =
    permit_mynetworks,
    check_helo_access hash:/etc/postfix/helo_access,
    reject_invalid_helo_hostname

# /etc/postfix/helo_access
# 拒绝声称是这些域名的连接
example.com     REJECT Don't pretend you are us
localhost       REJECT Don't use localhost in HELO

6.5.3 header_checks(邮件头过滤)

# /etc/postfix/header_checks

# 拒绝包含特定主题的邮件
/^Subject:.*中奖.*免费/    REJECT Spam detected

# 删除特定邮件头
/^X-Mailer:.*SpammerTool/    IGNORE

# 标记可疑邮件
/^Subject:.*紧急.*回复/    HOLD Possible spam

# 在 main.cf 中启用
header_checks = regexp:/etc/postfix/header_checks

6.5.4 body_checks(邮件正文过滤)

# /etc/postfix/body_checks

# 拒绝包含特定内容的邮件
/点击这里领取奖金/    REJECT Spam content detected
/http:\/\/suspicious-link/    REJECT Suspicious link

# 在 main.cf 中启用
body_checks = regexp:/etc/postfix/body_checks

# ⚠️ 注意:body_checks 性能开销较大,谨慎使用

6.6 ClamAV 病毒扫描

6.6.1 安装 ClamAV

# 安装 ClamAV
sudo apt install -y clamav clamav-daemon clamav-freshclam

# 更新病毒库
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam

# 启动 ClamAV 守护进程
sudo systemctl enable --now clamav-daemon

6.6.2 集成 Amavis + ClamAV + SpamAssassin

# Amavis 已集成 ClamAV 和 SpamAssassin
# /etc/amavis/conf.d/15-content_filter_mode

@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

# /etc/amavis/conf.d/50-user
use strict;

@local_domains_acl = ( "example.com" );

$sa_tag_level_deflt  = -999;  # 所有邮件都添加 SpamAssassin 标头
$sa_tag2_level_deflt = 5.0;   # 标记为垃圾邮件的阈值
$sa_kill_level_deflt = 10.0;  # 拒绝/隔离阈值
$sa_spam_subject_tag = '***SPAM*** ';

# ClamAV 设置
@av_scanners = (
    ['ClamAV-clamd',
     \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.ctl"],
     qr/\bOK$/, qr/\bFOUND$/,
     qr/^.*?: (?!Infected Archive)(.*) FOUND$/],
);

6.7 综合反垃圾邮件配置

完整的 main.cf 反垃圾配置

# /etc/postfix/main.cf — 综合反垃圾邮件配置

# ==================== 连接级限制 ====================
smtpd_client_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unknown_reverse_client_hostname,
    reject_rbl_client zen.spamhaus.org,
    reject_rbl_client bl.spamcop.net

# ==================== HELO 限制 ====================
smtpd_helo_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_invalid_helo_hostname,
    reject_non_fqdn_helo_hostname

# ==================== 发件人限制 ====================
smtpd_sender_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unknown_sender_domain,
    reject_non_fqdn_sender

# ==================== 收件人限制(含灰名单)====================
smtpd_recipient_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    reject_unknown_recipient_domain,
    reject_non_fqdn_recipient,
    check_policy_service inet:127.0.0.1:10023,
    reject_unverified_recipient,
    permit

# ==================== 内容过滤 ====================
content_filter = smtp-amavis:[127.0.0.1]:10024

# ==================== 邮件头/正文检查 ====================
header_checks = regexp:/etc/postfix/header_checks

6.8 业务场景:企业反垃圾邮件策略

场景描述

一家金融企业需要严格的反垃圾邮件策略,要求:

  • 误判率极低(不能漏掉重要邮件)
  • 符合金融行业合规要求
  • 支持审计和报告

配置方案

# 保守的反垃圾策略(低误判率)

# SpamAssassin 阈值调高
required_score 8.0

# 仅使用最可靠的 RBL
smtpd_client_restrictions =
    permit_mynetworks,
    reject_rbl_client zen.spamhaus.org=127.0.0.2    # 仅 SBL

# 隔离而非拒绝可疑邮件
# 使用 Amavis 隔离功能
$final_spam_destiny = D_DISCARD;    # 隔离到隔离区

# 邮件审计日志
# 在 main.cf 中添加
always_bcc = [email protected]

6.9 注意事项

⚠️ 误判处理

  • 定期检查垃圾邮件隔离区
  • 提供用户报告误判的渠道
  • 使用 whitelist_from 白名单重要发件人

⚠️ RBL 查询性能

  • 每次 RBL 查询都会产生 DNS 请求
  • 建议使用本地 DNS 缓存(如 unbound
  • 限制 RBL 查询数量(只使用最可靠的)

💡 灰名单的影响

  • 首次邮件投递会有 5-15 分钟延迟
  • 向用户说明情况,避免投诉
  • 白名单大型邮件服务(Gmail、Outlook)

6.10 扩展阅读


上一章← 第 5 章:TLS/SSL 加密配置 下一章第 7 章:DKIM 邮件签名 →