Skip to content

DNS — sing-box ​

DNS-движок sing-box — это список типизированных серверов плюс структурированная цепочка правил. Каждый сервер имеет type, выбирающий его транспорт (UDP, TCP, TLS, QUIC, HTTPS, HTTP/3, файл hosts, пул fake-ip, полученный по DHCP, mDNS, systemd-resolved, встроенный Tailscale или резолверы, переданные конечной точкой OpenVPN / OpenConnect). Правила используют тот же набор полей сопоставления, что и правила маршрутизации, но с действиями, специфичными для DNS, — а также могут сопоставляться с ответом.

Параметры верхнего уровня ​

ПолеТипПо умолчаниюДопустимые значенияОписание
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.
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-запроса. Переопределяется в правиле (timeout действия DNS-правила) и в 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 для перехода на Go-резолвер без CGO. neighbor_domain отвечает на одноуровневые имена LAN из резолвера соседей. На платформах, кроме Apple, сервер local также разрешает *.local. и link-local-зоны обратного просмотра через mDNS (на Apple — через системный резолвер).

ПолеТипПо умолчаниюДопустимые значенияОписание
prefer_goboolfalsetrue | falseИспользовать net.Resolver из Go (без CGO) вместо нативного резолвера платформы. Полезно на системах, где нативный резолвер сломан или ограничен по частоте запросов.
neighbor_domainbadoption.Listable[string][][<.suffix>]Суффиксы доменов (каждый начинается с .), для которых одноуровневые A/AAAA-запросы обслуживаются резолвером соседей (имена хостов LAN из аренд 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 | GETHTTP-метод для DoH-запросов.
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 CIDR, выделяемый под поддельные IP.
inet6_range*badoption.Prefix(required for v6)<CIDR>IPv6 CIDR, выделяемый под поддельные IP.

Исходный код: 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, привязанные к сетевым интерфейсам (только Linux).
  • type: "tailscale" — использовать резолвер MagicDNS демона Tailscale.
  • type: "mdns" — многоадресные запросы в локальной сети (mDNS), необязательный список interface. Рядом с сервером local обычно не нужен (он уже направляет *.local. через mDNS); добавляйте, чтобы ссылаться на него из preferred_by.
  • type: "openvpn" / type: "openconnect" — резолверы, переданные клиентской конечной точкой OpenVPN / OpenConnect (endpoint: "<tag>"), с accept_default_resolvers и accept_search_domain. Переданные настройки в ОС не устанавливаются.

Типов серверов predefined и rcode нет: фиксированные ответы даёт действие DNS-правила predefined (см. ниже).

Правила DNS ​

Правила DNS используют ту же полиморфную форму _Rule, что и правила маршрутизации (type: "default" или type: "logical"), с 54 ключами сопоставления RawDefaultDNSRule — в том числе query_client_subnet, query_dnssec, package_name_regex, source_mac_address, source_hostname, preferred_by (совпадение с именами, которые перечисленные серверы считают своими: записи hosts, имена mDNS, split-DNS и домены поиска от Tailscale / VPN) и поля сопоставления ответа ниже. Различия — на уровне действий:

DNS-действиеЗначение
route (по умолчанию)Отправить запрос в server: "<tag>". Необязательно: disable_cache, disable_optimistic_cache, rewrite_ttl, timeout, client_subnet / remove_client_subnet, speculative; strategy устарел.
route-optionsПрименить параметры DNS-маршрута (те же необязательные поля) к последующим совпадениям правил.
evaluateЗапросить server и сохранить ответ (при желании под tag), чтобы последующие правила сопоставлялись с ним через match_response; не завершает вычисление правил. Только в правилах верхнего уровня.
respondВернуть ответ, сохранённый предшествующим evaluate, без нового запроса.
rejectОтклонить запрос. method: "default" отвечает REFUSED; method: "drop" не отвечает.
predefinedВернуть жёстко заданный ответ (rcode, answer, ns, extra).

race: true (на правилах route / respond / reject / predefined, использующих match_response) позволяет судить зависящие от ответа правила параллельно — побеждает первое совпавшее, остальные запросы отменяются.

Сопоставление с ответом ​

Правила могут сопоставляться с ответом, а не только с запросом. Правило evaluate получает ответ; последующее правило с match_response: true (или tag того правила evaluate) сопоставляет его через ip_cidr / ip_is_private / ip_accept_any, IP-набор правил или поля ответа response_rcode, response_answer, response_ns, response_extra. Использование ip_cidr / ip_is_private без match_response (устаревший фильтр адресов), параметр действия strategy и 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, всё остальное через DoH Cloudflare:

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 ни на что не влияет: кэш всегда ключуется по тегу сервера (и client subnet), так что split-horizon-серверы никогда не делят ответы. Параметр устарел — удалите его.
  • ip_version и query_type применяются и к внутренним разрешениям, не нацеленным на конкретный сервер (например, действие маршрутизации resolve без server). Сочетание их с устаревшими полями фильтра адресов в одной DNS-конфигурации отклоняется при запуске.
  • Устаревший элемент DNS-правила outbound ещё разбирается, но его следует заменить на route.default_domain_resolver или domain_resolver исходящего.
  • Правила DNS и правила маршрутизации разделяют один и тот же словарь ключей сопоставления, но работают в разное время: правила DNS выполняются на запросе к резолверу; правила маршрутизации — на итоговом соединении.
  • type: "resolved" читает данные через D-Bus API systemd-resolved — работает только на Linux-системах, где resolved действительно является запущенным резолвером.

Сравнение с другими ядрами ​

  • Xray-core использует плоский блок dns:, где servers[] содержит URL-строки (или объекты NameServerConfig) — поля type нет, транспорт определяется схемой URL. См. DNS — Xray-core.
  • mihomo имеет блок dns: из 25 полей с отдельными списками nameserver / fallback и отображением nameserver-policy. См. DNS — mihomo.

Исходный код: option/dns.go:18-224 · v1.14.2 (af6e64c)

Core Tutorial от Argsment