SPF 里嵌套了一堆 include,怎么审计才能既不超限又不漏授权?

1 SPF 里嵌套了一堆 include,怎么审计才能既不超限又不漏授权?
为什么嵌套会失控

RFC 7208 第 5.2 节规定 include递归调用对被引用域的 SPF 评估。递归意味着:你引用的域内部若再引用别的域,这些查询全部计入同一个 10 次预算(第 4.6.4 节)。

典型的失控路径是:业务每接入一个新服务就往记录里加一个 include,加时无人核算总量,删时无人负责——只增不减,直到某天突然 permerror。而 permerror 一旦发生,SPF 侧整体失效,影响面是全域的。

审计第一步:画出完整的展开树

不要只看本域记录的字面内容,必须逐层展开:

  1. 取本域 SPF 记录,列出所有 includeredirectamxptrexists
  2. 对每个 include/redirect 目标域,取其 SPF 记录,重复上一步。
  3. 记录每一层的节点名、计数项数量、是否解析成功,直到叶子节点。
  4. 累加得到总查询数,并单独统计解析为空或不存在的节点数(对应 void lookup 的 2 次预算)。

产出物应当是一张树状清单,而不是一个数字。有了树,才能判断该砍哪一枝。

审计第二步:给每个 include 找到「负责人」

对展开树上的每个第三方节点,逐一回答四个问题:

  • 它对应哪个业务?答不上来的,基本就是可以删的。
  • 还在用吗?对照近期聚合报告中是否有来自该源的流量。报告里连续多个周期为零,是下线的有力证据。
  • 它消耗几次查询?把成本标在树上,砍枝时优先砍「高成本 + 低流量」的。
  • 谁负责维护?明确到人或团队,写进变更记录。没有负责人的条目最容易变成僵尸条目。
授权最小化:能不 include 就不 include

降低嵌套的根本手段是减少需要引用的对象:

  1. 地址稳定的自有出口直接写 ip4/ip6不查 DNS、不受对方影响。
  2. 按用途拆分发送子域。让每个子域只引用自己真正需要的服务,各自维护独立的 SPF 记录,预算天然分摊。这是最推荐的结构性解法。
  3. 优先依赖 DKIM 对齐。DKIM 不消耗 SPF 预算,且能穿透转发。对于新接入的第三方,应优先要求其支持用你的域签名,而不是简单加一个 include。
扁平化的正确姿势与风险

扁平化(把第三方 include 展开成静态 ip4 列表)能立刻降低查询数,但它把「对方随时可变的地址」固化成了你的静态配置。若要采用,必须同时具备三项配套

  • 自动化同步。周期性重新解析上游记录并比对差异,人工维护必然滞后。
  • 变更告警。上游地址发生变化时立即通知负责人,而不是等用户报障。
  • 长度监控。展开后的记录可能变得很长,需关注 DNS 记录的字符串拼接与响应大小,避免引入新的解析问题。

判断原则:没有自动化能力就不要做扁平化。用「静默漏发」换「显式报错」,通常是更糟的交易——permerror 至少还能从报告里看见。

把审计变成常态
  • 周期复核。上游记录会变,展开树必须定期重算,不能一次算完就当永久有效。
  • 变更即审计。新增 include 前先算一遍展开后的总数,把「预算检查」写进上线流程。
  • 阈值预警。不要等到 10 才动手,建议在总数逼近上限时就触发治理,给自己留出缓冲余量。
  • 留存记录。每次变更记录时间、原因、变更前后的总查询数,便于回溯。

参考:RFC 7208 Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, Version 1