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, возвращать географически близкий ответ. |
tag | string | dns | <inbound tag> | Внутренний тег входящего подключения DNS-движка. Используется правилами маршрутизации, которым нужно выделить DNS-трафик. |
queryStrategy | string | UseIP | UseIP | UseIPv4 | UseIPv6 | Стратегия запросов по умолчанию, применяемая, когда стратегия для конкретного сервера не задана. `UseIP` запрашивает и A, и AAAA; `UseIPv4`/`UseIPv6` пропускает другое семейство. |
disableCache | bool | false | true | false | Отключить кеш ответов в памяти. Каждый запрос уходит наружу заново. |
serveStale | bool | false | true | false | Отдавать просроченные записи кеша, пока в фоне идёт обновление. Улучшает воспринимаемую задержку. |
serveExpiredTTL | uint32 | 0 | <seconds> | Максимум секунд, в течение которых просроченная запись отдаётся при включённом `serveStale`. 0 — без ограничения. |
disableFallback | bool | false | true | false | Не переходить к последующим серверам, когда первый сервер не вернул пригодный ответ. |
disableFallbackIfMatch | bool | false | true | false | То же, но только когда у совпавшего сервера есть собственный список `domains` — т. е. серверы, совпавшие по домену, никогда не запускают fallback. |
enableParallelQuery | bool | false | true | false | Опрашивать все подходящие серверы параллельно; побеждает первый корректный ответ. |
useSystemHosts | bool | false | true | false | Дополнительно сверяться с `/etc/hosts` ОС (или платформенным эквивалентом), прежде чем идти в сеть. |
Исходный код: infra/conf/dns.go:160-173 · зафиксировано на v26.7.28 (5ca6f4b)
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 для этого сервера. |
port | uint16 | 53 | <port> | Порт сервера (только для голых IP-адресов). |
skipFallback | bool | false | true | false | Если true и этот сервер не дал ответа, цепочка fallback *не* пробуется — запрос просто завершается неудачей. |
domains | StringList | [] | <domain pattern> | Домены, на которые должен отвечать этот сервер. Синтаксис как у правил маршрутизации. Если список непуст, сервер опрашивается только для этих доменов. |
expectedIPs | StringList | [] | <IP / CIDR / geoip:> | Принимать ответ этого сервера, только когда разрешённый IP совпадает с одним из этих шаблонов. Используется для отсеивания цензурированных или перехваченных ответов. |
expectIPs | StringList | (alias) | (alias of expectedIPs) | Псевдоним для совместимости с `expectedIPs`. |
queryStrategy | string | (inherit) | UseIP | UseIPv4 | UseIPv6 | Переопределение стратегии для этого сервера. |
tag | string | (unset) | <string> | Тег сервера — на него ссылаются правила маршрутизации, направляющие исходящий трафик резолвера. |
timeoutMs | uint64 | 4000 | <ms> | Тайм-аут одного запроса в миллисекундах. |
disableCache | *bool | (inherit) | true | false | Переопределение кеша для этого сервера. |
serveStale | *bool | (inherit) | true | false | Переопределение serve-stale для этого сервера. |
serveExpiredTTL | *uint32 | (inherit) | <seconds> | Потолок TTL просроченных записей для этого сервера. |
finalQuery | bool | false | true | false | Пометить сервер как финальный fallback — если он ответил, дальнейшее разрешение не выполняется. |
unexpectedIPs | StringList | [] | <IP / CIDR / geoip:> | Отклонять ответ этого сервера, если разрешённый IP совпал с любым из этих шаблонов. Дополнение к `expectedIPs`. |
Исходный код: infra/conf/dns.go:19-35 · зафиксировано на v26.7.28 (5ca6f4b)
hosts
Поле hosts — плоское отображение. Ключи поддерживают те же префиксы, что и правила маршрутизации; значения — одиночный IP либо массив IP.
{
"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:
{
"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:
{
"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-трафик в него — и оно либо перешлёт каждый запрос фиксированному резолверу, либо ответит на него согласно списку правил. Недавние версии Xray добавили поля rewrite для перезаписи адресата и движок rules (старые ручки nonIPQuery / blockTypes теперь считаются устаревшими).
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
rewriteNetwork | Network | (unset) | tcp | udp | tcp,udp | Транспорт, на который переписываются запросы. Каноническое имя для устаревшего `network`. |
rewriteAddress | *Address | (unset) | <host> | Резолвер, на который переписываются перехваченные DNS-запросы. Каноническое имя для устаревшего `address`. |
rewritePort | uint16 | 0 | <port> | Порт, на который переписываются запросы. Каноническое имя для устаревшего `port`. |
network | Network | (alias) | (alias of rewriteNetwork) | Устаревший псевдоним для `rewriteNetwork`. |
address | *Address | (alias) | (alias of rewriteAddress) | Устаревший псевдоним для `rewriteAddress`. |
port | uint16 | (alias) | (alias of rewritePort) | Устаревший псевдоним для `rewritePort`. |
userLevel | uint32 | 0 | <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.7.28 (5ca6f4b)
rules[]
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
action | string | (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> | Сопоставление по доменам (по умолчанию — подстрока; те же префиксы шаблонов, что и у правил маршрутизации). |
rCode | uint32 | 0 | 0-65535 | Код ответа, возвращаемый при `action` равном `return` (например, 5 = REFUSED, 3 = NXDOMAIN). |
Исходный код: infra/conf/dns_proxy.go:13-18 · зафиксировано на v26.7.28 (5ca6f4b)
Перехватить A/AAAA на фиксированный резолвер, отбрасывать запросы HTTPS-записей (тип 65) и отказывать во всём остальном:
{
"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.7.28 (5ca6f4b)
