Skip to content

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 集合。
finalstring(unset)<server tag>无规则命中时使用的默认 DNS 服务器。为空时回退到 servers[] 中的第一个。
reverse_mappingboolfalsetrue | false维护反向映射(IP → 域名),使规则在连接的目标已解析为 IP 后仍能按原始域名匹配。

源码: option/dns.go:18-24 · 锚定版本 v1.14.2 (af6e64c)

以及内嵌的 DNSClientOptions:

字段类型默认值允许值描述
strategyDomainStrategy(prefer_ipv4)prefer_ipv4 | prefer_ipv6 | ipv4_only | ipv6_only默认地址家族偏好。
timeoutbadoption.Duration10s<duration>每个 DNS 查询的默认超时。可按规则(DNS 规则 action 的 timeout)或在 domain_resolver 中覆盖。
disable_cacheboolfalsetrue | false禁用内存应答缓存。
disable_expireboolfalsetrue | false不按 TTL 淘汰缓存条目 —— 永久保留。
independent_cacheboolfalsetrue | false已弃用:缓存总是按服务器区分,此选项不起作用。
cache_capacityuint321024<int>LRU 缓存容量(条目数)。小于 1024 的值会被提升为 1024。
optimistic*OptimisticDNSOptionsfalsetrue | 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_goboolfalsetrue | false使用 Go 的 net.Resolver(无 CGO)代替平台原生解析器。原生解析器损坏或被限速时有用。
neighbor_domainbadoption.Listable[string][][<.suffix>]域名后缀列表(每项以 . 开头),其单标签 A/AAAA 查询由邻居解析器(DHCP 租约中的局域网主机名)作答,而不是发往上游。. 匹配任意单标签名称,例如 [".", ".lan"]。

源码: option/dns.go:188-192 · 锚定版本 v1.14.2 (af6e64c)

type: "udp" 与 type: "tcp" —— RemoteDNSServerOptions ​

json
{ "type": "udp", "tag": "local-udp", "server": "8.8.8.8", "server_port": 53 }
字段类型默认值允许值描述
serverstring(required)<host>服务器主机名或 IP。
server_portuint1653 (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 ​

字段类型默认值允许值描述
pathstring/dns-query/<path>DoH 端点路径。
methodstringPOSTPOST | GETDoH 查询使用的 HTTP 方法。
headersbadoption.HTTPHeader{}{<header>: <value>}附加 HTTP 头。

源码: option/dns.go:204-209 · 锚定版本 v1.14.2 (af6e64c)

type: "hosts" —— 本地 hosts 文件 ​

字段类型默认值允许值描述
pathbadoption.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" ​

字段类型默认值允许值描述
interfacestring(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 分流的迁移写法:

json
{
  "dns": {
    "rules": [
      { "action": "evaluate", "server": "remote" },
      { "match_response": true, "rule_set": "geoip-cn",
        "action": "route", "server": "local" },
      { "action": "route", "server": "remote" }
    ]
  }
}

示例 ​

二服务器分流 —— 国内走本地 DoH,其余走 Cloudflare DoH:

json
{
  "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 拦截广告:

json
{
  "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 的路由 resolve action)。在同一 DNS 配置中把它们与已弃用的旧式地址过滤字段混用会在启动时被拒绝。
  • 已弃用的 outbound DNS 规则项仍可解析,但应改用 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)

由 Argsment 出品的 Core Tutorial