跳转到内容
Guide

SPF、DMARC 和 DKIM:完整的电子邮件身份验证指南

| 9 min read

了解 SPF、DMARC 和 DKIM 如何保护您的域免遭欺骗。 通过免费 API 调用在 30 秒内审核所有 3 条记录并修复 6 个最常见的错误配置。

Email security authentication flow diagram
Photo by Towfiqu barbhuiya on Unsplash

您的域通过了每次安全扫描。 您的 SSL 证书有效,您的标头很严格,您的 CSP 已被锁定。 然后,来自您的域的网络钓鱼电子邮件会进入客户的收件箱, 在“发件人”字段中输入您的公司名称。 该电子邮件是假的,但损坏是真实的。

发生这种情况是因为电子邮件是 1982 年设计的,没有内置的发件人验证。 任何人 可以在电子邮件上设置任何“发件人”地址,并且您的电子邮件中没有 SPF、DMARC 和 DKIM 记录 域,接收服务器无法捕获伪造行为。 超过 90% 的网络钓鱼攻击使用 域欺骗和错误配置的电子邮件身份验证都是敞开的大门。

本指南涵盖了每条记录的用途、它们如何协同工作以及如何审核所有三个记录 在任何域上使用单个脚本 botoi DNS 安全 API

电子邮件身份验证的工作原理

三个 DNS 记录充当防御层。 每个解决不同的问题:

  1. SPF 回答:“该服务器是否允许为此域发送电子邮件?”
  2. 德基姆 回答:“此消息在离开发件人服务器后是否被更改?”
  3. 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 有风险。 遵循以下路径:

  1. 开始于 p=none; rua=mailto:dmarc@example.com 收集报告 2-4 周
  2. 审查报告。 识别任何未通过身份验证的合法发件人。 修复他们的 SPF 包含和 DKIM 密钥。
  3. 移至 p=quarantine; pct=10 隔离 10% 的失败邮件
  4. 增加 pct 在您确认没有合法邮件受到影响后,在接下来的几周内将数量增加到 25、50,然后是 100
  5. 切换到 p=reject; pct=100 一旦您对自己的设置充满信心

pct API 响应中的字段显示您在此部署中的位置。 一个域名 在 pct=100policy=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=nonep=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 端点,涵盖查询、文本处理、图片生成和开发者工具。免费套餐,无需信用卡。