跳转到内容

CoDoNS — 用 P2P 哈希表替代分层 DNS 的实验

是什么

CoDoNS(Cooperative Domain Name System)是 Cornell 在 2004 年做的一个实验:把传统 DNS 那套”根服务器 → 顶级域 → 授权服务器”的层级结构整个拆掉,换成一张平面的、节点之间互相帮忙存数据的结构化 P2P 网络(DHT)。

日常类比:原来的 DNS 像一条政府邮政系统——你寄 example.com,先去市级邮局,市级转省级,省级转国家级,每一级都在掌管自己那块。出问题就是那一级的服务停了,整片地区拿不到信。

CoDoNS 像朋友圈互助寄存——所有节点平等,每个节点存一部分名字记录。你查 example.com,按一套数学规则(哈希)找到”这个名字应该在谁那”,几跳之内就能拿到。某个朋友失联,记录在别处也有副本。

它没真的取代 DNS(直到 2026 年都没),但论文里给出了一组实测数字:在真实 trace 上中位数解析延迟从 BIND 的 39ms 压到了 7ms,失败率从百分之几压到 0。

为什么重要

DNS 是 1983 年设计的,几乎是互联网最老的还在跑的系统。它有几个没法回避的痛点

  • DDoS 集中点:根服务器一共 13 个逻辑实例,2002 年和 2007 年都被打到过半数下线
  • 配置错误传染:一条 zone 文件写错,整个域下所有名字一起挂
  • 缓存失效慢:TTL 默认几十分钟到几小时,新地址生效要等
  • 长尾延迟:冷门记录第一次查要走完整层级,可能 1 秒以上

CoDoNS 就是回答:“如果我们今天重新设计一个全球名字服务,能不能用 P2P 的去中心化思想做更好?”

理解这篇论文你能看见三件事:DHT 用在真实工业场景的样子Zipf 分布如何被设计利用、以及为什么技术上更好的方案没能替代既有系统——最后这点,是工程师最该补上的一课。

核心要点

CoDoNS 把名字服务拆成三层

  1. 底层路由:Pastry DHT 每个节点拿一个 128 位 ID,每条 DNS 记录的 key 是 SHA-1(name)。Pastry 保证从任意节点出发,O(log N) 跳就能找到 key 最近的负责节点。N 一万节点也才 13 跳,每跳一两毫秒。

  2. 上层加速:Beehive 主动复制 Beehive 是同组人 NSDI 2004 的另一篇,专门解决”DHT 跳数虽小但每跳还是要时间”。 它的关键洞察:DNS 查询遵循 Zipf 分布——头部 1% 的名字吃掉 50%+ 的流量。Beehive 给热门记录主动复制到更多节点,让查询平均 0 跳就命中本地。冷门记录留在原 DHT 里走 O(log N)。 结果是平均跳数压到 1 以下。

  3. 兼容层:Legacy gateway 现有应用都说传统 DNS 协议。CoDoNS 在边缘部署一个协议网关:客户端发普通 DNS 查询,网关把它翻译成 DHT lookup,再把结果包回 DNS 响应。应用一行不改

记录的鉴权用每条 RR 自带 RSA 签名(类似 DNSSEC 的思路),不依赖路径上节点诚实。

实践案例

案例 1:一次查询的旅程

你的浏览器要查 www.example.com

  1. OS 把请求发给本地 CoDoNS 网关(部署在 ISP 或机器上)
  2. 网关算 key = SHA-1("www.example.com")
  3. Beehive 先看本地有没有副本——如果是热门站点,直接命中返回
  4. 没命中就走 Pastry:经几跳到达 key 最近的节点,拿到带签名的 RR
  5. 网关验签,转回标准 DNS 响应给浏览器

热门站点全程 < 1ms,冷门站点几毫秒。对比 BIND 一次冷查询要遍历 root → com → example.com 三级,每级一跳网络往返。

案例 2:trace 重放的实测数字

论文用 MIT 和 CoDeeN 的真实 DNS trace(几百万条查询)重放:

指标BIND(传统 DNS)CoDoNS
中位延迟39 ms7 ms
90 分位~250 ms39 ms
99 分位1.1 s100 ms
失败率几百分之一0

怎么看这张表:CoDoNS 不是在好的情况下小幅领先,而是整条延迟曲线整体左移。长尾压得最狠——传统 DNS 的 1 秒长尾基本来自冷启动 + 多级路径,DHT 把它消掉了。

案例 3:抗 DDoS 的论证

DNS 根服务器被打过。CoDoNS 的论证是:根本没有”根”。要打瘫整个系统得同时打瘫成千上万个节点。每个节点掉了,它负责的 key 段会自动让邻居接管(Pastry 的自我修复机制)。

代价是:没有一个明确的”我说了算”的权威点。这正是后面要谈的弱点。

踩过的坑

  1. 更新慢:DHT 上改一条记录要等 Beehive 把所有副本同步过来,论文测出来分钟级。传统 DNS 改 zone 文件 + 等 TTL 也是分钟级,但确定性更强。CoDoNS 你不知道哪些副本已经收敛。

  2. 签名开销:每条 RR 都带签名,记录大小膨胀几倍。一次查询带回的数据量比传统 DNS 大不少,对带宽敏感场景是负担。

  3. 没法回答”谁拥有这个名字”:传统 DNS 有清晰的委托树——.com 由 Verisign 管,example.com 由谁注册的就归谁。CoDoNS 是平面的,鉴权只能靠签名,没有天然的”组织主权”层级。这让法律层面(域名仲裁、商标争议)很难落地。

  4. Beehive 假设 Zipf 长期稳定:突发热点(某新闻事件)的 Zipf 分布会暂时偏移,主动复制还没赶上时,原节点就被压垮了。

适用 vs 不适用场景

适用

  • 研究/受控环境的 DNS 替代实验——能拿到漂亮数据
  • 抗审查/抗封锁场景——没有中心节点可被法令封
  • 内部系统的服务发现,规模可控、信任已建立

不适用

  • 替代生产 DNS——既得利益结构 + DNSSEC 已经部署 + 应用兼容性
  • 强一致性更新场景——金融、CDN 切流要秒级生效,DHT 复制收敛太慢
  • 责任明确的多租户——DHT 没有天然”这块归谁”的边界

关键概念展开(自学的人可读)

Pastry 是怎么”O(log N) 跳”的

每个节点和每条记录都有 128 位 ID。Pastry 让节点维护一张前缀路由表

  • 第 0 行:4 个邻居,前缀分别是 0/1/2/3 开头
  • 第 1 行:4 个邻居,和我共享 1 位前缀,第 2 位不同
  • 第 k 行:和我共享 k 位前缀,第 k+1 位不同

查 key 时,每跳保证和 key 多匹配一位前缀。128 位最多 128 跳?不——ID 空间用 base-16,每跳进 4 位,所以 N 个节点平均 log₁₆ N 跳。一万节点 ≈ 3 跳。

类比:从北京找西雅图,第一跳到对方所在大洲,第二跳到对方所在国家,第三跳到对方所在城市。每跳大幅缩小搜索空间。

Beehive 怎么”把 O(log N) 压到 O(1)”

Beehive 的关键:主动把热门记录复制到更多节点。复制的层级 i 表示”距离原节点 i 跳之内的节点都有这条副本”。

  • i = 0:只有原节点有
  • i = 1:1 跳内的节点都有副本,相当于查询者本机命中(如果查询者在 1 跳内)
  • i = ∞:所有节点都有

层级越高,存储成本越高,但查询跳数越低。Beehive 给每条记录算一个最优 i,使得整体平均跳数最小化总存储成本受限

数学上这是个有 closed-form 解的优化问题——前提是 Zipf 指数 α 已知,且查询独立同分布。论文测出真实 DNS trace 的 α ≈ 0.91,理论解和实测吻合。

历史背景与影响

  • 2001-2004:DHT 黄金期。Chord(MIT)/ Pastry(MSR-Cambridge)/ Tapestry(Berkeley)/ CAN(Berkeley)四大方案爆发,研究者都在找能用 DHT 做什么
  • 2002:DNS 根服务器被 DDoS,9/13 受影响。学术界对”分层 DNS 是否过时”的讨论达到顶峰
  • 2004:CoDoNS 论文发表,是把 DHT 用在已有大规模工业系统的最具体一次尝试
  • 之后:CoDoNS 没大规模部署。但思路被 BitTorrent DHT、IPFS、ENS(以太坊域名)、Handshake 等继承
  • 教训沉淀:技术更优 ≠ 替换得动。DNS 有 30 年的工具链、运营经验、法律框架——这些才是它真正的护城河

学到什么

  1. 去中心化是设计选项不是教条:CoDoNS 用平面 DHT 换来了延迟和抗 DDoS,但失去了清晰的责任归属。每一个去中心化决策都在交换某个属性,没有”全面更好”

  2. Zipf 分布是 P2P 系统的金矿:Beehive 主动复制能把 O(log N) 压到 O(1),靠的就是”少量热点吃掉大量流量”。Web 缓存、CDN、Memcached 都吃这个红利

  3. 测量胜利不是部署胜利:论文有漂亮数字也阻挡不了 DNS 继续主导。学会问”假设你是对的,凭什么能替换掉既有方案?”

  4. 兼容层是去中心化系统的入场券:CoDoNS 通过 legacy gateway 让应用零改动接入。任何想替换基础设施的方案都得回答”现存几亿份代码怎么办”

延伸阅读

关联