返回更新列表
新发布Aug 20, 2026

numa v0.23.0

基于 Rust 的可移植 DNS 解析器 — .numa 本地域名、广告拦截、开发者覆盖

分享

Numa

CI crates.io License: MIT

属于你的 DNS。无论你走到哪里。 — numa.rs

一个单二进制文件的可移植 DNS 解析器。在任何网络上屏蔽广告,为你的本地服务命名(frontend.numa),用自动回滚覆盖任何主机名,并用 ODoH (RFC 9230) 封装每一个出站查询,这样就没有任何一方能同时看到你是谁以及你查询了什么——这一切都在你的笔记本电脑上完成,无需云账户或树莓派。

用 Rust 从零构建。零 DNS 库。开箱即用的缓存、广告拦截和本地服务域名。可选的从根域名服务器开始的递归解析,带完整的 DNSSEC 信任链验证,外加一个用于加密客户端连接的 DNS-over-TLS 监听器(iOS 私人 DNS、systemd-resolved 等)。运行 numa relay,同一个二进制文件也能变成一个公共 ODoH 端点——精选的 DNSCrypt 列表目前只有一个存活的 relay,所以每一次 Numa 部署都实实在在地扩展了这个生态。一个约 8MB 的二进制文件,一切内嵌。线协议解析器是作为学习项目手写的;后续功能(递归解析器、DNSSEC、仪表盘)是在 AI 辅助下构建的。

Numa 仪表盘

快速开始

三种入门方式,从最轻到最重。只有第三种会更改你的系统 DNS。

1. 在 Docker 中试用(主机上不安装任何东西)

docker run -d --name numa -p 127.0.0.1:5553:53/udp -p 127.0.0.1:5553:53/tcp \
  -p 127.0.0.1:5380:5380 ghcr.io/razvandimescu/numa
dig @127.0.0.1 -p 5553 example.com
docker exec numa numa token            # dashboard password

打开 http://localhost:5380,用任意用户名和该 token 登录。端口 5553 绕开了主机上任何已占用 53 端口的程序。numa.numa 在这里无法解析,因为主机并未使用 Numa 作为 DNS。用 docker rm -f numa 清理。

2. 在前台运行(系统 DNS 不受影响)

安装二进制文件:

# macOS
brew install razvandimescu/tap/numa

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

# Arch Linux
pacman -S numa

# Windows — download from GitHub Releases
# All platforms
cargo install numa

# Nix
nix run github:razvandimescu/numa
sudo numa                              # Ctrl-C to stop (port 53 requires root/admin)

Numa 监听 53 端口,但在你运行 numa install 之前,你的系统会保持当前的解析器,所以用 dig @127.0.0.1 example.com 测试。仪表盘位于 http://localhost:5380。如果 53 端口被占用(Ubuntu/Mint 上的 systemd-resolved),在 numa.toml 中设置 bind_addr,或使用 Docker。

3. 设为系统 DNS

平台安装卸载
macOSsudo numa installsudo numa uninstall
Linuxsudo numa installsudo numa uninstall
Windowsnuma install(管理员)+ 重启numa uninstall(管理员)+ 重启

install 会注册一个服务,将系统 DNS 指向 Numa 并信任其本地 CA。uninstall 会撤销这三项。安装后,仪表盘也位于 **http://numa.numa**。

在 macOS 和 Linux 上,numa 作为系统服务运行(launchd/systemd)。systemd 单元是非特权的(DynamicUser=yes,仅 CAP_NET_BIND_SERVICE);launchd 守护进程以 root 运行。numa install 通过一个 drop-in 重新配置 systemd-resolved,numa uninstall 会将其移除;任何其他占用 53 端口的进程(dnsmasq,包括 NetworkManager 的)都必须手动停止。在 Windows 上,numa 通过注册表在登录时自动启动。Windows 还会绑定 127.0.0.2:53(内置的 Dnscache 占用 127.0.0.1:53)并安装一条 NRPT 规则将查询路由到它——所以请针对 127.0.0.2 而非 127.0.0.1 编辑 bind_addr/api_bind_addr。

登录

通过回环地址(localhost、127.0.0.1、numa.numa)无需登录。其他任何方式,包括 Docker 端口映射或本机的 LAN 地址,都会被要求提供 API token,Numa 在首次启动时生成它。用 sudo numa token(Windows 上为管理员 shell)打印它,然后用任意用户名登录。用 [server] api_token 或 NUMA_API_TOKEN 固定你自己的 token。

移除所有痕迹

uninstall 会恢复 DNS,但保留数据目录,所以重新安装会保留相同的 token 和 CA。要移除一切,先卸载,然后删除:

平台遗留内容
macOS二进制文件、/usr/local/var/numa、/usr/local/var/log/numa.log
Linux二进制文件(来自 install.sh 的 /usr/local/bin/numa)、/var/lib/numa、/etc/numa
Windows二进制文件、%PROGRAMDATA%\numa

包管理器安装的版本用 brew uninstall、pacman -R 或 cargo uninstall 移除二进制文件。在 Linux 上,numa install 会将一个无法从其原始位置(例如 ~/.cargo/bin)运行的二进制文件复制到 /usr/local/bin/numa,卸载会留下该副本。

如果你创建了用户配置,也请删除 ~/.config/numa,以及你设置的 [server] data_dir 路径。

本地服务

为你的开发服务命名,而不是记住端口号:

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

现在 https://frontend.numa 在你的浏览器中就能用了——绿色锁标、有效证书、用于 HMR 的 WebSocket 透传。无需 mkcert,无需 nginx,无需 /etc/hosts。

添加基于路径的路由(app.numa/api → :5001),通过 LAN 发现跨机器共享服务,或在 numa.toml 中配置一切。

广告拦截与隐私

通过 Hagezi Pro 进行广告和跟踪器拦截,每日刷新。在任何网络上都能用——咖啡馆、酒店、机场。随你的笔记本电脑同行。

三种解析模式:

  • forward(默认)——透明代理到你现有的系统 DNS。一切照旧,只是在其上叠加了缓存和广告拦截。强制门户、VPN、企业 DNS——全部得到尊重。
  • recursive——直接从根域名服务器解析。无上游依赖,没有任何单一实体能看到你的完整查询模式。添加 [dnssec] enabled = true 以进行完整的信任链验证。
  • auto——启动时探测根服务器,可达则递归,否则通过 DoH 转发到 Quad9(https://9.9.9.9/dns-query),后者会看到你的查询。使用 forward 搭配你自己的 [upstream] 来选择不同的提供商。

DNSSEC 验证完整的信任链:RRSIG 签名、DNSKEY 验证、DS 委派、NSEC/NSEC3 否认证明。阅读其工作原理 →

DNS-over-TLS 监听器(RFC 7858)——在 853 端口接受来自严格客户端的加密查询,如 iOS 私人 DNS、systemd-resolved 或 stubby。两种模式:

  • 自签名(默认)——numa 自动生成一个本地 CA。numa install 会将其添加到 macOS、Linux(Debian/Ubuntu、Fedora/RHEL/SUSE、Arch)和 Windows 的系统信任存储中,numa uninstall 会将其移除。在 iOS 上,从 numa setup-phone 安装 .mobileconfig。Firefox 保留自己的 NSS 存储并忽略系统存储——如果你需要在 Firefox 中为 .numa 服务使用 HTTPS,请在那里手动信任该 CA。
  • 自带证书——将 [dot] cert_path / key_path 指向一个公开受信任的证书(例如,通过 DNS-01 挑战在一个指向你的 numa 实例的域名上使用 Let's Encrypt)。客户端无需任何信任存储设置即可连接——与 AdGuard Home 或 Cloudflare 1.1.1.1 相同的用户体验。

两种模式下都会通告并强制 ALPN "dot";ALPN 不匹配的握手会被拒绝,作为跨协议混淆防御。

Oblivious DoH(RFC 9230)——使用 [upstream] mode = "odoh"(配方)时,每个查询都用 HPKE 密封到目标并通过一个 relay 发送。relay 看到你的 IP 和密文,目标看到问题和 relay 的 IP,而重定向查询的 relay 交给新目的地的东西它无法解密。Numa 拒绝共享同一可注册域名的 relay 和目标。ODoH 不会隐藏你之后打开的连接:你的 ISP 仍然能看到目标 IP,并且在没有 ECH 的情况下,还能看到 TLS 握手里的主机名。

手机设置——一步将你的 iPhone 或 Android 指向 Numa:

numa setup-phone

打印一个二维码。扫描它,安装配置文件,切换证书信任——你手机的 DNS 现在通过 TLS 路由到 Numa。需要在 numa.toml 中设置 [mobile] enabled = true。

LAN 发现

在多台机器上运行 Numa。它们通过 mDNS 自动找到彼此:

Machine A (192.168.1.5)              Machine B (192.168.1.20)
┌──────────────────────┐             ┌──────────────────────┐
│ Numa                 │    mDNS     │ Numa                 │
│  - api (port 8000)   │◄───────────►│  - grafana (3000)    │
│  - frontend (5173)   │  discovery  │                      │
└──────────────────────┘             └──────────────────────┘

从 Machine B:curl http://api.numa → 代理到 Machine A 的 8000 端口。用 numa lan on 启用。

Hub 模式:运行一个实例,设置 bind_addr = "0.0.0.0:53",并将其他设备的 DNS 指向它——它们无需安装任何东西就能获得广告拦截 + .numa 解析。bind_addr 也接受一个列表来绑定特定的接口子集。分步指南:全网配方。

Docker

# Recommended — host networking (Linux)
docker run -d --name numa --network host -v numa-data:/var/lib/numa ghcr.io/razvandimescu/numa

# Port mapping (macOS/Windows Docker Desktop)
docker run -d --name numa -p 53:53/udp -p 53:53/tcp -p 5380:5380 -v numa-data:/var/lib/numa ghcr.io/razvandimescu/numa

仪表盘位于 http://localhost:5380。使用端口映射或从另一台设备访问时,用任意用户名和来自 docker exec numa numa token 的 token 登录。numa-data 卷在容器重建之间保留 token 和本地 CA。镜像默认将 API 和代理绑定到 0.0.0.0。用自定义配置覆盖:

docker run -d --name numa --network host -v numa-data:/var/lib/numa \
  -v /path/to/numa.toml:/root/.config/numa/numa.toml \
  ghcr.io/razvandimescu/numa

多架构:linux/amd64 和 linux/arm64。

开箱即用的 compose 配方:

对比

分类