Skip to content

DNS — Xray-core ​

Блок dns настраивает внутренний резолвер Xray: список серверов, необязательные статические хосты и набор переключателей кеширования / fallback. DNS-движок также представляет себя внутренним входящим подключением (по умолчанию с тегом dns), поэтому DNS-трафик можно маршрутизировать как любое другое соединение.

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

ПолеТипПо умолчаниюДопустимые значенияОписание
servers[]*NameServerConfig[][NameServerConfig | <string>]Список резолверов. Каждая запись — либо строка address (8.8.8.8, https://dns.google/dns-query, tcp+local://, fakedns, …), либо полный объект NameServerConfig.
hosts*HostsWrapper{}{<domain or pattern>: <IP | [IP, …]>}Статические хосты. Ключи поддерживают те же префиксы full:, domain:, regexp:, keyword:, geosite:, что и правила маршрутизации.
clientIp*Address(unset)<IP>ECS (EDNS Client Subnet), объявляемый в исходящих запросах. Помогает резолверам, знающим о CDN, возвращать географически близкий ответ.
tagstringdns<inbound tag>Внутренний тег входящего подключения DNS-движка. Используется правилами маршрутизации, которым нужно выделить DNS-трафик.
queryStrategystringUseIPUseIP | UseIPv4 | UseIPv6Стратегия запросов по умолчанию, применяемая, когда стратегия для конкретного сервера не задана. UseIP запрашивает и A, и AAAA; UseIPv4/UseIPv6 пропускает другое семейство.
disableCacheboolfalsetrue | falseОтключить кеш ответов в памяти. Каждый запрос уходит наружу заново.
serveStaleboolfalsetrue | falseОтдавать просроченные записи кеша, пока в фоне идёт обновление. Улучшает воспринимаемую задержку.
serveExpiredTTLuint320<seconds>Максимум секунд, в течение которых просроченная запись отдаётся при включённом serveStale. 0 — без ограничения.
disableFallbackboolfalsetrue | falseНе переходить к последующим серверам, когда первый сервер не вернул пригодный ответ.
disableFallbackIfMatchboolfalsetrue | falseТо же, но только когда у совпавшего сервера есть собственный список domains — т. е. серверы, совпавшие по домену, никогда не запускают fallback.
enableParallelQueryboolfalsetrue | falseОпрашивать все подходящие серверы параллельно; побеждает первый корректный ответ.
useSystemHostsboolfalsetrue | falseДополнительно сверяться с /etc/hosts ОС (или платформенным эквивалентом), прежде чем идти в сеть.

Исходный код: infra/conf/dns.go:160-173 · зафиксировано на v26.9.9 (52a412d)

servers[] — NameServerConfig ​

Каждая запись — либо голая строка адреса (разбирается в address), либо развёрнутая объектная форма:

ПолеТипПо умолчаниюДопустимые значенияОписание
address*Address(required)<DNS URL>Адрес резолвера. Голый IP (8.8.8.8 = UDP/53), tcp://, tls://, https://, quic://, tcp+local://... (локальный DNS в обход прокси), localhost или fakedns.
clientIp*Address(inherit)<IP>Переопределение ECS для этого сервера.
portuint1653<port>Порт сервера (только для голых IP-адресов).
skipFallbackboolfalsetrue | falseЕсли true и этот сервер не дал ответа, цепочка fallback *не* пробуется — запрос просто завершается неудачей.
domainsStringList[]<domain pattern>Домены, на которые должен отвечать этот сервер. Синтаксис как у правил маршрутизации. Если список непуст, сервер опрашивается только для этих доменов.
expectedIPsStringList[]<IP / CIDR / geoip:>Принимать ответ этого сервера, только когда разрешённый IP совпадает с одним из этих шаблонов. Используется для отсеивания цензурированных или перехваченных ответов.
expectIPsStringList(alias)(alias of expectedIPs)Псевдоним для совместимости с expectedIPs.
queryStrategystring(inherit)UseIP | UseIPv4 | UseIPv6Переопределение стратегии для этого сервера.
tagstring(unset)<string>Тег сервера — на него ссылаются правила маршрутизации, направляющие исходящий трафик резолвера.
timeoutMsuint644000<ms>Тайм-аут одного запроса в миллисекундах.
disableCache*bool(inherit)true | falseПереопределение кеша для этого сервера.
serveStale*bool(inherit)true | falseПереопределение serve-stale для этого сервера.
serveExpiredTTL*uint32(inherit)<seconds>Потолок TTL просроченных записей для этого сервера.
finalQueryboolfalsetrue | falseПометить сервер как финальный fallback — если он ответил, дальнейшее разрешение не выполняется.
unexpectedIPsStringList[]<IP / CIDR / geoip:>Отклонять ответ этого сервера, если разрешённый IP совпал с любым из этих шаблонов. Дополнение к expectedIPs.

Исходный код: infra/conf/dns.go:19-35 · зафиксировано на v26.9.9 (52a412d)

hosts ​

Поле hosts — плоское отображение. Ключи поддерживают те же префиксы, что и правила маршрутизации; значения — одиночный IP либо массив IP.

json
{
  "dns": {
    "hosts": {
      "domain:example.com": "203.0.113.10",
      "domain:internal.corp": ["10.0.0.1", "10.0.0.2"],
      "geosite:cn": "8.8.8.8"
    }
  }
}

Значение "fakedns" вместо IP заставляет Xray выдавать поддельный адрес из пула FakeDNS.

Примеры ​

Стандартный раздельный резолвер — домены КНР через локальный DoH, всё остальное через Cloudflare DoH:

json
{
  "dns": {
    "servers": [
      {
        "address": "https://doh.pub/dns-query",
        "domains": ["geosite:cn"],
        "expectedIPs": ["geoip:cn"]
      },
      "https://1.1.1.1/dns-query",
      {
        "address": "tcp+local://223.5.5.5",
        "domains": ["geosite:cn"]
      }
    ],
    "hosts": {
      "domain:example.com": "203.0.113.10"
    },
    "queryStrategy": "UseIP",
    "disableFallbackIfMatch": true,
    "enableParallelQuery": false
  }
}

Маршрутизация FakeDNS:

json
{
  "dns": {
    "servers": ["fakedns", "1.1.1.1"]
  },
  "fakeDns": { "ipPool": "198.18.0.0/15", "poolSize": 32768 },
  "inbounds": [{
    "port": 1080,
    "protocol": "socks",
    "sniffing": {
      "enabled": true,
      "destOverride": ["http", "tls", "fakedns"]
    }
  }]
}

Примечания ​

  • Голая строка 8.8.8.8 в servers[] — сокращение для {"address": "8.8.8.8"}: UnmarshalJSON структуры NameServerConfig (infra/conf/dns.go:36-43) принимает обе формы.
  • address: "localhost" использует резолвер ОС (удобно на платформах со stub-резолвером вроде systemd-resolved).
  • address: "tcp+local://..." выполняет запрос по TCP в обход движка маршрутизации — полезно для bootstrap-резолвера, от которого зависит остальная DNS-настройка.
  • Шаблоны domains: голые строки по умолчанию сопоставляются по суффиксу; префикс full: — точное совпадение, regexp: — регулярное выражение, keyword: — подстрока, geosite: — категория GeoSite.
  • expectedIPs / unexpectedIPs вместе реализуют паттерн «отклоняй отравленные ответы»: задайте expectedIPs: ["geoip:cn"] на домашнем резолвере и unexpectedIPs: ["geoip:cn"] на публичном.
  • clientIp (и clientIp конкретного сервера) задаёт опцию EDNS Client Subnet. Используйте реалистичное значение (например, один из своих IP), чтобы получать ответы с учётом CDN.
  • finalQuery: true помечает сервер как терминальный — как только он ответил, fallback не выполняется.

Исходящий dns ​

В отличие от блока dns выше, Xray поставляет исходящее подключение dns ("protocol": "dns"). Направьте DNS-трафик в него — и оно либо перешлёт каждый запрос фиксированному резолверу, либо ответит на него согласно списку правил: у него есть поля rewrite для перезаписи адресата и движок rules, а ручки nonIPQuery / blockTypes устарели в пользу rules.

ПолеТипПо умолчаниюДопустимые значенияОписание
rewriteNetworkNetwork(unset)tcp | udp | tcp,udpТранспорт, на который переписываются запросы. Каноническое имя для устаревшего network.
rewriteAddress*Address(unset)<host>Резолвер, на который переписываются перехваченные DNS-запросы. Каноническое имя для устаревшего address.
rewritePortuint160<port>Порт, на который переписываются запросы. Каноническое имя для устаревшего port.
networkNetwork(alias)(alias of rewriteNetwork)Устаревший псевдоним для rewriteNetwork.
address*Address(alias)(alias of rewriteAddress)Устаревший псевдоним для rewriteAddress.
portuint16(alias)(alias of rewritePort)Устаревший псевдоним для rewritePort.
userLeveluint320<uint32>Уровень политики для соединений этого исходящего подключения.
rules[]*DNSOutboundRuleConfig(unset)[DNSOutboundRuleConfig]Правила для каждого запроса, вычисляемые по порядку; первое совпадение решает, как обрабатывается запрос.
nonIPQuery*string(legacy)reject | drop | skipУстаревшая обработка не-IP-запросов. Вытеснена rules и не может с ними сочетаться.
blockTypes*[]int32(legacy)[<qType number>]Устаревший список номеров типов DNS-запросов для блокировки. Вытеснен rules.

Исходный код: infra/conf/dns_proxy.go:60-71 · зафиксировано на v26.9.9 (52a412d)

rules[] ​

ПолеТипПо умолчаниюДопустимые значенияОписание
actionstring(required)direct | drop | return | hijackЧто делать с совпавшим запросом. direct пересылает как есть; drop отбрасывает; return отвечает локально кодом rCode; hijack перенаправляет запрос на сервер из rewrite-полей.
qType*PortList(any)<DNS type number / range>Сопоставление по номерам типов DNS-запросов (1 = A, 28 = AAAA, 65 = HTTPS, …). Принимает списки через запятую и диапазоны.
domain*StringList(any)<domain pattern>Сопоставление по доменам (по умолчанию — подстрока; те же префиксы шаблонов, что и у правил маршрутизации).
rCodeuint3200-65535Код ответа, возвращаемый при action равном return (например, 5 = REFUSED, 3 = NXDOMAIN).

Исходный код: infra/conf/dns_proxy.go:13-18 · зафиксировано на v26.9.9 (52a412d)

Перехватить A/AAAA на фиксированный резолвер, отбрасывать запросы HTTPS-записей (тип 65) и отказывать во всём остальном:

json
{
  "outbounds": [
    {
      "tag": "dns-out",
      "protocol": "dns",
      "settings": {
        "rewriteAddress": "1.1.1.1",
        "rewritePort": 53,
        "rewriteNetwork": "udp",
        "rules": [
          { "action": "hijack", "qType": "1,28" },
          { "action": "drop",   "qType": "65" },
          { "action": "return", "rCode": 5 }
        ]
      }
    }
  ]
}

nonIPQuery и blockTypes нельзя смешивать с rules — это ошибка при запуске. Мигрируйте устаревшие конфигурации на rules.

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

  • sing-box использует полиморфную схему серверов по типу (type: "https", type: "tls", type: "fakeip", …) плюс структурированные DNS-правила с action: "route"|"reject"|"predefined". См. DNS — sing-box.
  • mihomo использует плоский блок dns: с отдельными списками nameserver / fallback и мощным отображением nameserver-policy для маршрутизации по доменам. См. DNS — mihomo.

Исходный код: infra/conf/dns.go:19-173 · v26.9.9 (52a412d)

Core Tutorial от Argsment