SPF、DMARC 和 DKIM:完整的电子邮件身份验证指南
了解 SPF、DMARC 和 DKIM 如何保护您的域免遭欺骗。 通过免费 API 调用在 30 秒内审核所有 3 条记录并修复 6 个最常见的错误配置。
您的域通过了每次安全扫描。 您的 SSL 证书有效,您的标头很严格,您的 CSP 已被锁定。 然后,来自您的域的网络钓鱼电子邮件会进入客户的收件箱, 在“发件人”字段中输入您的公司名称。 该电子邮件是假的,但损坏是真实的。
发生这种情况是因为电子邮件是 1982 年设计的,没有内置的发件人验证。 任何人 可以在电子邮件上设置任何“发件人”地址,并且您的电子邮件中没有 SPF、DMARC 和 DKIM 记录 域,接收服务器无法捕获伪造行为。 超过 90% 的网络钓鱼攻击使用 域欺骗和错误配置的电子邮件身份验证都是敞开的大门。
本指南涵盖了每条记录的用途、它们如何协同工作以及如何审核所有三个记录 在任何域上使用单个脚本 botoi DNS 安全 API。
电子邮件身份验证的工作原理
三个 DNS 记录充当防御层。 每个解决不同的问题:
- SPF 回答:“该服务器是否允许为此域发送电子邮件?”
- 德基姆 回答:“此消息在离开发件人服务器后是否被更改?”
- DMARC 回答:“如果 SPF 或 DKIM 失败,我该怎么办?我应该将报告发送到哪里?”
当有人发送一封声称来自 you@example.com, 接收
服务器按顺序检查这些记录。 如果 SPF 和 DKIM 均失败,且 DMARC 提示
p=reject,邮件在到达收件箱之前就会被丢弃。 没有全部
第三,存在可供攻击者利用的漏洞。
SPF:谁可以代表您发送
SPF(发件人策略框架)是位于域根目录的 DNS TXT 记录。 它列出了每一个
授权为您的域发送电子邮件的 IP 地址和邮件服务器。 当接收服务器
收到一封电子邮件 example.com,它检查 SPF 记录以查看发送的
服务器在批准的列表中。
使用单个 API 调用检查任何域的 SPF 记录:
curl -s -X POST https://api.botoi.com/v1/dns-security/spf-check \\
-H "Content-Type: application/json" \\
-d '{"domain": "example.com"}'
回复:
{
"success": true,
"data": {
"domain": "example.com",
"has_spf": true,
"record": "v=spf1 include:_spf.google.com ~all",
"mechanisms": ["include:_spf.google.com", "~all"],
"all_policy": "~all",
"includes": ["_spf.google.com"],
"valid": true
}
}
要检查的关键字段:
-
has_spf: 是否有以以下开头的 TXT 记录v=spf1存在? 如果是假的, 任何服务器都可以伪造来自您域的电子邮件。 -
valid: 记录解析没有错误吗? SPF记录悄然被打破 它们超出了 10 个 DNS 查找限制。 -
all_policy:定义未列出的发件人会发生什么情况的跟踪机制。-all(硬失败)拒绝他们。~all(软失败)使他们变得可疑。+all允许每个人,这违背了整个目的。
10 次查找限制
SPF 记录最多允许 10 次 DNS 查找。 每个 include:, a:,
mx:, 和 redirect: 机制算作一次查找。 嵌套包括
也算。 添加 Google Workspace、您的营销工具、交易电子邮件服务后,
如果使用 CRM,您很快就会达到这个极限。
当查找次数超过 10 次时,整个 SPF 记录将失效。 API 的 valid
领域抓住了这一点。 通过将嵌套包含展平到 IP 范围或合并来修复此问题
提供商。
DMARC:检查失败时该怎么办
DMARC(基于域的消息身份验证、报告和一致性)将 SPF 和 DKIM 联系起来
在一起。 它住在 _dmarc.example.com 作为TXT记录并告知接收
服务器做两件事:如何处理身份验证失败的消息以及发送到哪里
有关这些失败的报告。
检查您的 DMARC 记录:
curl -s -X POST https://api.botoi.com/v1/dns-security/dmarc-check \\
-H "Content-Type: application/json" \\
-d '{"domain": "example.com"}'
回复:
{
"success": true,
"data": {
"domain": "example.com",
"has_dmarc": true,
"record": "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; pct=100",
"policy": "reject",
"subdomain_policy": null,
"reporting": {
"rua": ["mailto:dmarc@example.com"],
"ruf": []
},
"pct": 100,
"alignment": {
"dkim": "r",
"spf": "r"
}
}
}
DMARC 政策
这 policy 字段确定失败消息会发生什么情况:
-
none: 不采取任何行动。 仅监控。 您收到报告,但仍然收到欺骗性电子邮件 到达收件箱。 -
quarantine:将失败的邮件移至垃圾邮件。 收件人仍然可以找到它们 如果他们看的话。 -
reject:完全删除失败的消息。 最强的保护,但是 配置错误意味着丢失合法电子邮件。
安全 DMARC 推出策略
直接前往 p=reject 有风险。 遵循以下路径:
- 开始于
p=none; rua=mailto:dmarc@example.com收集报告 2-4 周 - 审查报告。 识别任何未通过身份验证的合法发件人。 修复他们的 SPF 包含和 DKIM 密钥。
- 移至
p=quarantine; pct=10隔离 10% 的失败邮件 - 增加
pct在您确认没有合法邮件受到影响后,在接下来的几周内将数量增加到 25、50,然后是 100 - 切换到
p=reject; pct=100一旦您对自己的设置充满信心
这 pct API 响应中的字段显示您在此部署中的位置。 一个域名
在 pct=100 和 policy=reject 有充分的保护。
DKIM:每封电子邮件上的加密签名
DKIM(域名密钥识别邮件)将加密签名添加到每个邮件的标头中 传出消息。 发送服务器使用私钥对消息进行签名; 接收服务器 根据您的 DNS 中发布的公钥对其进行验证。 如果消息在传输过程中被更改 (标题已更改,正文已修改,通过重写内容的邮件列表转发), 签名失败。
DKIM 现场记录 [selector]._domainkey.example.com。 选择器是一个标签
您的电子邮件提供商分配的,例如 google 对于 Google Workspace 或 selector1
对于 Microsoft 365。
检查 DKIM 记录:
curl -s -X POST https://api.botoi.com/v1/dns-security/dkim-check \\
-H "Content-Type: application/json" \\
-d '{"domain": "example.com", "selector": "google"}'
回复:
{
"success": true,
"data": {
"domain": "example.com",
"selector": "google",
"has_dkim": true,
"record": "v=DKIM1; k=rsa; p=MIIBIjANBgkq...",
"key_type": "rsa",
"public_key_length": 2048
}
}
关键领域:
-
has_dkim:是否为该选择器发布了公钥? 如果错误,DKIM 使用此选择器签名的所有消息的验证都会失败。 -
public_key_length:NIST 建议至少 2048 位。 1024 以下的按键 位的强度不足以分解。 -
key_type:RSA 是标准。 Ed25519 更快并且使用更短的键,但是 邮件提供商的支持有限。
DKIM 和电子邮件转发
这就是为什么即使配置了 SPF,DKIM 也很重要。 当有人转发您的电子邮件时, 转发服务器的 IP 不在您的 SPF 记录中,因此 SPF 失败。 但是DKIM签名 转发后仍然存在(只要内容不被修改)。 DMARC 通过,如果任一 SPF 或 DKIM 对齐,因此 DKIM 是转发邮件的安全网。
三者如何协同工作
| 威胁 | SPF | 德基姆 | DMARC |
|---|---|---|---|
| 来自未经授权的服务器的欺骗性电子邮件 | 检测到 | 检测到(无有效签名) | 执行政策 |
| 消息正文在传输过程中被篡改 | 未检测到 | 检测到 | 执行政策 |
| 从合法发件人转发的电子邮件 | 失败(不同服务器IP) | 通过(签名完好) | 如果 DKIM 对齐则通过 |
| 子域欺骗 (user@fake.example.com) | 无保护 | 无保护 | 块通过 sp=reject |
| 身份验证失败的可见性 | 没有任何 | 没有任何 | 发送汇总报告 |
没有任何单一记录能够提供全面的覆盖。 没有 DMARC 的 SPF 意味着不会强制失败。 没有 SPF 的 DKIM 意味着拥有有效密钥的任何人都可以从您的域发送。 没有两者的 DMARC SPF 和 DKIM 没有什么可强制执行的。
30 秒内审核您的域名
此 shell 脚本检查所有三个记录并打印通过/失败摘要。 它使用 botoi DNS安全API; 每分钟最多 5 个请求无需 API 密钥。
#!/bin/bash
# Audit SPF, DMARC, and DKIM for a domain in 30 seconds
DOMAIN=\${1:-"example.com"}
DKIM_SELECTOR=\${2:-"google"}
API="https://api.botoi.com/v1/dns-security"
PASS=0
FAIL=0
echo "Auditing email authentication for \$DOMAIN"
echo "==========================================="
# SPF check
SPF=\$(curl -s -X POST "\$API/spf-check" \\
-H "Content-Type: application/json" \\
-d "{\\"domain\\": \\"\$DOMAIN\\"}")
HAS_SPF=\$(echo "\$SPF" | jq -r '.data.has_spf')
SPF_VALID=\$(echo "\$SPF" | jq -r '.data.valid')
SPF_RECORD=\$(echo "\$SPF" | jq -r '.data.record // "not found"')
ALL_POLICY=\$(echo "\$SPF" | jq -r '.data.all_policy // "none"')
if [ "\$HAS_SPF" = "true" ] && [ "\$SPF_VALID" = "true" ]; then
echo "[PASS] SPF: \$SPF_RECORD"
PASS=\$((PASS + 1))
else
echo "[FAIL] SPF: \$SPF_RECORD"
FAIL=\$((FAIL + 1))
fi
if [ "\$ALL_POLICY" = "+all" ]; then
echo " WARNING: +all allows any server to send as your domain"
fi
# DMARC check
DMARC=\$(curl -s -X POST "\$API/dmarc-check" \\
-H "Content-Type: application/json" \\
-d "{\\"domain\\": \\"\$DOMAIN\\"}")
HAS_DMARC=\$(echo "\$DMARC" | jq -r '.data.has_dmarc')
POLICY=\$(echo "\$DMARC" | jq -r '.data.policy // "not set"')
PCT=\$(echo "\$DMARC" | jq -r '.data.pct // 0')
if [ "\$HAS_DMARC" = "true" ]; then
echo "[PASS] DMARC: policy=\$POLICY pct=\$PCT%"
PASS=\$((PASS + 1))
else
echo "[FAIL] DMARC: no record found"
FAIL=\$((FAIL + 1))
fi
if [ "\$POLICY" = "none" ]; then
echo " WARNING: policy=none only monitors, does not enforce"
fi
# DKIM check
DKIM=\$(curl -s -X POST "\$API/dkim-check" \\
-H "Content-Type: application/json" \\
-d "{\\"domain\\": \\"\$DOMAIN\\", \\"selector\\": \\"\$DKIM_SELECTOR\\"}")
HAS_DKIM=\$(echo "\$DKIM" | jq -r '.data.has_dkim')
KEY_TYPE=\$(echo "\$DKIM" | jq -r '.data.key_type // "unknown"')
KEY_LEN=\$(echo "\$DKIM" | jq -r '.data.public_key_length // 0')
if [ "\$HAS_DKIM" = "true" ]; then
echo "[PASS] DKIM: selector=\$DKIM_SELECTOR key_type=\$KEY_TYPE key_length=\$KEY_LEN"
PASS=\$((PASS + 1))
else
echo "[FAIL] DKIM: no record for selector '\$DKIM_SELECTOR'"
FAIL=\$((FAIL + 1))
fi
if [ "\$HAS_DKIM" = "true" ] && [ "\$KEY_LEN" -lt 2048 ] 2>/dev/null; then
echo " WARNING: DKIM key is \$KEY_LEN bits (2048 recommended)"
fi
# Summary
echo ""
echo "Results: \$PASS passed, \$FAIL failed"
[ "\$FAIL" -eq 0 ] && echo "All checks passed." || exit 1
运行它:
bash audit.sh example.com google
第一个参数是你的域; 第二个是您的 DKIM 选择器。 该脚本制作了3个API 调用(在免费套餐限制内),检查每条记录,标记弱配置警告, 如果任何检查失败,则以非零代码退出。 将其放入 cron 作业或 CI 管道中 用于持续监控。
如果您更喜欢 JavaScript,这里是与异步函数相同的审核:
async function auditEmailAuth(domain, dkimSelector = "google") {
const api = "https://api.botoi.com/v1/dns-security";
const headers = { "Content-Type": "application/json" };
const [spf, dmarc, dkim] = await Promise.all([
fetch(\`\${api}/spf-check\`, {
method: "POST",
headers,
body: JSON.stringify({ domain }),
}).then((r) => r.json()),
fetch(\`\${api}/dmarc-check\`, {
method: "POST",
headers,
body: JSON.stringify({ domain }),
}).then((r) => r.json()),
fetch(\`\${api}/dkim-check\`, {
method: "POST",
headers,
body: JSON.stringify({ domain, selector: dkimSelector }),
}).then((r) => r.json()),
]);
return {
domain,
spf: {
exists: spf.data.has_spf,
valid: spf.data.valid,
record: spf.data.record,
allPolicy: spf.data.all_policy,
},
dmarc: {
exists: dmarc.data.has_dmarc,
policy: dmarc.data.policy,
pct: dmarc.data.pct,
reporting: dmarc.data.reporting?.rua || [],
},
dkim: {
exists: dkim.data.has_dkim,
selector: dkimSelector,
keyType: dkim.data.key_type,
keyLength: dkim.data.public_key_length,
},
};
}
// Usage
const report = await auditEmailAuth("example.com", "google");
console.log(JSON.stringify(report, null, 2));
常见的提供商配置
每个电子邮件提供商都有自己的 SPF,包括域和 DKIM 选择器。 这是值 对于最常见的提供商:
| 提供者 | SPF包括 | DKIM 选择器 |
|---|---|---|
| 谷歌工作区 | include:_spf.google.com |
google |
| 微软365 | include:spf.protection.outlook.com |
selector1, selector2 |
| 亚马逊SES | include:amazonses.com |
基于 UUID(检查 SES 控制台) |
| 发送网格 | include:sendgrid.net |
s1, s2 |
| 邮戳 | include:spf.mtasv.net |
每个域(检查邮戳 DNS 设置) |
| Mailchimp/山魈 | include:servers.mcsv.net |
k1 |
如果您使用多个提供商,您的 SPF 记录将在单个 TXT 条目中包含所有这些提供商。
例如: v=spf1 include:_spf.google.com include:sendgrid.net ~all。 手表
添加提供商时的 10 次查找限制。
要点
-
SPF 控制哪些服务器可以为您的域发送电子邮件。 检查一下
的
/v1/dns-security/spf-check端点。 注意 10 次查找限制并 避免+all。 -
DMARC 定义 SPF 或 DKIM 失败时会发生什么情况。 逐渐推出
p=none到p=reject使用pct场地。 始终设置 一个rua接收报告的地址。 -
德基姆 使用加密签名证明消息完整性。 使用 2048 位
最少密钥并验证您的选择器是否已发布
/v1/dns-security/dkim-check。 - 所有三个记录一起工作。 SPF 本身并不能阻止转发的电子邮件欺骗。 仅 DKIM 不告诉接收者在失败时该怎么做。 没有 SPF 和 DKIM 的 DMARC 无需强制执行。
- 自动化您的检查。 按计划或在 CI 中运行审核脚本以捕获 DNS 漂移、提供商 迁移和意外记录删除,以免影响可交付性。
FAQ
- 什么是 SPF 记录?为什么需要一个?
- SPF(发件人策略框架)记录是一个 DNS TXT 条目,其中列出了有权代表您的域发送电子邮件的每台服务器。 如果没有,互联网上的任何服务器都可以发送看似来自您的域的电子邮件,而接收邮件服务器无法区分两者。 大多数域需要至少一个包含其电子邮件提供商的 SPF 记录。
- 如何检查我的域是否有 DMARC 记录?
- 在 _dmarc.yourdomain.com 查询 DNS TXT 记录。 您可以使用 dig、nslookup 或使用您的域名向 botoi DMARC 检查 API 发送 POST 请求来执行此操作。 API 返回完整的解析记录,包括策略、百分比和报告地址。
- 如果我已经有 SPF 了,还需要 DKIM 吗?
- 是的。 SPF 和 DKIM 解决不同的问题。 SPF验证发送服务器是否被授权; DKIM 验证邮件内容在传输过程中没有更改。 电子邮件转发会破坏 SPF 对齐,但保留 DKIM 签名。 DMARC 至少需要其中之一才能通过,因此同时拥有两者可以让您在发生转发或中继时具有弹性。
- 如果我将 DMARC 策略设置为立即拒绝,会发生什么情况?
- 接收服务器将丢弃所有未通过 SPF 和 DKIM 对齐的邮件。 如果您的记录配置错误、忘记了第三方发件人或未考虑到转发规则,合法电子邮件将被默默丢弃。 从 p=none 开始收集报告,然后转到 10% 的 p=quarantine,只有在确认所有合法邮件都通过身份验证后才设置 p=reject。
- 我应该多久审核一次我的电子邮件身份验证记录?
- 至少在每次 DNS 更改、电子邮件提供商迁移或添加新的发送服务(营销工具、交易电子邮件、CRM)后进行检查。 每周一次的自动检查可发现静默破坏,例如超出 SPF 10 查找限制或过期的 DKIM 密钥。 botoi DNS 安全 API 端点使此操作可以轻松地在 CI 或 cron 作业中实现自动化。
开始使用 botoi 构建
150+ 个 API 端点,涵盖查询、文本处理、图片生成和开发者工具。免费套餐,无需信用卡。