Designate/蓝图/MiniDNS
目录
- 1 概述
- 1.1 概要
- 1.2 实施步骤
- 1.2.1 更新存储层以返回对象,而不是简单的字典
- 1.2.2 更新网络 API 返回值以匹配存储层的更改
- 1.2.3 更新 Record 对象,使其能够提供记录的结构化和文本表示形式的 RData
- 1.2.4 构建核心 `designate-mdns` 服务
- 1.2.5 DIY 路由
- 1.2.6 DNSPython 路由
- 1.2.7 扩展步骤 4 中的 `designate-mdns` 服务,以解码传入的查询,从存储中收集结果,并构建 + 返回答案
- 1.2.8 扩展步骤 7 中的 `designate-mdns` 服务以支持 AXFR
- 1.2.9 扩展 Designate 的 TSIG 密钥支持,以允许作用域 TSIG 密钥
- 1.2.10 扩展 `designate-mdns` 服务,使其具有 TSIG 密钥支持
- 1.2.11 扩展步骤 10 中的 `designate-mdns` 服务,使其具有 NOTIFY 支持
- 1.2.12 更新后端以仅处理区域创建/更新/删除
概述
| Gerrit补丁 | [] |
|---|---|
| Launchpad蓝图 | [1] |
总结
此蓝图的目的是描述在 Designate 中直接实现“Mini DNS”服务器的理由、优势和劣势。不会讨论低级实施细节。
理由
Designate 当前的“后端”实现存在缺陷,为 Designate 和后端之间不同步留下了许多机会,并且在实施某些类型的后端时(例如:将 BIND9 区域文件写入 N DNS 服务器)过于复杂。这些失败的原因可以分解为两个核心思想
- Designate 不以事务方式执行后端操作。过去曾尝试过跨存储和后端实施两阶段提交协议,但这种解决方案的复杂性对于非数据库后端(BIND9、NSD 等)来说引入了大量的复杂性,并且为了真正可靠,需要修复下面第 2 点。
- 非数据库后端(例如 BIND9)要求将每个更改应用于每个 DNS 服务器,并且更改必须以所有服务器上的相同顺序应用。Designate 当前缺乏可靠的方法来执行这两项任务。此外,任何实施都需要在上述两阶段提交协议下正确运行。
大多数解决方案对于这两个问题来说都过于复杂。虽然 Mini-DNS 提案确实很复杂,但它提供了其他解决方案无法提供的几个额外优势。Mini-DNS 可以允许的附加功能使复杂性可以接受。
高级实施方案
Designate 将实现一个 Mini-DNS 服务器,能够处理来自预定义“受支持的 DNS 客户端”的非常有限数量的 DNS 操作。此服务不会处理最终用户的查询。最初,此服务将执行两个核心任务
- 为公共 DNS 服务器提供 AXFR 源。这涉及接受来自已知受支持 DNS 服务器子集的 SOA 和 AXFR 查询(BIND9、PowerDNS、NSD 等)。
- 在区域更改时发布 DNS NOTIFY,从而触发公共 DNS 服务器的 AXFR。
此服务将分为两部分实现
- DNS 协议实现(存在概念验证 DIY 代码,也存在诸如 dnspython 之类的现成库)
- 一个新的 designate-minidns 服务。此服务将充当通常称为“隐藏”或“隐形”名称服务器。监听 AXFR 查询并发送 NOTIFY。
优点
直接优势
- 可以通过简单地对存储执行事务更新来执行事务区域更改,无需两阶段提交协议。
- 确保所有公共 DNS 服务器接收所有区域更改简化为发送 N 个 DNS NOTIFY
- 确保在所有公共 DNS 服务器上以适当的顺序应用区域更改不再是一个问题,AXFR 可以解决此问题,而无需我们进行任何额外工作。
- 区域更改异步地应用于公共 DNS 服务器,并且 DNS 内置的区域刷新间隔可确保在错过更新的情况下(例如,名称服务器在更改期间关闭)最终一致性。
- 后端实现减少到将区域添加和删除所需的最小功能量
- 对于 BIND9,我们可以使用 TCP 上的 RNDC 实现此功能
- 对于 PowerDNS,我们可以使用我们当前执行的相同的 DB 交互来实现此功能。
- TODO:了解 NSD / FreeIPA DNS / Akamai EDNS 等等如何关联
未来优势
有了这段代码,我们为其他未来功能奠定了坚实的基础;
- 支持 RFC2136(nsupdate 样式)动态 DNS 更新
- 支持来自客户的传入 AXFR
- 能够按需对区域进行 DNSSEC 签名
- 考虑拥有 DNS 区域的多个视图的可能性(最常见的示例是拆分视界)。如果没有按需签名,必须预先签名区域的所有可能的视图。
- 简化了 服务器池 提案的实施
劣势
- 我们必须维护自己的 Mini-DNS 服务器。
- 核心 DNS RFC 简单,但已被扩展如此之多,以至于完全符合所有 DNS RFC 很难。对于我们需要的特性集所需的 RFC 范围有限,这使得这个问题不太紧迫。
- 某些 DNS 客户端存在错误,发送损坏或损坏的数据,或者表现不端。随着 Mini-DNS 的用例从 AXFR -> 公开可访问的服务(动态 DNS、传入 AXFR 等)的增长,优雅地处理这些错误的必要性将增加实施的复杂性。
实施步骤
更新存储层以返回对象,而不是简单的字典
storage-objects
这具有超越 MiniDNS 的优势,例如,验证规则可以隔离到每个对象的隔离类中。
此步骤将创建以下对象,使存储返回它们,并更新其余代码以处理这些更改
- Quota
- 服务器
- TLD
- TsigKey
- Tenant[1]
- Domain
- RecordSet
- Record
- Blacklist
[1]: Tenant 非常不寻常,仅用于 V1 管理 API 扩展。
更新网络 API 返回值以匹配存储层的更改
networkapi-objects
此步骤将创建以下对象,使 NetworkAPI 返回它们,并更新其余代码以处理这些更改
- FloatingIP
此步骤仅是为了保持各种 API 的一致性。
更新 Record 对象,使其能够提供记录的结构化和文本表示形式的 RData
structured-rdata
这允许 RData 由所选的 DNS 协议实现序列化。当前 designate/objects 具有 record 的对象。此对象 (designate.objects.Record) 将提供 from_text、to_text 方法。designate.objects.base 将提供 from_dict、to_dict 方法。支持的各种记录类型(“A”、“AAAA”、“CNAME”、“MX”、“SRV”、“TXT”、“SPF”、“NS”、“PTR”、“SSHFP”)将各自具有从 designate.objects.Record 继承的单独类型。存储的 get_record、find_record 和 find_records 能够返回特定的记录类型,而不是通用的 designate.objects.Record。
对于存储的 create_record、update_record,以接受这些记录类型之一(而不是当前的情况下的字典)并能够创建/更新它,我们需要修改中央和/或 api 层以提供这些记录类型之一,而不是字典。这是否应该作为另一个蓝图来完成?
构建核心 `designate-mdns` 服务
core-mdns-service
此步骤涉及构建服务类/守护程序,该守护程序侦听 tcp/udp 53,并将传入请求分派到存根请求处理程序。
这尚未涉及解析/响应 DNS 查询。
DIY 路由
构建基础 DNS 协议实现
dns-implementation
在这里,我们编写基础协议实现 - 能够编码和解码基础 DNS 结构
- Packet - DNS 数据包本身,包含 Header、Questions、Answers、Authorities 和 Additionals
- Header - DNS 数据包 Header
- Name - DNS 名称的表示形式,具有处理 DNS 名称压缩/指针的逻辑
- Question - DNS 查询的表示形式,包含查询的名称、类型和类。
- ResourceRecord - 表示结果中的单个记录[1]。
[1]: 这一项可以跳过,Record 对象而是实现这部分。
扩展步骤 1 和 3 中的 Record+Rdata 对象,以包含 DNS 协议编码和解码方法
record-rdata-dns-implementation
这些应该是简短的、rtype 特定的编码器和解码器,它们利用在步骤 3 中创建的结构化 RData 对象。
DNSPython 路由
扩展 Record+Rdata 对象
扩展步骤 1 和 3 中的 Record+Rdata 对象,以包含将转换为/从 DNSPython 的表示形式的翻译方法
扩展步骤 4 中的 `designate-mdns` 服务,以解码传入的查询,从存储中收集结果,并构建 + 返回答案
designate-mdns-functional
目前,这将仅限于标准的、非 AXFR/TSIG 查询。
扩展步骤 7 中的 `designate-mdns` 服务以支持 AXFR
designate-mdns-axfr
目前,这将仅限于非 TSIG AXFR 查询。
扩展 Designate 的 TSIG 密钥支持,以允许作用域 TSIG 密钥
For example, it should be possible to create a TSIG key with:
- Scope = Global。这将是无限的,可以 AXFR 所有区域。
- Scope = Zone, Resource = <Zone ID>。这将限制为单个区域。
- Scope = Pool, Resource = <Pool ID>。这将限制为池中的区域。
扩展 `designate-mdns` 服务,使其具有 TSIG 密钥支持
designate-mdns-tsig
扩展步骤 8 中的 `designate-mdns` 服务,以通过步骤 9 中的 TSIG 密钥扩展支持身份验证和授权
扩展步骤 10 中的 `designate-mdns` 服务,使其具有 NOTIFY 支持
designate-mdns-notify
当 Central 检测到区域更改时,将通知 designate-mdns。该服务将向所有辅助名称服务器发出 NOTIFY。
在 Pools 之前,这将是一个预配置的辅助服务器列表,以进行 NOTIFY,在 Pools 之后,将动态加载 NOTIFY 的辅助服务器列表。
更新后端以仅处理区域创建/更新/删除
后端不再需要为 RecordSet 或 Record 更改调用,因此现在可以安全地删除此代码