定位 :网络基础与协议安全篇 · 邮件身份验证三板斧 + 钓鱼为何仍能得手
声明 :伪造邮件、钓鱼测试仅限自有域名与书面授权;向他人发送欺诈邮件违法。
一、为什么邮件是钓鱼的「主战场」?
text
攻击链常见入口:
钓鱼邮件 → 恶意链接/附件 → 凭据窃取 → 内网横向
邮件协议 SMTP 设计于 无身份时代:
| 问题 | 后果 |
|---|---|
| SMTP 不验证发件人 | 可伪造 From: 显示名 |
| 转发、中继复杂 | 单纯 SPF 易在转发后失败 |
| 用户信「看起来对」 | 显示名、Logo、 urgency 话术 |
SPF / DKIM / DMARC 是当今抵御 域名伪造 的主流 DNS 机制,但 不能防住所有钓鱼 。本文:配好三板斧 + 演示绕过手法 + 蓝队检测。
二、SMTP 与「两个发件人」
读邮件头前先分清:
text
┌─────────────────────────────────────────────────────────┐
│ 信封发件人(Envelope MAIL FROM / Return-Path) │
│ → SPF 检查的对象,退信回到这里 │
├─────────────────────────────────────────────────────────┤
│ 头域发件人(Header From:) │
│ → 用户邮箱客户端显示的「发件人」 │
└─────────────────────────────────────────────────────────┘
钓鱼常利用二者不一致:
text
From: "财务部" <ceo@yourcompany.com> ← 用户看到的
MAIL FROM: <bounce@attacker-smtp.com> ← SPF 可能查这个
DMARC 的核心就是要求:SPF 或 DKIM 至少有一个与 Header From「对齐(Alignment)」。
三、SPF:发信 IP 白名单
3.1 原理
域名发布 DNS TXT 记录,声明哪些 IP/服务可以代发:
text
v=spf1 ip4:203.0.113.10 include:_spf.google.com -all
收信方 MX 查 SPF:连接来的 IP 是否在名单内。
3.2 记录语法速查
| 机制 | 含义 | 示例 |
|---|---|---|
ip4: / ip6: |
允许的主机 | ip4:203.0.113.0/24 |
include: |
引用其他域 SPF | include:spf.protection.outlook.com |
a / mx |
域的 A/MX 记录 IP | mx |
-all |
其余 拒绝(推荐生产) | 严格 |
~all |
其余 软失败 | 过渡 |
+all |
其余允许 | 危险,等于没配 |
3.3 配置示例(自有域名 mailsec.lab)
DNS 控制台添加 TXT(主机记录 @ 或根域):
text
v=spf1 mx ip4:192.168.56.30 ~all
若用 Google Workspace:
text
v=spf1 include:_spf.google.com -all
3.4 验证
bash
dig TXT mailsec.lab +short
dig TXT mailsec.lab @8.8.8.8 +short
# 在线:mxtoolbox.com/spf.aspx
3.5 SPF 局限
text
· 只验证 MAIL FROM 域,不验证 From 头
· 邮件转发后 IP 变,可能 SPF fail(需 ARC 等,进阶)
· 10 次 DNS 查询限制(include 嵌套)
· 不保证邮件内容未被篡改
四、DKIM:密码学签名
4.1 原理
发信服务器用 私钥 对邮件头/体签名,公钥通过 DNS 发布:
text
selector._domainkey.mailsec.lab TXT "v=DKIM1; k=rsa; p=MIGfMA0G..."
收信方用 p= 公钥验签,确认邮件未被篡改且来自持有私钥的一方。
4.2 邮件头中的样子
http
DKIM-Signature: v=1; a=rsa-sha256; d=mailsec.lab; s=default;
h=from:to:subject:date; bh=...; b=...
| 字段 | 含义 |
|---|---|
d= |
签名域 |
s= |
选择器(selector) |
b= |
签名值 |
4.3 靶场生成密钥(OpenDKIM 风格)
bash
# Ubuntu 受害机/邮件机 192.168.56.30
sudo apt install -y opendkim opendkim-tools
sudo mkdir -p /etc/opendkim/keys/mailsec.lab
sudo opendkim-genkey -b 2048 -d mailsec.lab -s default -D /etc/opendkim/keys/mailsec.lab/
# 公钥发布到 DNS(查看 default.txt)
sudo cat /etc/opendkim/keys/mailsec.lab/default.txt
default.txt 内容合并为一行 TXT 记录,主机名:
text
default._domainkey.mailsec.lab
4.4 验证
bash
dig TXT default._domainkey.mailsec.lab +short
收到邮件后看头:
http
Authentication-Results: mx.google.com;
dkim=pass header.d=mailsec.lab header.s=default;
五、DMARC:策略 + 对齐
5.1 原理
在 _dmarc.mailsec.lab 发布策略,告诉收信方:
text
· SPF/DKIM 失败时怎么处理(none / quarantine / reject)
· 对齐规则(relaxed / strict)
· 报告发到哪里(rua 聚合 / ruf 取证)
5.2 记录示例
监测期(建议先上):
text
v=DMARC1; p=none; rua=mailto:dmarc-reports@mailsec.lab; pct=100; adkim=r; aspf=r
成熟后收紧:
text
v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc-reports@mailsec.lab; adkim=s; aspf=s
严格生产:
text
v=DMARC1; p=reject; pct=100; rua=mailto:dmarc-reports@mailsec.lab
| 参数 | 含义 |
|---|---|
p= |
对当前域策略 |
sp= |
子域策略 |
rua= |
聚合报告邮箱 |
adkim=r/s |
DKIM 宽松/严格对齐 |
aspf=r/s |
SPF 宽松/严格对齐 |
5.3 对齐(Alignment)图解
text
Header From: alice@mailsec.lab
SPF 对齐:MAIL FROM 域也是 mailsec.lab(或子域,看 relaxed/strict)
DKIM 对齐:DKIM d= 也是 mailsec.lab
DMARC pass = (SPF pass 且 SPF 对齐) 或 (DKIM pass 且 DKIM 对齐)
仅 SPF pass 但对齐失败 → DMARC fail,钓鱼仍可能被拒。
5.4 验证
bash
dig TXT _dmarc.mailsec.lab +short
工具:dmarcian.com、MXToolbox DMARC
六、三板斧协同工作流程
text
收信 MX 收到邮件
│
┌───────────────┼───────────────┐
▼ ▼ ▼
查 SPF TXT 验 DKIM 签 读 DMARC 策略
连接 IP 用 DNS 公钥 看对齐+失败处置
│ │ │
└───────────────┴───────────────┘
▼
Authentication-Results 写入邮件头
▼
p=reject → 拒收;quarantine → 垃圾箱
Authentication-Results 示例(Gmail):
http
Authentication-Results: mx.google.com;
dkim=pass header.i=@mailsec.lab;
spf=pass (google.com: domain of bounce@mailsec.lab designates ...);
dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=mailsec.lab
七、实验环境搭建
7.1 拓扑
text
邮件服务器 Ubuntu 192.168.56.30 Postfix + OpenDKIM
Kali 发信测试 192.168.56.10 swaks
DNS 真实域名控制台 或 靶场 dnsmasq
分析 任意邮箱 / mail-tester.com
建议 :用 你可控的真实子域 (如 lab.你的域名.com)做 DNS 实验,比纯内网假域更可验证。
7.2 最小 Postfix + OpenDKIM(56.30)
bash
sudo apt install -y postfix mailutils opendkim opendkim-tools
# 安装时选 "Internet Site",主机名 mailsec.lab(或 FQDN)
# /etc/opendkim.conf 关键项
sudo tee -a /etc/opendkim.conf <<'EOF'
Domain mailsec.lab
Selector default
KeyFile /etc/opendkim/keys/mailsec.lab/default.private
Socket inet:8891@localhost
EOF
# Postfix 集成 milter(/etc/postfix/main.cf)
# milter_protocol = 2
# milter_default_action = accept
# smtpd_milters = inet:localhost:8891
# non_smtpd_milters = inet:localhost:8891
sudo systemctl enable --now opendkim postfix
7.3 DNS 三板斧清单(实验域)
| 记录类型 | 主机 | 值 |
|---|---|---|
| TXT | @ |
v=spf1 ip4:你的公网IP -all(靶场可用 ~all) |
| TXT | default._domainkey |
OpenDKIM 生成的 p=... |
| TXT | _dmarc |
v=DMARC1; p=none; rua=mailto:you@mailsec.lab |
| MX | @ |
指向邮件服务器 |
7.4 打快照
mail-server-clean / kali-clean
八、合法发信测试
8.1 swaks 发送「合规邮件」
bash
# Kali
sudo apt install -y swaks
swaks --to your-test@gmail.com \
--from alice@mailsec.lab \
--server 192.168.56.30 \
--header "Subject: DMARC Lab Legit Mail" \
--body "SPF+DKIM+DMARC lab test"
检查收件箱 → 显示原始邮件 → 找 spf=pass dkim=pass dmarc=pass。
8.2 mail-tester.com 打分
bash
# 网站会给你一个临时地址 test-xxxxx@mail-tester.com
swaks --to test-xxxxx@mail-tester.com \
--from alice@mailsec.lab \
--server 你的公网SMTP
目标:10/10,常见扣分:SPF/DKIM/DMARC 缺失、反向 DNS、黑名单。
九、钓鱼绕过手法(授权演示)
以下在 自有域、授权红队、封闭靶场 中演示,用于蓝队培训。
9.1 显示名伪造(最常见,DMARC 不管)
bash
swaks --to victim@company.com \
--from ceo@attacker-gmail.com \
--header "From: CEO Zhang <ceo@attacker-gmail.com>" \
--header "Subject: 紧急:请立即付款" \
--body "..."
| 现象 | 说明 |
|---|---|
| 邮箱显示「CEO Zhang」 | 用户看名字不看地址 |
| SPF/DKIM | 可能 pass 攻击者自己的域 |
| DMARC | 对齐的是 attacker 域,与伪装无关 |
防御 :用户培训 + 邮件网关 显示名与地址不一致告警 + 外部邮件横幅。
9.2 相似域名(Lookalike)
text
真实: company.com
伪造: c0mpany.com / company-co.com / company-login.com
攻击者注册近似域,配好 SPF/DKIM/DMARC,发 真 pass 的钓鱼信。
防御:域相似度检测、品牌保护注册、浏览器隔离点击链接。
9.3 子域滥用
若父域 SPF:
text
v=spf1 include:... ~all
攻击者控制 evil.company.com 的 DNS,自建 SMTP,SPF 可能 子域独立 ------取决于父域 sp= DMARC 策略。
防御 :_dmarc 设 sp=reject;子域同样配 DMARC。
9.4 未配 DMARC 的域(经典伪造)
对 无 DMARC / p=none 的 victim-company.com:
bash
swaks --to test@gmail.com \
--from fake@victim-company.com \
--server 攻击者SMTP \
--header "From: HR <fake@victim-company.com>"
部分收件方仅 SPF fail 标垃圾,仍可能进箱;Gmail/Outlook 对无 DMARC 域越来越严,但不可依赖。
蓝队 :尽快 p=quarantine → p=reject。
9.5 合法账号被盗
text
真实 SPF pass + DKIM pass + DMARC pass
但内容仍是钓鱼链接(账号接管、OAuth 滥用)
防御:MFA、异常登录检测、链接重写沙箱(Safe Links)、行为分析。
9.6 同源不同内容(BEC 商务邮件诈骗)
不伪造技术字段,用 被控供应商真实邮箱 改收款账号。
防御:付款二次确认流程、带外电话核实,不靠邮件 alone。
9.7 绕过手法汇总表
| 手法 | SPF | DKIM | DMARC | 技术能否挡 |
|---|---|---|---|---|
| 显示名伪造 | 任意 | 任意 | 不相关 | ❌ 需培训+网关 |
| 相似域名 | pass | pass | pass | ❌ 需品牌监测 |
| 无 DMARC 域伪造 | fail/soft | fail | 无 | △ 部分挡 |
| 盗号真信 | pass | pass | pass | ❌ 需 MFA+UEBA |
| 转发导致 SPF fail | fail | pass | 可能 pass | DKIM+ARC |
十、蓝队:如何读邮件头
10.1 查看顺序
text
1. Authentication-Results(综合结论)
2. Received-SPF
3. DKIM-Signature + 验签结果
4. From / Reply-To / Return-Path 是否一致
5. Received 链(来源 IP、跳数)
6. Message-ID、Date 异常
10.2 快速判断脚本思路
python
# 伪代码:解析 Authentication-Results
if "dmarc=pass" in headers and from_domain == company_domain:
trust_level = "high"
elif "dmarc=fail" and from_domain == company_domain:
trust_level = "reject_candidate"
elif display_name_matches_exec and envelope_from_external:
trust_level = "phish_suspect"
10.3 邮件网关策略
text
□ 外部邮件加 [EXTERNAL] 横幅
□ DMARC fail + 声称内部域 → 隔离
□ 显示名=高管 && 发件地址非公司域 → 告警
□ URL 重写 + 沙箱 detonation
□ 附件宏默认剥离
十一、DMARC 报告解读
11.1 聚合报告(rua)
每日 XML 发到 rua= 邮箱,含:
text
· 声称从你域发出的 IP 列表
· SPF/DKIM 成功/失败统计
· 对齐失败来源(发现未授权发信)
工具:dmarcian、Postmark DMARC、Google 报表解析。
11.2 从 p=none 到 reject 路线图
text
周 1-2:p=none,收 rua,盘点合法发信源(营销邮件、工单系统、CRM)
周 3-4:补全 SPF include、上 DKIM,确认第三方 SaaS
周 5-6:p=quarantine; pct=25 → 50 → 100
周 7+:p=reject; sp=reject
十二、完整实验步骤(120 分钟)
text
□ 1. 准备可控子域,添加 SPF TXT
□ 2. opendkim-genkey,发布 default._domainkey TXT
□ 3. 添加 _dmarc p=none; rua=...
□ 4. Postfix+OpenDKIM 发一封合法信,确认三板斧 pass
□ 5. mail-tester 或 Gmail 原始头截图
□ 6. swaks 演示显示名伪造(外部域),记录仍进箱原因
□ 7. 演示相似域名思路(文字说明+DNS 对比表,勿滥注册)
□ 8. 将 DMARC 改为 p=quarantine,重发伪造 internal From,观察拒收/垃圾箱
□ 9. 写蓝队检查清单 10 条
□ 10. 实验报告:配置片段 + 头部分析 + 绕过与对策
十三、常见踩坑
| 问题 | 原因 | 解决 |
|---|---|---|
| SPF permerror | 语法错误、超过 10 DNS 查询 | 用 spf flatten 或减少 include |
| DKIM fail | DNS 未生效、selector 错 | dig 验证;私钥路径 |
| DMARC 永远 none | 不敢收紧 | 先 rua 监测再 quarantine |
| 转发后 SPF fail | 转发器 IP 不在 SPF | 保持 DKIM;考虑 ARC |
| Gmail 不进箱 | 无 PTR、IP 黑名单 | 配 rDNS;用 reputable IP |
| 内网 56.30 发不到公网 | NAT/25 端口封 | 用公网 VPS SMTP 或 mail-tester 子域实验 |
| 把 From 当 SPF 对象 | 概念混淆 | 记住 MAIL FROM vs Header From |
十四、法律与伦理
text
✅ 允许:自有域测试、授权钓鱼演练(Phishing Simulation)
❌ 禁止:伪造银行/政府邮件诈骗
❌ 禁止:未授权对他人域做 DMARC 绕过测试发信
企业钓鱼演练需 HR/法务/IT 书面批准,并提供举报通道。
十五、本篇小结
text
┌─────────────────────────────────────────────────────────────┐
│ 邮件安全 核心记忆 │
├─────────────────────────────────────────────────────────────┤
│ SPF:MAIL FROM 发信 IP 白名单(DNS TXT) │
│ DKIM:私钥签名 + DNS 公钥验签 │
│ DMARC:对齐 + 失败策略(none→quarantine→reject) │
│ 技术挡「域伪造」,不挡「显示名伪造/相似域/盗号」 │
│ 蓝队:Authentication-Results + 网关策略 + 用户培训 │
└─────────────────────────────────────────────────────────────┘
下一篇预告:《BGP 劫持是怎么回事?运营商级路由安全科普》------从企业邮件边界跃迁到互联网路由信任模型。
附录 A:DNS 记录模板
text
; SPF
@ IN TXT "v=spf1 mx ip4:203.0.113.10 include:_spf.google.com -all"
; DKIM
default._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3..."
; DMARC
_dmarc IN TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc@mailsec.lab; adkim=s; aspf=s"
附录 B:swaks 速查
bash
# 基础
swaks --to dest@example.com --from src@mailsec.lab --server SMTP_HOST
# 自定义头(显示名)
swaks --to victim@test.com --from att@evil.com \
--header "From: \"财务总监\" <att@evil.com>" \
--header "Subject: 测试" --body "lab"
# TLS
swaks --to ... --server smtp.gmail.com:587 --tls
附录 C:dig 一键检查
bash
DOMAIN=mailsec.lab
dig TXT $DOMAIN +short
dig TXT default._domainkey.$DOMAIN +short
dig TXT _dmarc.$DOMAIN +short
dig MX $DOMAIN +short
附录 D:与专栏前篇关联
| 前篇 | 关联 |
|---|---|
| DNS 安全 | SPF/DKIM/DMARC 全是 DNS TXT |
| HTTP/HTTPS | 钓鱼链接落地仍靠 Web 安全 |
| SSL 剥离 | 邮件中的 http 链接同样危险 |
| Kill Chain | 钓鱼是初始入侵常见向量 |