适用场景
钓鱼邮件处置能力决定了企业邮箱被攻陷后的止损速度。当员工收到伪装成财务对账、发票催收、快递通知的邮件并点击了附件或链接后,常见后果是 M365 / Exchange 账号被 AiTM 反向代理页面窃取会话 Cookie、终端被植入窃密木马、后续对内发起横向钓鱼。以下场景必须依赖邮件网关与处置流程联动:
- 同一封钓鱼邮件在数分钟内投递到上百个收件箱,需要批量撤回;
- 员工已提交账号密码,需要强制注销会话并重置凭据;
- 需要从邮件头中提取发件基础设施 IOC,并在网关侧批量封禁。
前置条件
- 边界 MTA 为 Postfix 3.x,已启用 TLS,管理员具备
/etc/postfix与/etc/rspamd写权限; - 已部署 Rspamd(推荐 3.7 以上)作为内容过滤与评分引擎,或使用 SpamAssassin 替代;
- 域名已完成 SPF、DKIM、DMARC 三项配置,DMARC 策略至少为
p=quarantine; - 具备邮件归档、日志保留与批量撤回的工具链(如 Dovecot + Sieve)。
原理说明
钓鱼邮件的防线分为三层,任何一层单独使用都不足够。第一层是身份验证层,通过 SPF 校验发信 IP、DKIM 校验签名完整性、DMARC 校验 From 域与信封域对齐,拦截伪造发件人的邮件;第二层是内容与行为层,由 Rspamd 这类引擎对邮件正文、URL、附件结构打分,识别宏文档、伪装扩展名、新建域链接;第三层是处置响应层,在邮件已经投递、用户已经点击的前提下,完成撤回、会话吊销、IOC 封禁与终端排查。
需要特别强调:SPF / DKIM / DMARC 完全无法拦截攻击者用自有域名注册的邮箱发来的钓鱼邮件,因为对其而言三项校验全部通过。这类邮件只能靠内容评分与链接信誉拦截,这也是必须部署邮件网关的原因。
操作步骤
步骤一:加固边界 MTA 的输入面
# 限制单封邮件收件人数与邮件大小,降低群发钓鱼的投递效率
postconf -e 'smtpd_recipient_limit = 50'
postconf -e 'message_size_limit = 20971520'
postconf -e 'smtpd_helo_required = yes'
postconf -e 'disable_vrfy_command = yes'
# 拒绝未提供合法 HELO 的会话,阻断大部分批量投递工具
postconf -e 'smtpd_helo_restrictions = permit_mynetworks,reject_invalid_helo_hostname,reject_non_fqdn_helo_hostname'
postconf -e 'smtpd_sender_restrictions = reject_non_fqdn_sender,reject_unknown_sender_domain'
postconf -e 'smtpd_recipient_restrictions = permit_mynetworks,reject_unauth_destination,reject_unauth_pipelining'
systemctl reload postfix
其中 reject_unauth_pipelining 用于阻断批量投递脚本常滥用的 SMTP 管道化行为,是降低群发速度的关键参数。
步骤二:接入 Rspamd 内容过滤
# 将 Rspamd 作为 milter 接入 Postfix
postconf -e 'smtpd_milters = inet:127.0.0.1:11332'
postconf -e 'non_smtpd_milters = inet:127.0.0.1:11332'
postconf -e 'milter_default_action = accept'
postconf -e 'milter_protocol = 6'
systemctl reload postfix
# 验证 milter 连接
systemctl restart rspamd
ss -lntp | grep 11332
调整评分阈值与动作映射,让高分邮件直接进隔离区而非丢弃(保留取证可能):
# /etc/rspamd/local.d/actions.conf
reject = 15;
add_header = 6;
greylist = 4;
# /etc/rspamd/local.d/worker-proxy.inc
milter = yes;
timeout = 120;
步骤三:拦截高危附件与伪装扩展名
# /etc/rspamd/local.d/multimap.conf
# 按真实 MIME 类型拦截,避免仅依赖扩展名被绕过
BAD_ATTACHMENT_TYPE {
type = "mime_types";
map = "/etc/rspamd/maps/bad_mime.map";
score = 8;
message = "blocked dangerous attachment";
}
# /etc/rspamd/maps/bad_mime.map 内容示例(每行一条)
application/x-msdownload
application/x-dosexec
application/vnd.ms-htmlhelp
application/x-sh
application/java-archive
systemctl restart rspamd
同时用正则识别双扩展名伪装(如 invoice.pdf.exe、report.doc.com):
# /etc/rspamd/local.d/regexp.conf
DOUBLE_EXTENSION = {
re = /\.(pdf|docx?|xlsx?|jpg|png)\.(exe|scr|js|vbs|com|bat|lnk)$/i;
score = 9;
message = "double extension detected";
}
步骤四:建立隔离区与用户上报入口
# 用 Dovecot Sieve 把 Rspamd 标记的邮件移入隔离文件夹
# /etc/dovecot/sieve/rspamd.sieve
require ["fileinto", "mailbox", "imap4flags"];
if header :contains "X-Spamd-Result" "default: False" {
if header :contains "X-Spam-Level" "********" {
fileinto :create "Junk/Quarantine";
stop;
}
}
# 编译并生效
sievec /etc/dovecot/sieve/rspamd.sieve
systemctl restart dovecot
另设一个 report-phishing@ 别名邮箱,员工一键转发可疑邮件即可进入人工分析队列,这是获取真实样本最有效的渠道。
步骤五:钓鱼事件的处置流程
# 1. 从样本中提取发件基础设施 IOC
# 抓取 Received 链、Return-Path、Message-ID 与所有 URL 域名
grep -E "^(Received|Return-Path|Message-ID|From):" suspicious.eml
# 提取正文中的全部域名,去重后与信誉库比对
grep -oE "https?://[a-zA-Z0-9.-]+" suspicious.eml | \
sed -E 's#https?://##' | sort -u
# 2. 统计该邮件的影响面(按 Message-ID 检索投递日志)
grep -F "$(grep -m1 '^Message-ID:' suspicious.eml | cut -d' ' -f2)" \
/var/log/mail.log | awk '{print $7}' | sort -u > /tmp/affected_users.txt
wc -l /tmp/affected_users.txt
# 3. 批量撤回:把已投递邮件移入隔离区
while read u; do
doveadm move -u "$u" Junk/Quarantine mailbox INBOX \
HEADER Message-ID "$(grep -m1 '^Message-ID:' suspicious.eml | cut -d' ' -f2)"
done < /tmp/affected_users.txt
撤回完成后必须对点击过链接的用户强制吊销会话,否则已窃取的 Cookie 仍然有效:
# 以 Exchange Online 为例,吊销全部刷新令牌与会话
Connect-ExchangeOnline
Get-Mailbox -Identity user@example.com | \
Revoke-Session
# 同时强制改密并要求重新注册 MFA
Set-MsolUser -UserPrincipalName user@example.com -StrongAuthenticationMethods @()
步骤六:网关侧下发封禁规则
# /etc/rspamd/local.d/multimap.conf
PHISH_DOMAIN {
type = "from";
map = "/etc/rspamd/maps/phish_domains.map";
score = 12;
message = "known phishing domain";
}
# /etc/rspamd/local.d/maps.d/phish_domains.map
example-phish[.]top
invoice-secure[.]xyz
# 用后缀匹配同一发信域下的所有子域,避免攻击者换子域继续投递
rspamadm configtest && systemctl restart rspamd
配置验证
# 从外部投递一封测试邮件,确认 milter 生效
printf 'Subject: test\n\nbody' | sendmail -f t@example.com user@example.com
grep -i "rspamd" /var/log/mail.log | tail -5
# 确认危险附件被拦截(应返回 add_header 或 reject)
rspamc -h 127.0.0.1:11333 symbols suspicious.eml
# 确认封禁域已生效
rspamadm configdump | grep -A3 PHISH_DOMAIN
# 确认隔离区可读
doveadm search -u user@example.com mailbox Junk/Quarantine all | head
验证标准是:测试邮件在 X-Spamd-Result 中出现评分明细,危险附件测试样本被标记为 reject 或进入隔离区,封禁域邮件被直接拒绝。
常见问题
FAQ 1:已经部署了 SPF、DKIM、DMARC,为什么还会收到大量钓鱼邮件?
因为这三项只校验发件人身份是否被伪造,不判断内容是否恶意。攻击者用自己注册的域名发信时,SPF 通过、DKIM 通过、DMARC 对齐也通过,整封邮件在身份层是完全合法的。此外,攻击者还可以利用第三方邮件服务的合法发信域、被入侵的真实企业邮箱,或直接复用 AI 生成的完美商务语料绕过语义判断。因此身份验证层之后,必须叠加内容评分(Rspamd)、链接信誉查询与新建域告警三道机制。
FAQ 2:未点击链接的员工也需要强制改密吗?
不需要,但需要区分处置等级。仅收到邮件未交互的员工,只需要撤回邮件并加入安全提醒;点击了链接但未提交凭据的员工,需要吊销当前会话并检查终端是否有异常进程;已经提交账号密码的员工,必须执行吊销全部会话 + 强制改密 + 重置 MFA 注册三步,缺一不可。特别注意 AiTM 类钓鱼会同时窃取会话 Cookie,仅改密码而不吊销会话,攻击者仍可凭有效 Cookie 继续访问邮箱,因此吊销会话必须排在改密之前执行。
FAQ 3:如何判断一封钓鱼邮件触达了多少人?
关键索引是邮件头中的 Message-ID。同一批次群发的邮件通常复用同一 Message-ID,用它在 MTA 日志中做全文检索即可拉出全部收件人;若攻击者为每封邮件单独生成 Message-ID,则改用 Return-Path 或发件域名做聚合统计。建议在 MTA 日志中保留完整的 to=、from=、message-id=、status= 字段,并统一投递到 SIEM,便于后续按任意维度回溯影响面。
总结
邮件网关与钓鱼邮件处置不是单点产品,而是一条完整链路:边界 MTA 限制批量投递能力,Rspamd 补齐内容与附件维度,Sieve 隔离区保留人工复核空间,Message-ID 索引支撑影响面统计,会话吊销与凭据重置完成最终止损。三者缺一,攻击者就能在身份验证合法或员工已交互的缝隙中完成账户接管。日常运维应把新建域名发信、首次出现的附件类型、异常 URL 域名三个信号纳入告警,把处置响应时间压缩到分钟级。