DNS — sing-box
sing-box 的 DNS 引擎是「带类型的服务器列表 + 结构化规则链」。每个服务器都有 type 选择其传输方式(UDP、TCP、TLS、QUIC、HTTPS、HTTP/3、hosts 文件、fake-ip 池、DHCP、mDNS、systemd-resolved、Tailscale 内嵌,或由 OpenVPN / OpenConnect 端点推送的解析器)。规则使用与路由规则相同的匹配字段集合,但带有 DNS 专用 action —— 还可以匹配应答。
顶层选项
| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
servers | []DNSServerOptions | [] | [DNSServerOptions] | DNS 服务器列表。每条目带 type(local、hosts、tcp、udp、tls、quic、https、h3、dhcp、mdns、fakeip、tailscale、openconnect、openvpn、resolved)与对应的选项集合。不带 type 的条目(无类型的 address 格式)会被拒绝。 |
rules | []DNSRule | [] | [DNSRule] | DNS 级别的路由规则。形态与路由规则相同,但携带 DNS 专用的 action 集合。 |
final | string | (unset) | <server tag> | 无规则命中时使用的默认 DNS 服务器。为空时回退到 servers[] 中的第一个。 |
reverse_mapping | bool | false | true | false | 维护反向映射(IP → 域名),使规则在连接的目标已解析为 IP 后仍能按原始域名匹配。 |
源码: option/dns.go:18-24 · 锚定版本 v1.14.2 (af6e64c)
以及内嵌的 DNSClientOptions:
| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
strategy | DomainStrategy | (prefer_ipv4) | prefer_ipv4 | prefer_ipv6 | ipv4_only | ipv6_only | 默认地址家族偏好。 |
timeout | badoption.Duration | 10s | <duration> | 每个 DNS 查询的默认超时。可按规则(DNS 规则 action 的 timeout)或在 domain_resolver 中覆盖。 |
disable_cache | bool | false | true | false | 禁用内存应答缓存。 |
disable_expire | bool | false | true | false | 不按 TTL 淘汰缓存条目 —— 永久保留。 |
independent_cache | bool | false | true | false | 已弃用:缓存总是按服务器区分,此选项不起作用。 |
cache_capacity | uint32 | 1024 | <int> | LRU 缓存容量(条目数)。小于 1024 的值会被提升为 1024。 |
optimistic | *OptimisticDNSOptions | false | true | false | {enabled, timeout} | 乐观缓存:已过期但仍在 timeout(默认 3d)窗口内的条目会被立即返回,同时在后台刷新。与 disable_cache、disable_expire 冲突。 |
client_subnet | *badoption.Prefixable | (unset) | <CIDR> | 出站查询中携带的 ECS(EDNS Client Subnet)。 |
源码: option/dns.go:62-71 · 锚定版本 v1.14.2 (af6e64c)
服务器类型
servers[] 中每条都有 type 字段。对应字段集合:
type: "local"
通过操作系统解析器解析(在 macOS / iOS 等系统解析器为权威路径的平台上很实用)。提供 prefer_go 切到无 CGO 的 Go 解析器。neighbor_domain 用邻居解析器回答单标签的局域网名称。在非 Apple 平台上,local 服务器还会通过 mDNS 解析 *.local. 与链路本地反向区域(Apple 平台上交给系统解析器)。
| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
prefer_go | bool | false | true | false | 使用 Go 的 net.Resolver(无 CGO)代替平台原生解析器。原生解析器损坏或被限速时有用。 |
neighbor_domain | badoption.Listable[string] | [] | [<.suffix>] | 域名后缀列表(每项以 . 开头),其单标签 A/AAAA 查询由邻居解析器(DHCP 租约中的局域网主机名)作答,而不是发往上游。. 匹配任意单标签名称,例如 [".", ".lan"]。 |
源码: option/dns.go:188-192 · 锚定版本 v1.14.2 (af6e64c)
type: "udp" 与 type: "tcp" —— RemoteDNSServerOptions
{ "type": "udp", "tag": "local-udp", "server": "8.8.8.8", "server_port": 53 }| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
server | string | (required) | <host> | 服务器主机名或 IP。 |
server_port | uint16 | 53 (udp/tcp), 853 (tls), 443 (https/h3) | <port> | 服务器端口。 |
源码: option/dns.go:158-161 · 锚定版本 v1.14.2 (af6e64c)
type: "tls" —— DNS-over-TLS
字段同 udp / tcp 加上标准的 tls: 块。type: "quic"(DNS-over-QUIC)的字段完全相同。
type: "https" 与 type: "h3" —— DNS-over-HTTPS / -H3
| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
path | string | /dns-query | /<path> | DoH 端点路径。 |
method | string | POST | POST | GET | DoH 查询使用的 HTTP 方法。 |
headers | badoption.HTTPHeader | {} | {<header>: <value>} | 附加 HTTP 头。 |
源码: option/dns.go:204-209 · 锚定版本 v1.14.2 (af6e64c)
type: "hosts" —— 本地 hosts 文件
| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
path | badoption.Listable[string] | [/etc/hosts] | [<file path>] | 要合并的 hosts 文件路径列表。 |
predefined | *badjson.TypedMap[string, badoption.Listable[netip.Addr]] | {} | {<domain>: [<IP>]} | 内联 hosts 表。优先级高于 path。 |
源码: option/dns.go:179-182 · 锚定版本 v1.14.2 (af6e64c)
type: "fakeip"
| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
inet4_range | *badoption.Prefix | (required for v4) | <CIDR> | 为 IPv4 伪 IP 分配的 CIDR。 |
inet6_range | *badoption.Prefix | (required for v6) | <CIDR> | 为 IPv6 伪 IP 分配的 CIDR。 |
源码: option/dns.go:211-214 · 锚定版本 v1.14.2 (af6e64c)
type: "dhcp"
| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
interface | string | (auto) | <interface> | 使用其 DHCP 解析器的接口。 |
源码: option/dns.go:216-219 · 锚定版本 v1.14.2 (af6e64c)
其他类型
type: "resolved"—— 读取 systemd-resolved 的每链路 nameserver(仅 Linux)。type: "tailscale"—— 使用 Tailscale 守护进程的 MagicDNS。type: "mdns"—— 在本地网络上以组播方式查询(mDNS),可选interface列表。已有local服务器时通常无需单独配置(它已通过 mDNS 处理*.local.);需要在preferred_by中引用时再添加。type: "openvpn"/type: "openconnect"—— 使用 OpenVPN 客户端 / OpenConnect 端点(endpoint: "<tag>")推送的解析器,可配accept_default_resolvers与accept_search_domain。推送的设置不会写入操作系统。
不存在 predefined 或 rcode 服务器类型:固定应答由 predefined DNS 规则 action 提供(见下文)。
DNS 规则
DNS 规则使用与路由规则相同的多态 _Rule 形态(type: "default" 或 type: "logical"),匹配键为 RawDefaultDNSRule 中的 54 个 —— 其中包括 query_client_subnet、query_dnssec、package_name_regex、source_mac_address、source_hostname、preferred_by(匹配所列服务器视为自身负责的名称:hosts 条目、mDNS 名称、Tailscale / VPN 推送的分流 DNS 与搜索域)以及下文的应答匹配字段。差异在 action:
| DNS action | 含义 |
|---|---|
route(默认) | 把查询送往 server: "<tag>"。可选:disable_cache、disable_optimistic_cache、rewrite_ttl、timeout、client_subnet / remove_client_subnet、speculative;strategy 已弃用。 |
route-options | 对后续规则匹配应用 DNS route 选项(可选字段相同)。 |
evaluate | 向 server 查询并保留应答(可用 tag 命名),供后续规则通过 match_response 匹配;不会结束规则求值。仅限顶层规则。 |
respond | 返回之前 evaluate 保留的应答,不发起新查询。 |
reject | 拒绝查询。method: "default" 回复 REFUSED;method: "drop" 不回应。 |
predefined | 返回硬编码应答(rcode、answer、ns、extra)。 |
race: true(用于带 match_response 的 route / respond / reject / predefined 规则)让依赖应答的规则并行判定 —— 最先命中者生效,其余查询被取消。
应答匹配
规则可以匹配应答,而不只是查询。evaluate 规则获取一个应答;之后带 match_response: true(或该 evaluate 规则的 tag)的规则用 ip_cidr / ip_is_private / ip_accept_any、IP 规则集,或应答字段 response_rcode、response_answer、response_ns、response_extra 去匹配它。不带 match_response 使用 ip_cidr / ip_is_private(旧式地址过滤)、strategy action 选项以及 rule_set_ip_cidr_accept_empty 均已弃用,计划移除。基于 GeoIP 分流的迁移写法:
{
"dns": {
"rules": [
{ "action": "evaluate", "server": "remote" },
{ "match_response": true, "rule_set": "geoip-cn",
"action": "route", "server": "local" },
{ "action": "route", "server": "remote" }
]
}
}示例
二服务器分流 —— 国内走本地 DoH,其余走 Cloudflare DoH:
{
"dns": {
"servers": [
{ "type": "https", "tag": "local",
"server": "doh.pub", "path": "/dns-query" },
{ "type": "https", "tag": "remote",
"server": "cloudflare-dns.com", "path": "/dns-query",
"detour": "proxy" },
{ "type": "fakeip", "tag": "fakeip",
"inet4_range": "198.18.0.0/15",
"inet6_range": "fc00::/18" }
],
"rules": [
{ "rule_set": ["geosite-cn"], "server": "local" }
],
"final": "remote",
"strategy": "prefer_ipv4"
}
}通过 DNS 拦截广告:
{
"dns": {
"servers": [
{ "type": "https", "tag": "main",
"server": "cloudflare-dns.com" }
],
"rules": [
{
"domain_keyword": ["ads", "doubleclick", "googlesyndication"],
"action": "reject",
"method": "default"
}
],
"final": "main"
}
}说明
- 不支持顶层
fakeip: {...}块与不带type的服务器条目(无类型的address: "tls://…"格式)—— 两者都会导致启动失败。请使用带类型的条目(type: "fakeip"、type: "tls"等)。 reverse_mapping: true让后续路由规则在嗅探已把目的解析为 IP 之后仍能按域名匹配。在 fake-ip 与复杂域名规则共存时必备。independent_cache不起作用:缓存总是按服务器 tag(及 client subnet)区分,因此 split-horizon 服务器不会共享应答。该字段已弃用,请移除。ip_version与query_type也作用于不指定服务器的内部查询(例如未设server的路由resolveaction)。在同一 DNS 配置中把它们与已弃用的旧式地址过滤字段混用会在启动时被拒绝。- 已弃用的
outboundDNS 规则项仍可解析,但应改用route.default_domain_resolver或出站上的domain_resolver。 - DNS 规则与路由规则共享 相同 的匹配键词表,但发生在不同阶段:DNS 规则在解析查询上运行;路由规则在生成的连接上运行。
type: "resolved"通过 D-Bus 读取 systemd-resolved,仅在该解析器确实在运行的 Linux 系统上有效。
跨内核说明
- Xray-core 使用扁平的
dns:块,servers[]元素是 URL 字符串(或 NameServerConfig 对象)—— 没有type字段,URL scheme 决定传输方式。参见 DNS — Xray-core。 - mihomo 提供 25 字段的
dns:块,独立的nameserver/fallback列表与nameserver-policy映射。参见 DNS — mihomo。
源码: option/dns.go:18-224 · v1.14.2 (af6e64c)
