CAA DNS 记录:证书颁发机构授权机制的原理、协议与部署实践
概述
证书颁发机构授权(Certification Authority Authorization,CAA)是一种 DNS 资源记录类型,允许域名所有者指定哪些证书颁发机构(CA)被允许为其域名签发证书。CAA 的核心价值在于:将证书签发的授权决策权从 CA 侧转移到域名所有者侧,为域名所有者提供了一种主动防御恶意或错误签发证书的机制。
CAA 并非孤立的安全机制,而是 Web PKI 多层防御体系中的一环:
┌─────────────────────────────────────────────────────┐
│ Web PKI 纵深防御体系 │
│ │
│ 域名所有者控制层 │
│ ┌──────────────────────────────┐ │
│ │ CAA DNS 记录 ← 本文重点 │ ← 主动策略声明 │
│ └──────────────────────────────┘ │
│ │
│ CA 签发流程层 │
│ ┌──────────────────────────────┐ │
│ │ 基线要求(BR)强制 CAA 检查 │ ← 流程强制 │
│ └──────────────────────────────┘ │
│ │
│ 签发后审计层 │
│ ┌──────────────────────────────┐ │
│ │ 证书透明度(CT)日志 │ ← 事后可审计 │
│ └──────────────────────────────┘ │
│ │
│ 传输层 │
│ ┌──────────────────────────────┐ │
│ │ DNSSEC 签名保护 CAA 记录 │ ← 防篡改 │
│ └──────────────────────────────┘ │
└─────────────────────────────────────────────────────┘CAA 与 CT 的关系尤其重要:CAA 是预防性的(阻止不该签发的证书),CT 是检测性的(发现已经签发的证书)。两者互补而非替代。
设计动机:CA 签发权力的制衡
问题的本质
在传统 PKI 模型中,任何公开信任的 CA 都可以为任何域名签发证书。这一设计源于 X.509 信任模型——只要 CA 的根证书被浏览器/操作系统信任,该 CA 签发的任何证书都被信任。
这意味着:
- 如果某个 CA 被入侵(如 2011 年 DigiNotar 事件),攻击者可以为任意域名(包括
google.com)签发伪造证书 - 如果某个 CA 操作失误(如错误验证域名所有权),可能为错误的主体签发证书
- 如果 CA 的 subordinate CA 被滥用,影响范围可能波及数百万域名
CAA 的解决方案
CAA 的核心思想极其简洁:域名所有者通过 DNS 记录声明"只有这些 CA 可以为我的域名签发证书",CA 在签发前必须检查并遵守这一声明。
域名所有者的 DNS 区域文件:
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 issue "digicert.com"
example.com. IN CAA 0 issuewild "letsencrypt.com"
example.com. IN CAA 0 iodef "mailto:security@example.com"上述记录的含义:
- 只允许 Let's Encrypt 和 DigiCert 为
example.com及其子域名签发非通配符证书 - 只允许 Let's Encrypt 签发通配符证书
- 如果 CA 发现违反 CAA 记录的签发请求,通过邮件通知
security@example.com
协议规范:从 RFC 8659 到 RFC 8657
演进历程
CAA 标准经历了三个主要阶段:
| 阶段 | 标准 | 发布时间 | 核心贡献 |
|---|---|---|---|
| 初始标准化 | RFC 6844 | 2013 年 1 月 | 定义 CAA 记录的基本格式和语义属性 |
| 核心修订 | RFC 8659 | 2019 年 5月 | 全面修订,修复已知问题,明确处理规则 |
| 扩展增强 | RFC 8657 | 2019 年 11 月 | 新增 accounturi 和 validationmethods 参数 |
CAA 记录的 Wire 格式
CAA DNS 记录的 Wire 格式由三个字段组成:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
│ Flags │
├─────────────────────────────────────────────────────┤
│ Tag Length │
├─────────────────────────────────────────────────────┤
│ Tag │
├─────────────────────────────────────────────────────┤
│ Value │
│ ... │
└─────────────────────────────────────────────────────┘Flags(标志位):1 字节,目前仅定义了第 7 位(Critical Flag):
Bit 7 (Critical Flag):
1 = 关键标志:CA 不理解该属性时必须拒绝签发
0 = 非关键标志:CA 不理解该属性时可忽略Tag(标签):标识属性类型的 ASCII 字符串,如 issue、issuewild、iodef。
Value(值):属性的具体值,格式取决于属性类型。
三类核心属性
#### 1. issue:指定授权的 CA
issue 属性是最常用的 CAA 属性,指定允许为域名签发证书的 CA。
语法:
issue <CA-domain-name>
示例:
example.com. IN CAA 0 issue "letsencrypt.org"处理规则:
- CA 的域名必须与
issue值匹配(精确匹配,不支持通配符) - 如果
issue值为空字符串(issue ""),表示禁止任何 CA 为该域名签发证书 - 多个
issue记录表示"任一匹配即可"
# 禁止任何 CA 为 example.com 签发证书
example.com. IN CAA 0 issue ""
# 允许 Let's Encrypt 或 DigiCert 签发
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 issue "digicert.com"#### 2. issuewild:通配符证书控制
issuewild 属性专门控制通配符证书(*.example.com)的签发授权。
语法:
issuewild <CA-domain-name>关键规则:issuewild 的优先级高于 issue。当 CA 签发通配符证书时,只检查 issuewild 记录,忽略 issue 记录。
# 允许 Let's Encrypt 签发所有证书(包括通配符)
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 issuewild "letsencrypt.org"
# 允许 DigiCert 签发非通配证书,但禁止其签发通配符证书
example.com. IN CAA 0 issue "digicert.com"
# 注意:没有 issuewild 指向 digicert.com这一分离设计的意义在于:通配符证书的安全影响范围远大于单域名证书(一个 *.example.com 证书可用于所有子域名),因此需要更严格的控制。
#### 3. iodef:违规通知
iodef 属性指定当 CA 检测到违反 CAA 记录的证书请求时,应如何通知域名所有者。
语法:
iodef <mailto-uri>
iodef <https-uri>
示例:
example.com. IN CAA 0 iodef "mailto:security@example.com"
example.com. IN CAA 0 iodef "https://example.com/caa-report"iodef 使用 Incident Object Description Exchange Format(IODEF,RFC 7970)标准,支持邮件和 HTTP 两种通知方式。
实际效果:虽然 iodef 在理论上提供了实时通知能力,但在实践中,大多数 CA 并不自动发送 iodef 通知。CA/B 论坛的基线要求也未强制要求 CA 实现 iodef 通知。因此,iodef 更多是作为策略声明存在,而非可靠的检测机制。
RFC 8657 扩展参数
RFC 8657 为 CAA 引入了两个关键扩展参数,大幅增强了 CAA 的表达能力。
#### accounturi:CA 账户绑定
accounturi 参数允许域名所有者将签发权限限制到特定 CA 的特定账户。
语法:
issue <CA-domain-name>;<parameter-name>=<parameter-value>
示例:
example.com. IN CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/123456"安全语义:
- 只有 Let's Encrypt 的账户
123456可以为example.com签发证书 - 即使攻击者获得了 Let's Encrypt 的其他账户,也无法为
example.com签发证书 - 这大幅缩小了攻击面——从"任何 Let's Encrypt 账户"缩小到"特定账户"
accounturi 的核心价值在于防止 CA 内部的横向移动攻击。如果 CA 的某个账户被入侵,accounturi 可以限制该账户只能为特定域名签发证书。#### validationmethods:验证方法绑定
validationmethods 参数允许域名所有者限制 CA 在验证域名所有权时使用的方法。
语法:
issue <CA-domain-name>; validationmethods=<method1>,<method2>
示例:
example.com. IN CAA 0 issue "letsencrypt.org; validationmethods=dns-01,http-01"安全语义:
- 只允许 Let's Encrypt 使用 DNS-01 或 HTTP-01 验证方法
- 不允许使用 TLS-ALPN-01 等其他方法
- 这可以防止攻击者利用验证方法的弱点(如 TLS-ALPN-01 的共享证书问题)
CAA 属性优先级与冲突处理
当 CAA 记录中存在多个属性时,处理规则如下:
┌─────────────────────────────────────────────────────┐
│ CAA 属性优先级 │
│ │
│ 1. issuewild > issue │
│ 签发通配符证书时只检查 issuewild │
│ │
│ 2. Critical Flag > Non-critical │
│ CA 不理解的关键属性 → 必须拒绝 │
│ │
│ 3. 多值 OR 关系 │
│ 多个 issue 记录 → 任一匹配即可 │
│ │
│ 4. 空值 = 禁止 │
│ issue "" → 禁止所有签发 │
│ │
│ 5. 无 CAA 记录 = 不限制 │
│ 域名没有 CAA 记录 → 任何 CA 都可签发 │
└─────────────────────────────────────────────────────┘CA/B 论坛基线要求中的 CAA
强制检查要求
CA/B 论坛(CA/Browser Forum)的基线要求(Baseline Requirements,BR)是公开信任 CA 必须遵守的行业规范。自 BR 1.6.0 版本起,CAA 检查已成为强制要求。
核心要求:
┌──────────────────────────────────────────────────────────────┐
│ CA/B BR §3.2.2.8 — CAA 检查要求 │
│ │
│ 1. CA 在签发证书前,必须查询 DNS 中的 CAA 记录 │
│ 2. 如果存在 CAA 记录,CA 必须检查是否被授权 │
│ 3. 如果未被授权,CA 必须拒绝签发 │
│ 4. CA 必须在证书签发日志中记录 CAA 检查结果 │
│ 5. CAA 检查必须在证书签发的 8 小时内完成 │
│ 6. CA 必须处理 issue、issuewild、iodef 属性 │
│ 7. CA 必须处理 RFC 8657 的 accounturi 和 validationmethods │
│ (自 SC-098v2 生效,2027 年 3 月 15 日起强制) │
└──────────────────────────────────────────────────────────────┘SC-098v2:RFC 8657 参数成为强制要求
2026 年 5 月 13 日,CA/B 论坛通过了 SC-098v2 投票,规定自 2027 年 3 月 15 日起,所有公开信任的 CA 必须处理 RFC 8657 定义的 accounturi 和 validationmethods 参数。
这一要求的背景是:
- ACME 协议的广泛采用:Let's Encrypt 等 CA 使用 ACME 协议自动化证书签发,
accounturi可以将 CAA 策略绑定到特定 ACME 账户 - 验证方法的多样化:ACME 支持多种域名验证方法(DNS-01、HTTP-01、TLS-ALPN-01),不同方法的安全特性不同
- 安全事件的教训:某些安全事件源于 CA 未正确处理 CAA 扩展参数
CAA TTL 与缓存
CA 在查询 CAA 记录时,必须遵守 DNS TTL(生存时间):
- CA 不得缓存 CAA 记录超过其 TTL 值
- 如果 TTL 为 0,CA 必须在每次签发时实时查询
- CA/B BR 规定:如果 CAA 查询失败(NXDOMAIN 除外),CA 必须在 8 小时内完成签发
CAA 与 DNSSEC 的协同
为什么 CAA 需要 DNSSEC
CAA 记录存储在 DNS 中,而 DNS 协议本身缺乏完整性保护。如果攻击者能够篡改 DNS 响应(通过 DNS 劫持、中间人攻击等),就可以绕过 CAA 保护:
攻击场景(无 DNSSEC):
1. 域名所有者设置了 CAA 记录:只允许 Let's Encrypt
2. 攻击者劫持 DNS 查询,将 CAA 记录替换为:允许某个恶意 CA
3. 恶意 CA 为域名签发伪造证书
4. 浏览器信任该证书(因为 CA 根证书被信任)DNSSEC 通过对 DNS 记录进行数字签名,确保 DNS 响应的完整性和真实性。CAA 在没有 DNSSEC 的环境下,安全性被削弱为 DNS 的安全性。
DNSSEC 签名链
┌─────────────────────────────────────────────────────┐
│ DNSSEC 签名链保护 CAA │
│ │
│ Root Zone (.) │
│ ├── 签名 TLD 密钥(.com 的 DNSKEY) │
│ │ └── 签名区域密钥(example.com 的 DNSKEY) │
│ │ └── 签名 CAA 记录的 RRSIG │
│ │ │
│ 验证链: │
│ Root Trust Anchor → DS → DNSKEY → DS → DNSKEY │
│ → RRSIG(CAA) → CAA 记录 │
│ │
│ 如果任何环节被篡改,验证失败,CAA 记录不可信 │
└─────────────────────────────────────────────────────┘部署建议
对于安全要求高的域名,强烈建议同时部署 CAA 和 DNSSEC:
- 先部署 DNSSEC:确保 DNS 响应的完整性
- 再部署 CAA:在 DNS 安全的基础上添加签发控制
- 监控 CAA 有效性:定期检查 CAA 记录是否被意外修改
CAA 与证书透明度的互补关系
CAA 和 CT 是 Web PKI 安全体系中两个互补的机制:
┌──────────────────────────────────────────────────────────────┐
│ CAA vs CT 对比 │
│ │
│ 维度 │ CAA │ CT │
│ ──────────────┼─────────────────────┼─────────────────────── │
│ 作用时机 │ 签发前(预防性) │ 签发后(检测性) │
│ 安全目标 │ 阻止不该签发的证书 │ 发现已签发的证书 │
│ 实施主体 │ 域名所有者 │ CA │
│ 依赖基础设施 │ DNS(+DNSSEC) │ 独立日志基础设施 │
│ 发现延迟 │ 即时(签发时阻止) │ 可延迟(日志监控) │
│ 覆盖范围 │ 仅声明授权的 CA │ 所有公开证书 │
│ 篡改难度 │ 需攻破 DNS │ 需攻破日志服务器 │
│ 国密适用性 │ 直接适用 │ 需国密 CT 日志 │
└──────────────────────────────────────────────────────────────┘关键洞察:CAA 和 CT 不是替代关系,而是互补关系。一个完整的安全策略应该同时使用两者:
- CAA:阻止未经授权的签发("不该签的不让签")
- CT:发现所有已签发的证书("签了什么都知道")
实施中的关键问题
1. CAA 记录的 DNS 传播延迟
CAA 记录作为 DNS 记录,其变更需要时间传播到全球 DNS 缓存。这意味着:
- 新增 CAA 记录:可能需要等待旧缓存过期(最多 TTL 时间)
- 修改 CAA 记录:在传播窗口期内,不同地理位置的 CA 可能看到不同的 CAA 记录
- 删除 CAA 记录:旧缓存可能继续生效,导致 CA 继续遵守已删除的 CAA 策略
- 设置合理的 TTL 值(建议 3600 秒 = 1 小时)
- 在变更 CAA 记录前,先降低 TTL 值,等待旧缓存过期
- 变更后使用多个地理位置的 DNS 服务器验证
2. 子域名的 CAA 继承
CAA 记录具有继承性:如果子域名没有自己的 CAA 记录,将继承父域名的 CAA 记录。
example.com. CAA 0 issue "letsencrypt.org"
www.example.com. (无 CAA 记录,继承父域名)
→ www.example.com 也只允许 Let's Encrypt 签发重要细节:
- 继承是递归的:
a.b.example.com会继承b.example.com→example.com的 CAA - 一旦子域名设置了 CAA 记录,继承链断裂,不再受父域名 CAA 影响
- 通配符匹配:
*.example.com的 CAA 记录匹配所有直接子域名
3. CAA 与内部 PKI
CAA 机制仅适用于公开信任的 CA。企业内部 PKI(如自建的 CA 体系)不受 CAA 约束,因为:
- 内部 CA 不在浏览器/操作系统的信任列表中
- 内部 CA 通常不查询外部 DNS 的 CAA 记录
- 内部 PKI 的安全边界是企业网络本身
4. CAA 绕过风险
CAA 并非万能,存在以下绕过风险:
┌─────────────────────────────────────────────────────┐
│ CAA 绕过场景 │
│ │
│ 1. DNS 劫持 │
│ 攻击者篡改 DNS 响应,移除或修改 CAA 记录 │
│ 缓解:部署 DNSSEC │
│ │
│ 2. CA 不合规 │
│ CA 未正确实施 CAA 检查 │
│ 缓解:CA/B 论坛审计、浏览器吊销 │
│ │
│ 3. 时间窗口攻击 │
│ 在 CAA 记录变更的传播窗口期内利用旧缓存 │
│ 缓解:合理设置 TTL,变更前等待传播完成 │
│ │
│ 4. 子域名接管 │
│ 攻击者控制废弃子域名的 DNS,绕过父域名 CAA │
│ 缓解:定期审计 DNS 记录,清理废弃子域名 │
│ │
│ 5. 通配符滥用 │
│ 攻击者利用合法通配符证书覆盖未授权的子域名 │
│ 缓解:严格限制 issuewild 授权 │
└─────────────────────────────────────────────────────┘国密 PKI 体系中的 CAA 适用性
直接适用性分析
CAA 作为 DNS 层面的安全机制,其协议本身与算法无关,因此在协议层面对国密 PKI 体系完全适用:
- DNS 层面无国密依赖:CAA 记录是标准的 DNS 资源记录,不依赖任何特定密码算法
- CA 检查逻辑通用:国密 CA 在签发证书前同样可以查询 CAA 记录
- 与国密算法无关:CAA 控制的是"谁可以签发",而非"用什么算法签发"
国密体系的特殊考虑
然而,国密 PKI 体系在实际部署 CAA 时需要考虑以下特殊因素:
┌─────────────────────────────────────────────────────┐
│ 国密 PKI 体系 CAA 部署考虑 │
│ │
│ 1. 内部 CA vs 公开 CA │
│ 国密 CA(如 CFCA、中国金融认证中心)多为内部 CA │
│ 内部 CA 的签发策略由内部策略引擎控制 │
│ CAA 可以作为内部策略引擎的输入之一 │
│ │
│ 2. 双证书体系 │
│ 国密系统通常同时使用 SM2 和国际算法双证书 │
│ CAA 记录需要同时覆盖两类 CA │
│ │
│ 3. DNSSEC 部署率 │
│ 国内 DNSSEC 部署率较低 │
│ 在没有 DNSSEC 的环境下,CAA 安全性受限 │
│ │
│ 4. 自动化签发 │
│ 国密 CA 的签发流程通常不如 Let's Encrypt 自动化 │
│ accounturi 等扩展参数的价值相对有限 │
│ │
│ 5. 监管合规 │
│ 等保 2.0 和密评对 CA 签发流程有明确要求 │
│ CAA 可以作为合规措施的一部分 │
└─────────────────────────────────────────────────────┘部署建议
对于国密 PKI 体系,建议:
- 公开信任的国密 CA(如 CFCA 的公开服务)应完整支持 CAA 检查和 RFC 8657 扩展参数
- 内部国密 CA 可以在内部策略引擎中实现 CAA 逻辑,作为签发决策的输入
- 双证书环境 的 CAA 记录应同时包含国际 CA 和国密 CA
- 推动 DNSSEC 部署,为 CAA 提供完整性保护基础
总结
CAA DNS 记录是 Web PKI 安全体系中一个设计简洁但影响深远的机制。通过在 DNS 层面声明签发授权,CAA 将证书签发的控制权从 CA 侧部分转移到域名所有者侧,有效缩小了恶意签发和错误签发的攻击面。
CAA 的核心价值不仅在于其技术机制,更在于其安全哲学的转变:从"信任 CA 不会犯错"到"不信任任何单一实体,通过制衡机制降低风险"。这一哲学与纵深防御、零信任等现代安全理念一脉相承。
随着 SC-098v2 在 2027 年 3 月将 RFC 8657 扩展参数变为强制要求,CAA 的表达能力和安全精度将进一步提升。域名所有者应积极部署 CAA 记录,并结合 DNSSEC、CT 日志等机制,构建多层次的证书安全防御体系。
参考来源
- RFC 8659 - DNS Certification Authority Authorization (CAA) Resource Record — CAA 核心标准
- RFC 8657 - CAA Record Extensions for Account URI and ACME Method Binding — CAA 扩展参数
- RFC 6844 - DNS Certification Authority Authorization (CAA) Resource Record — CAA 初始标准(已被 RFC 8659 取代)
- CA/B Forum Baseline Requirements — CA/B 基线要求
- Let's Encrypt: CAA — Let's Encrypt CAA 文档
- ACM SIGCOMM: A First Look at CAA — CAA 部署实证研究
- Princeton: Cryptographically-Secured Domain Validation — CAA 与密码学域名验证
- KrakenKey: SC-098v2 RFC 8657 Mandatory — SC-098v2 分析
- Hetzner: Encrypted Traffic Interception and CAA — CAA 与流量拦截讨论
相关实践
- 如需了解证书透明度的 Merkle 树审计架构及其与 CAA 的互补关系,请参阅《证书透明度(CT)日志:Merkle 树审计架构与 RFC 6962 协议》
- 如需了解 PKI 体系中证书链验证与信任锚机制,请参阅《PKI 体系中证书链验证与信任锚机制》
- 如需了解国密 TLS 协议中的证书处理流程,请参阅《国密 TLS 1.1 协议详解:GM/T 0024 与 RFC 8998》