Numa:用 Rust 从零造一个 DNS 解析器,顺手解决了开发者最头疼的几件事

Numa:用 Rust 从零造一个 DNS 解析器,顺手解决了开发者最头疼的几件事


相信大家都遇到过这几个问题

开发时本地起了五六个服务,localhost:3000localhost:5173localhost:8080......端口记不住,换台机器更是一片混乱。

出差去咖啡馆用 Wi-Fi,浏览器广告铺天盖地,想开 Pi-hole 但家里的树莓派根本带不走。

调试线上问题时想临时把某个域名指向本地,改 /etc/hosts 还要手动还原,一不小心忘了就出问题。

这三件事,Numa 一个工具全解决了。


Numa 是什么

Numa 是一个用 Rust 从零写成的便携式 DNS 解析器,打包成单个二进制文件(约 8MB),在 macOS、Linux、Windows 上均可运行。不需要树莓派,不需要云账号,不需要注册任何服务。

名字来自古罗马第二任国王 Numa Pompilius------他建立的律法与制度,比王权本身活得更久。


三个核心能力

1. 本地服务域名:告别 localhost:端口号

安装 Numa 后,只需一条 API 调用:

bash 复制代码
curl -X POST localhost:5380/services \
  -d '{"name":"frontend","target_port":5173}'

之后 https://frontend.numa 就能在浏览器里直接打开,有绿色小锁,支持 WebSocket(Vite HMR 不受影响),路径路由也支持:

bash 复制代码
app.numa/api  →  localhost:5001
app.numa/web  →  localhost:3000

不需要配 mkcert,不需要装 nginx,不需要碰 /etc/hosts

2. 广告拦截:跟着笔记本走的 Pi-hole

内置 Hagezi Pro 拦截列表,超过 38.5 万个广告和追踪域名。默认开启,零配置。

Pi-hole 和 AdGuard Home 需要部署在树莓派或家庭服务器上,出门就失效。Numa 装在笔记本里,咖啡馆、酒店、机场,到哪都拦截。

3. 开发者 DNS 覆盖:临时改域名,自动还原

调试时想让 api.example.com 临时指向本地:

bash 复制代码
curl -X POST localhost:5380/overrides \
  -d '{"name":"api.example.com","ip":"127.0.0.1","ttl_minutes":30}'

30 分钟后自动还原。不需要手动改 /etc/hosts,不会忘记还原。


真正的技术亮点:从零实现 DNS 协议

这个项目最值得关注的地方,不是功能列表,而是实现方式

作者 Razvan Dimescu 没有用任何现成的 DNS 库(没有 hickory-dns,没有 trust-dns,没有 simple-dns)。整个 RFC 1035 DNS 线路协议------报文头、标签压缩、记录类型------全部手写解析。

作者在博客里解释了动机:

"我想真正理解 DNS 是怎么工作的。不是'它把域名翻译成 IP'这种解释------而是线路上的实际字节。DNS 数据包长什么样?标签压缩怎么工作?为什么所有东西都塞进 512 字节?"

一个 DNS 查询包只有 29 个字节:

makefile 复制代码
Header: AB CD  01 00  00 01  00 00  00 00  00 00
        ID     Flags  1个问题  0个答案  0个权威  0个附加

Question: 07 65 78 61 6D 70 6C 65  03 63 6F 6D  00  00 01  00 01
              e  x  a  m  p  l  e      c  o  m  结束  A类型  IN类

这个项目从这 29 个字节开始,一路实现到 DNSSEC 完整信任链验证------RSA、ECDSA P-256、Ed25519 三种签名算法,NSEC/NSEC3 否定证明全部支持。


三种解析模式

markdown 复制代码
forward(默认)→ 透明代理到系统 DNS,加上缓存和广告拦截
                  兼容企业 VPN、Tailscale、强制门户

recursive       → 从根域名服务器迭代查询,不依赖任何上游
                  可选开启 DNSSEC 完整信任链验证

auto            → 启动时探测根服务器,能连就用 recursive,
                  被封就自动回退到加密的 DNS-over-HTTPS

LAN 发现:多机器自动互联

在多台机器上运行 Numa,它们通过 mDNS 自动发现彼此:

scss 复制代码
机器 A(192.168.1.5)                  机器 B(192.168.1.20)
┌──────────────────────┐               ┌──────────────────────┐
│ Numa                 │     mDNS      │ Numa                 │
│  - api (port 8000)   │◄─────────────►│  - grafana (3000)    │
│  - frontend (5173)   │   自动发现    │                      │
└──────────────────────┘               └──────────────────────┘

在机器 B 上执行 curl http://api.numa,请求会自动代理到机器 A 的 8000 端口。一行命令开启:numa lan on

还可以用 Hub 模式:一台机器运行 Numa 并监听 0.0.0.0:53,其他设备把 DNS 指向它,就能共享广告拦截和 .numa 域名解析,不需要在每台设备上单独安装。


性能数据

这些数字都是可复现的(cargo bench 跑微基准,python3 bench/dns-bench.sh 跑端到端):

指标 数值
缓存命中延迟 691 ns
单线程吞吐量 ~200 万 QPS
热路径堆分配 0
ECDSA P-256 DNSSEC 验证 174 ns

与主流解析器对比(dig 测量,相同机器):

解析器 平均延迟 P99
Numa(缓存命中) <1ms <1ms
Numa(冷查询) 9ms 18ms
系统解析器 9ms 44ms
Quad9 15ms 43ms
Cloudflare 19ms 132ms
Google 22ms 37ms

冷查询和系统解析器速度相当------瓶颈是上游 RTT,不是 Numa 本身。


与同类工具的对比

Pi-hole AdGuard Home Unbound Numa
本地服务代理 + 自动 TLS --- --- --- .numa 域名
LAN 服务发现 --- --- --- ✅ mDNS 零配置
开发者覆盖 + 自动还原 --- --- --- ✅ REST API
递归解析 --- ---
DNSSEC 验证 --- --- ✅ 完整信任链
广告拦截 --- ✅ 38.5万域名
便携性(跟着笔记本走) ❌ 树莓派 ❌ 网络设备 ❌ 服务器 ✅ 单二进制

安装和使用

bash 复制代码
# macOS
brew install razvandimescu/tap/numa

# Linux
curl -fsSL https://raw.githubusercontent.com/razvandimescu/numa/main/install.sh | sh

# 任意平台(需要 Rust 工具链)
cargo install numa
bash 复制代码
# 前台运行(53 端口需要 root)
sudo numa

# 设置为系统 DNS(macOS / Linux)
sudo numa install

# 打开 Dashboard
open http://localhost:5380
# 或者安装后直接访问 http://numa.numa

解析管道:每一步都清晰可追踪

Numa 最好的设计决策之一,是把解析过程做成显式的流水线,每一步要么回答,要么传给下一步:

复制代码
查询
 → 覆盖规则(有命中?返回,自动计时还原)
 → .numa TLD(是本地服务?反向代理 + 自动 TLS)
 → 拦截列表(命中广告域名?返回 0.0.0.0)
 → 本地 Zone(静态记录?返回)
 → 缓存(有缓存?返回 TTL 调整后的结果)
 → 上游解析(递归 / DoH)
 → DNSSEC 验证
 → 返回客户端

这个结构让扩展变得直接------想加 Tailscale 条件转发?在上游那步之前插入一条规则。想临时覆盖某个域名?加到第一步,带过期时间。


总结点评

这个项目的有意思之处不完全在于功能------广告拦截、本地域名、DNS 覆盖,这几件事单独拿出来都有现成工具可以做到。

Numa 的价值在于把这三件事整合进一个不需要基础设施的工具里,并且整个实现是从 RFC 1035 字节开始手写的。作者在博客里记录了 DNS 线路协议、标签压缩、TTL 懒惰驱逐、DoH 实现的全过程,读下来比很多 DNS 教程都扎实。

目前刚发布不久,代码质量和文档完成度已经相当高。如果你经常在本地跑多个服务、或者在意笔记本出行时的隐私保护,值得试一下。


项目地址github.com/razvandimes...
官网numa.rs

单个二进制,零依赖,DNS 真正属于你自己。

相关推荐
江畔柳前堤7 小时前
roLabelImg 详细安装教程
开发语言·人工智能·后端·云原生
阿里云大数据AI技术7 小时前
分链路差异化设计的DSP准实时数仓|钛动科技基于阿里云实时计算 Flink 版 + DLF Paimon + EMR Serverless StarRocks 的实践
人工智能·flink
陕西企来客7 小时前
2026年7月AI智能搜索曝光趋势研判
大数据·人工智能·机器学习·ai智能搜索曝光
阿里云大数据AI技术8 小时前
从算力到智能体,面向 Agentic AI 的基础设施演进
人工智能·agent
hangyuekejiGEO8 小时前
GEO技术服务选型指南
大数据·人工智能·python
阿里云大数据AI技术9 小时前
EMR Serverless Spark AI Function 的双维降本实践
人工智能·sql·spark
维基框架9 小时前
GitHub源码处理提速 一趟扫描反而更慢
人工智能·github
冬奇Lab9 小时前
代码库知识库系列(05):向量检索 vs 知识图谱——加了调用图并没有变更好
人工智能
AKAMAI9 小时前
你的源服务器可能是你做出的最昂贵决定
运维·人工智能·云计算
冬奇Lab9 小时前
【无标题】
人工智能·开源