使用 GitHub Actions 在每次推送时审核域的电子邮件安全性
一个 GitHub 操作,使用 botoi API 检查 SPF、DMARC 和 DKIM 记录,如果任何记录丢失或配置错误,则构建失败。
您团队中的某人更新了 DNS 记录。 TXT 条目在提供商迁移期间被删除。 您的 SPF 记录悄悄超出了 10 次查找限制。 电子邮件开始成为垃圾邮件。 没有人 通知两周,直到客户提到他们从未收到您的发票。
基于 DNS 的电子邮件安全记录(SPF、DMARC、DKIM)是一种基础设施, 完美地工作,直到它不起作用。 当它损坏时,故障模式是静默的:没有错误, 没有警报,电子邮件消失到垃圾邮件文件夹中。
本指南设置了一个 GitHub Action,用于验证每次推送时的所有三个记录。 如果 任何记录丢失或配置错误,工作流程都会失败并告诉您发生了什么问题。
工作流程的作用
每次推动 main,动作:
- 呼叫 botoi
/v1/dns-security/spf-check用于验证您的 SPF 记录的端点 - 通话
/v1/dns-security/dmarc-check验证您的 DMARC 策略 - 通话
/v1/dns-security/dkim-check验证您的 DKIM 密钥是否已发布 - 如果任何检查失败,则以非零代码退出,从而阻止合并
GitHub Action 工作流程
创造 .github/workflows/dns-security.yml 在你的存储库中:
代替 yourdomain.com 与您的域名和 google 与
您的电子邮件提供商的 DKIM 选择器。 工作流程在每次推送时运行 main,
按每日计划进行,并且可以从“操作”选项卡手动触发。
每项检查验证什么
SPF(发件人策略框架)
SPF 声明哪些邮件服务器有权为您的域发送电子邮件。 应用程序编程接口 返回原始记录、已解析的机制列表以及记录是否有效。
需要关注的关键领域:
-
has_spf: 是否有以以下开头的TXT记录v=spf1? 如果为 false,则任何服务器都可以声称从您的域发送电子邮件。 -
valid: 记录解析正确吗? SPF 记录打破时 超过 10 个 DNS 查找限制或包含语法错误。 -
all_policy: 尾随机制。-all(硬失败)是 最强设定。~all(软失败)将未经授权的邮件标记为 可疑。+all完全违背了SPF的目的。
健康 SPF 记录的 API 响应示例:
DMARC(基于域的消息身份验证、报告和一致性)
DMARC 告诉接收服务器当 SPF 或 DKIM 检查失败时要做什么。 没有它, 即使有效的 SPF 和 DKIM 记录也无法防止欺骗。
需要关注的关键领域:
-
policy:失败的消息会发生什么情况。reject滴 他们,quarantine将它们发送到垃圾邮件,none不采取任何行动 (仅监控)。 -
pct:策略适用的邮件百分比。 从低位开始 推出期间的数量,然后移至 100。 -
reporting.rua:发送汇总报告的位置。 没有这个,你 对身份验证失败没有可见性。
DMARC 记录的 API 响应示例:
DKIM(域名密钥识别邮件)
DKIM 向传出消息添加加密签名。 接收服务器验证 针对 DNS 中发布的公钥进行签名。 如果钥匙丢失或被旋转 如果不更新 DNS,签名验证会失败。
需要关注的关键领域:
-
has_dkim:是否为给定选择器发布了 DKIM 密钥? 每封电子邮件 提供者使用不同的选择器名称。 -
public_key_length:NIST 建议至少 2048 位。 按键更短 超过 1024 位被认为是弱的。 -
key_type:大多数密钥使用 RSA。 Ed25519 键更小、更快,但 邮件提供商的支持有限。
DKIM 检查的 API 响应示例:
按提供商列出的常见 DKIM 选择器
| 电子邮件提供商 | DKIM 选择器 |
|---|---|
| 谷歌工作区 | google |
| 微软365 | selector1, selector2 |
| 亚马逊SES | 基于 UUID(检查您的 SES 仪表板) |
| Mailchimp/山魈 | k1 |
| 发送网格 | s1, s2 |
| 邮戳 | 每个域生成(检查 DNS 设置) |
扩展工作流程
多个域
如果您管理多个域,请使用矩阵策略来检查每个域。 添加 botoi API 密钥作为 GitHub 秘密,以避免达到免费套餐速率限制。
Slack 失败通知
添加一个在任何检查失败时触发的通知步骤。 这使用了 官方 Slack GitHub 操作:
Monorepo 设置
在 monorepo 中,您可能不希望每次推送时都运行 DNS 检查 包。 将触发器的范围限定为基础设施相关文件中的更改:
无论路径过滤器如何,计划的触发器仍然每天运行,因此您可以捕获 DNS 在存储库外部进行的更改。
使用 API 密钥实现更高的速率限制
如果您检查多个域或频繁运行工作流程,请添加您的 botoi API 密钥 作为 GitHub Actions 秘密:
- 转到您的存储库的“设置”> 秘密与变量> 行动
- 添加一个名为
BOTOI_API_KEY - 将 auth 标头添加到每个 curl 命令中:
检查失败时该怎么办
-
缺少 SPF 记录: 将 TXT 记录添加到您域的 DNS。 开始于
v=spf1 include:_spf.google.com ~all(将包含替换为您的 电子邮件提供商的 SPF 域)。 -
无效的 SPF 记录: 您可能达到了 10 个 DNS 查找限制。 使用
替换 SPF 平整工具
include:具有IP地址的机制, 或整合提供商。 -
缺少 DMARC 记录: 添加 TXT 记录于
_dmarc.yourdomain.com。 开始于v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com监视 在执行之前。 -
DMARC 政策为“无”: 这在推出期间很好。 一旦您确认
合法电子邮件通过 SPF 和 DKIM,移至
p=quarantine进而p=reject。 -
缺少 DKIM 记录: 验证您的选择器是否正确
电子邮件提供商(参见上表)。 密钥必须作为 TXT 记录发布在
[selector]._domainkey.yourdomain.com。 - DKIM 密钥太短: 通过您的 DKIM 密钥将您的 DKIM 密钥旋转至 2048 位 电子邮件提供商的管理面板,然后更新 DNS TXT 记录。
FAQ
- 此工作流程是否需要 botoi API 密钥?
- 不需要。免费套餐每分钟允许 5 个请求,无需 API 密钥。 工作流每次运行发出 3 个请求(SPF、DMARC、DKIM),这在限制范围内。 如果您对多个域或选择器运行检查,请将您的 API 密钥添加为 GitHub 密钥并将其传递到授权标头中。
- 我可以在一次工作流程运行中检查多个域吗?
- 是的。 循环检查脚本中的域数组。 每个域需要 3 个 API 调用,因此免费层运行每次调用处理一个域。 对于多个域,添加 botoi API 密钥以避免速率限制。
- 我应该使用什么 DKIM 选择器?
- 选择器取决于您的电子邮件提供商。 Google Workspace 使用“google”,Microsoft 365 使用“selector1”和“selector2”,Amazon SES 使用基于 UUID 的选择器。 检查您的 DNS TXT 记录中是否有与模式 [selector]._domainkey.yourdomain.com 匹配的条目。
- 此工作流程会阻止我的部署吗?
- 仅当检查失败时,这意味着您的电子邮件安全记录丢失或配置错误。 这就是要点:您希望在这些问题导致可交付性问题之前发现它们。 您可以将工作流程更改为发布警告而不是失败,方法是将“exit 1”替换为创建 GitHub 问题或发送 Slack 消息的步骤。
- 我应该多久运行一次此检查?
- 每次推送到主分支时都是基线。 添加计划的 cron 触发器(例如,每天上午 9 点)以捕获存储库外部所做的 DNS 更改,例如当团队成员在注册商仪表板中编辑记录时。
开始使用 botoi 构建
150+ 个 API 端点,涵盖查询、文本处理、图片生成和开发者工具。免费套餐,无需信用卡。