家里的 DNS 这件事,从一开始只用路由器自带的 dnsmasq,到后来挂上 AdGuard Home 加一层过滤,再后来装 SmartDNS 区分国内外解析,每多一层就多一堆配置、多个面板、几套规则。它们之间怎么协作、谁先谁后、哪条规则先匹配,只能靠手写顺序和注释撑着。
直到最近看到 OxiDNS 这个项目,它的思路不一样:不是再给你一个 DNS 服务器,而是给你一套「可组合的策略管线」——把匹配、转发、回退、改写、联动防火墙全部拆成插件,用声明式 YAML 把它们按顺序串起来跑。它的作者是国产开发者,从 mosdns 那里受到启发,但把核心做得更可观测、可验证。

它到底是什么
OxiDNS(项目仓库 svenshi/oxidns)是一个用 Rust 写的、面向软路由、OpenWrt、Homelab 和高级自建网络的「DNS 策略编排引擎」。它的核心思路借鉴了 mosdns,但胜在两点:
- 策略可编排:内置的
sequence插件能把 matcher(匹配器)、executor(执行器)和 provider(上游)像管道一样拼起来,条件跳转、回退链这些都能声明地写。 - 决策可解释:每一次查询的匹配路径、执行路径、上游选择都会被记录下来,配上 Prometheus 指标和实时日志。出问题时能复盘出「为什么解析成这个 IP」,这在传统 dnsmasq 体系里几乎做不到。
它的上游/接入协议支持得很完整——UDP、TCP、DoT、DoQ、DoH(含 HTTP/1.1/2/3)都收。还能把解析结果联动到 Linux 的 ipset/nftset、RouterOS 的地址列表上,做「按域名自动出防火墙规则」这种事。
对有状态可观测要求的人(比如我这种隔三差五想看路由为什么飘到某个奇怪节点的人),这点吸引力很大。
它跑起来像什么
一行命令装最新 release,默认注册成系统服务:
curl -fsSL https://oxidns.org/install.sh | sudo sh
Windows 管理员 PowerShell 一行命令同效。装完默认监听 UDP/TCP 53 和一个管理 HTTP 端口 9199(WebUI + REST API)。它可以选择 裸跑、二进制直接跑、Docker 跑,也提供了 Debian 包。对 OpenWrt 用户有专门的 luci-app-oxidns 插件。
YAML 配置是这个项目的灵魂。官方 README 给了个最小例子——把 corp.lan 交给内网 DNS,其余走加密上游:
plugins:
- tag: internal_domains
type: domain_set
args:
exps: ["domain:corp.lan"]
- tag: forward_internal
type: forward
args:
upstreams:
- addr: "udp://192.168.1.1:53"
- tag: forward_public
type: forward
args:
upstreams:
- addr: "tls://dns.quad9.net:853"
bootstrap: "9.9.9.9:53"
- tag: main
type: sequence
args:
- matches: "qname $internal_domains"
exec: "$forward_internal"
- matches: "!has_resp"
exec: "$forward_public"
- exec: accept
- tag: dns_server
type: udp_server
args:
entry: main
listen: ":5335"
这套结构的优点是 逻辑和协议入口解耦——同一个 main 序列可以挂到 UDP、TCP、DoH 三个 listener 后面,一次定义多处复用。
它的硬实力:性能基准
作者在 docs/static/img/benchmarks/staged/ 放了一张对比基准:

看图就清楚——在 6 个常见场景(缓存热路径、本地 UDP、本地 TCP、本地应答、通用域名集、负缓存)下,OxiDNS 和 mosdns 咬得很紧,两者都比 AdGuard Home 和 SmartDNS 高出明显一截。对家庭 NAS 这种轻负载来说这个量级的性能优势用不太上,但对真正在跑高 QPS 的网关来说有意义。
哪些坑要先踩
从我自己捋 README 和文档站的过程中挑了几条值得提前知道的:
- 不是开箱即用的图形化面板。项目自己也承认:「OxiDNS 更适合愿意用一定配置复杂度换取控制力和可解释性的用户」。如果你的首要需求是「点几下鼠标就能拦截广告」,AdGuard Home 那种更合适,OxiDNS 不是来抢这个市场的。
- 53 端口冲突。系统 systemd-resolved、dnsmasq、其它 DNS 服务都会占 53。装它之前要么改成别的(比如文档里示例用的
:5335),要么先把原来的停掉。 - 管理 API 不能直接裸奔到公网。
9199有 Basic Auth,但 静态文件不受 Auth 保护,只靠 Basic Auth 等于半裸。文档强烈建议要么只监听127.0.0.1,要么走 nginx 反代,要么开防火墙。 - WebUI 前端路由刷新要 fallback。反向代理(如 nginx)必须配
try_files $uri $uri/ /index.html;,否则刷新/settings这种深链会 404。 - DNS 配置就是网络配置。任何 DNS 服务的 bug 都会直接断网。变更前必须有可恢复的备份和旁路方案——作者也在 README 显眼位置强调了这一点。
- 迁移成本。如果你已经在跑 mosdns,作者提供了「从 mosdns 迁移」的文档一键搬配置。但从 SmartDNS / AdGuard Home / dnsmasq 搬过来就需要重写一遍,没有现成的迁移工具。
适合谁
我读完文档后觉得它最合适的画像是:
- 家用网关、旁路由、OpenWrt、NAS、HOMELAB 这种需要长期稳定运行的环境;
- 想按域名、客户端 IP、查询类型做精细策略路由的人;
- 有多上游并发、主备回退、加密 DNS 与自定义出口叠加需求的人;
- 想用 DNS 结果直接驱动
ipset/nftset或 RouterOS 地址列表做软路由策略路由的人。
反过来,它不适合「想 30 秒搞定广告过滤」的人,也不适合当权威 DNS(那是 BIND/NSD 的活)。
小结
DNS 这个事大多数人不愿意再折腾——它看不见摸不着,出了问题又很难诊断。OxiDNS 的核心诚意是把决策过程摆到台面上:匹配了什么、执行了什么、为什么选了当前结果,都能查。这点对愿意花时间写 YAML 的人来说很值。
目前 433 个 star、昨天还在 commit 的活跃度对它来说偏少,还不算主流——但 GPL-3.0、文档清晰、性能过得去。如果你在折腾多层的 DNS 分流、想试一种不同于面板/拦截器的新思路,可以拿它当折腾对象玩一玩;要不要上生产,自己评估。