Files
XTLS_Xray-docs-next/docs/ru/config/dns.md
T
2026-09-12 06:38:54 +08:00

367 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Встроенный DNS-сервер
## DNS-сервер
Встроенный модуль DNS в Xray имеет три основных назначения:
- На этапе маршрутизации: разрешение доменов в IP и сопоставление правил на основе полученных IP для разделения трафика.
::: details Подробное объяснение
Разрешение доменного имени для маршрутизации по IP зависит от значения `routing.domainStrategy`. Встроенный DNS-сервер может использоваться для запросов только при следующих значениях:
- `"IPIfNonMatch"`: если в первом проходе маршрутизации не сработало ни одно правило, разрешение выполняется при условии, что цель содержит доменное имя и хотя бы одно правило содержит условие `ip`.
- `"IPOnDemand"`: разрешение выполняется, если цель содержит доменное имя и встречается правило с условием `ip`.
:::
- На этапе исходящего подключения: разрешение целевых доменных имен для подключения или передачи удаленному прокси-серверу.
::: details Подробное объяснение
- Например, если в исходящем подключении VLESS задать `targetStrategy` равным `UseIP`, целевой домен проксируемого запроса сначала разрешается локальным встроенным модулем DNS, затем полученный IP передается удаленному прокси-серверу.
- Если в исходящем подключении VLESS задать `sockopt.domainStrategy` равным `UseIP`, домен сервера VLESS разрешается встроенным модулем DNS, затем устанавливается соединение с полученным IP.
- Если в исходящем подключении Freedom задать `sockopt.domainStrategy` равным `UseIP`, целевой домен запроса разрешается встроенным модулем DNS, затем устанавливается соединение с полученным IP.
- Протокол WireGuard не допускает передачу доменного имени в качестве цели, поэтому его исходящее подключение может использовать встроенный модуль DNS для разрешения доменов в IP.
:::
- Перехват DNS-трафика в режиме TUN/прозрачного прокси с помощью маршрутизации и исходящего подключения DNS для направления запросов в этот модуль; либо использование [Tunnel](./inbounds/tunnel.md) для открытия порта 53 и работы в качестве рекурсивного DNS-сервера.
::: details Подробное объяснение
- Поддерживаются только базовые IP-запросы (записи A и AAAA). Записи CNAME будут запрашиваться повторно до тех пор, пока не будет возвращена запись A/AAAA. Другие типы запросов не попадают во встроенный DNS-сервер, а либо отбрасываются, либо передаются другим серверам в зависимости от вашей конфигурации исходящего подключения.
:::
## Процесс обработки DNS
Домен сначала проходит проверку сопоставления Hosts (см. поле `hosts`). Если нужный IP не найден, для запроса используется DNS-сервер.
Затем ядро начинает строить список серверов, сортируя их в зависимости от запрашиваемого домена по следующим правилам.
- Построение списка 1: содержит серверы, у которых поле `domains` успешно совпало с запрашиваемым доменом, в порядке их появления в конфигурационном файле.
- Проверка `disableFallback`: если `true`, построение списка 2 пропускается.
- Проверка `disableFallbackIfMatch`: если `true` и список 1 не пуст, построение списка 2 пропускается.
- Построение списка 2: содержит серверы, не входящие в список 1, у которых `skipFallback` не равно `true`, в порядке их появления в конфигурационном файле.
- Итоговый список серверов = список 1 + список 2.
Примечание: любой DNS-сервер с `FinalQuery`, равным `true`, напрямую усекает последующую часть списка.
При выполнении DNS-запроса ядро последовательно опрашивает серверы из итогового списка, фильтруя результаты с помощью `expectedIPs` и `unexpectedIPs`; если результат пуст, переходит к следующему серверу в списке. (При `enableParallelQuery`, равном `true`, поведение немного отличается, подробнее см. описание этого поля.)
## DnsObject
`DnsObject` соответствует разделу `dns` в конфигурационном файле.
```json
{
"dns": {
"hosts": {
"baidu.com": "127.0.0.1",
"dns.google": ["8.8.8.8", "8.8.4.4"]
},
"servers": [
"8.8.8.8",
"8.8.4.4",
{
"address": "1.2.3.4",
"port": 5353,
"domains": ["domain:xray.com"],
"expectedIPs": ["geoip:cn"],
"skipFallback": false,
"clientIP": "1.2.3.4"
},
{
"address": "https://8.8.8.8/dns-query",
"domains": ["geosite:netflix"],
"skipFallback": true,
"queryStrategy": "UseIPv4"
},
{
"address": "https://1.1.1.1/dns-query",
"domains": ["geosite:openai"],
"skipFallback": true,
"queryStrategy": "UseIPv6"
},
"localhost"
],
"clientIp": "1.2.3.4",
"queryStrategy": "UseIP",
"disableCache": false,
"serveStale": false,
"serveExpiredTTL": 0,
"disableFallback": false,
"disableFallbackIfMatch": false,
"enableParallelQuery": false,
"useSystemHosts": false,
"tag": "dns_inbound"
}
}
```
> `hosts`: map{string: address} | map{string: [address]}
Статический список сопоставлений. Значения представляют собой записи в форме "домен": "адрес" или "домен": ["адрес 1", "адрес 2"]. Адреса могут быть IP или доменными именами. При разрешении домена ядро проверяет все записи сопоставления и возвращает все совпавшие IP-адреса. Если совпадений не найдено, переходит к этапу DNS-запроса.
Целевое значение маппинга может быть доменом. Когда ядро завершает сопоставление и маппинг содержит доменное имя(а), поведение меняется следующим образом:
- Если маппинг содержит одновременно IP-адреса и доменные имена, доменные имена удаляются, и возвращаются только IP-адреса.
- Если маппинг содержит несколько доменных имен, возникает неоднозначность: запрос завершается неудачей.
- Если маппинг содержит ровно одно доменное имя, это доменное имя повторно передаётся в модуль Hosts для рекурсивного разрешения, повторяя описанные шаги; максимальная глубина рекурсии — 5.
- Если вышеописанная рекурсивная проверка не вернула IP, и итоговый результат содержит ровно одно доменное имя, это доменное имя заменяет исходный запрошенный домен и отправляется на этап DNS-запроса.
- В частности, если «домен» имеет формат знака решётки и следующего за ним числа (например, `#3`), любой запрос, совпавший с этой записью, немедленно завершается неудачей. Если запрос поступил от DNS outbound, ядро вернёт пустой ответ и соответствующий этому числу rcode, чтобы отклонить запрос.
Формат сопоставления (`domain:`, `full:` и т.д.) аналогичен `domain` в системе [маршрутизации](./routing.md#ruleobject). Отличие в том, что без префикса здесь по умолчанию используется `full:` (аналогично стандартному файлу hosts).
> `servers`: \[string | [DnsServerObject](#dnsserverobject) \]
Список DNS-серверов. Поддерживаются два типа: адрес DNS (строка) и [DnsServerObject](#dnsserverobject).
Если значение `"localhost"`, используется конфигурация DNS локальной системы.
Если значение — адрес DNS `"IP:Port"`, например, `"8.8.8.8:53"`, Xray будет использовать указанный UDP-порт этого адреса для DNS-запроса. Запрос следует правилам маршрутизации. Если порт не указан, по умолчанию используется 53.
Если значение в формате `"tcp://host:port"`, например, `"tcp://8.8.8.8:53"`, Xray будет использовать `DNS over TCP`. Запрос следует правилам маршрутизации. По умолчанию порт 53.
Если значение в формате `"tcp+local://host:port"`, например, `"tcp+local://8.8.8.8:53"`, Xray будет использовать `TCP Local Mode (TCPL)`. DNS-запрос не проходит через компонент маршрутизации, а отправляется напрямую через Freedom outbound для снижения задержек. По умолчанию порт 53.
Если значение в формате `"https://host:port/dns-query"`, например, `"https://dns.google/dns-query"`, Xray будет использовать `DNS over HTTPS` (RFC8484, сокращенно DoH). Некоторые провайдеры имеют сертификаты для IP-адресов, поэтому можно указывать IP напрямую, например, `https://1.1.1.1/dns-query`. Также можно использовать нестандартные порты и пути, например, `"https://a.b.c.d:8443/my-dns-query"`.
Если значение в формате `"h2c://host:port/dns-query"`, например, `"h2c://dns.google/dns-query"`, Xray будет использовать формат запроса `DNS over HTTPS`, но отправит его в открытом виде (h2c). Это нельзя использовать напрямую; требуется настроить Freedom Outbound + streamSettings с TLS, чтобы обернуть запрос в нормальный DoH. Используется для специальных целей, например, для настройки SNI в DoH-запросе или использования `utls` отпечатков.
Если значение в формате `"https+local://host:port/dns-query"`, например, `"https+local://dns.google/dns-query"`, Xray будет использовать `DoH Local Mode (DOHL)`. DoH-запрос не проходит через компонент маршрутизации, а отправляется напрямую через Freedom outbound. Обычно подходит для использования на сервере. Поддерживаются нестандартные порты и пути.
Если значение в формате `"quic+local://host"`, например, `"quic+local://dns.adguard.com"`, Xray будет использовать `DNS over QUIC Local Mode (DOQL)`. DNS-запрос не проходит через компонент маршрутизации, а отправляется напрямую через Freedom outbound. Требуется поддержка DNS over QUIC сервером. По умолчанию используется порт 853, можно указать нестандартный.
Если значение `fakedns`, используется функционал FakeDNS.
::: tip TIP 1
При использовании `localhost` DNS-запросы системы не контролируются Xray. Требуется дополнительная настройка, чтобы перенаправить системные DNS-запросы в Xray.
:::
::: tip TIP 2
DNS-клиенты, инициализированные различными правилами, будут отображаться в логе запуска Xray с уровнем `info`, например, режимы `local DOH`, `remote DOH` и `udp`.
:::
::: tip TIP 3
(v1.4.0+) В [логах](./log.md) можно включить журналирование DNS-запросов.
:::
::: tip TIP 4
DNS-сервер по умолчанию проходит сопоставление в системе маршрутизации, если только он не содержит `+local`. При использовании доменных имён внутри него обратите внимание на возможные петли (loop); может помочь `hosts`.
:::
> `clientIp`: string
IP-адрес, используемый в расширении EDNS Client Subnet (ECS).
Должен быть валидным IPv4 или IPv6. При фактической отправке последние биты автоматически стираются: отправляются подсети /24 для IPv4 и /96 для IPv6.
> `queryStrategy`: "UseIP" | "UseIPv4" | "UseIPv6" | "UseSystem"
Ограничивает возможности всех серверов в модуле DNS, а также задает значение по умолчанию для типов IP-запросов, инициированных самим Xray.
Значение по умолчанию `UseIP` разрешает запросы A + AAAA. Если тип IP не указан в запросе, инициированном самим Xray, у вышестоящего DNS-сервера запрашиваются одновременно A и AAAA записи. `UseIPv4` запрашивает и разрешает только A записи; `UseIPv6` запрашивает и разрешает только AAAA записи.
`UseSystem` адаптируется к сетевой среде операционной системы. Перед запросом проверяется наличие шлюзов по умолчанию для IPv4 и IPv6, чтобы ограничить возможности серверов и установить тип запроса. В ОС с графическим интерфейсом проверка выполняется в реальном времени, в среде командной строки — только один раз.
```json
{
"dns": {
"servers": [
"https://1.1.1.1/dns-query",
{
"address": "https://8.8.8.8/dns-query",
"domains": ["geosite:netflix"],
"skipFallback": true,
"queryStrategy": "UseIPv4" // Для доменов netflix запрашивать A запись
},
{
"address": "https://1.1.1.1/dns-query",
"domains": ["geosite:openai"],
"skipFallback": true,
"queryStrategy": "UseIPv6" // Для доменов openai запрашивать AAAA запись
}
],
"queryStrategy": "UseIP" // Глобально запрашивать одновременно A и AAAA записи
}
}
```
::: tip TIP 1
Глобальное значение `"queryStrategy"` имеет приоритет. Если `"queryStrategy"` во вложенном элементе конфликтует с глобальным `"queryStrategy"`, запрос вложенного элемента вернет пустой ответ.
:::
::: tip TIP 2
Если параметр `"queryStrategy"` во вложенном элементе не указан, используется глобальное значение `"queryStrategy"`. Поведение аналогично версиям Xray-core до v1.8.6.
:::
Например:<br>
Глобальный `"queryStrategy": "UseIPv6"` и вложенный `"queryStrategy": "UseIPv4"` — конфликт.<br>
Глобальный `"queryStrategy": "UseIPv4"` и вложенный `"queryStrategy": "UseIPv6"` — конфликт.<br>
Глобальный `"queryStrategy": "UseIP"` и вложенный `"queryStrategy": "UseIPv6"` — не конфликтуют.<br>
Глобальный `"queryStrategy": "UseIP"` и вложенный `"queryStrategy": "UseIPv4"` — не конфликтуют.
```json
{
"dns": {
"servers": [
"https://1.1.1.1/dns-query",
{
"address": "https://8.8.8.8/dns-query",
"domains": ["geosite:netflix"],
"skipFallback": true,
"queryStrategy": "UseIPv6" // Конфликт: глобальный "UseIPv4" и "UseIPv6" вложенного элемента
}
],
"queryStrategy": "UseIPv4"
}
}
```
Запрос домена Netflix получит пустой ответ из-за конфликта значений `"queryStrategy"`. Домен Netflix будет запрошен через `https://1.1.1.1/dns-query` и получит запись A.
> `disableCache`: true | false
`true` отключает кэширование DNS. По умолчанию `false` (не отключено).
Это не влияет на `localhost` DNS (системный DNS), который всегда следует поведению кэширования DNS в Golang (cgo и pure go могут немного отличаться).
> `serveStale`: true | false
`true` включает оптимистичное кэширование DNS (DNS optimistic caching). По умолчанию `false` (не включено).
Работает только если кэширование включено на сервере (зависит от `disableCache`).
> `serveExpiredTTL`: number
Срок жизни оптимистичного кэша в секундах. По умолчанию 0 (никогда не истекает).
Если сервер использует кэш и включено оптимистичное кэширование: когда основной кэш истек, но оптимистичный кэш еще действителен, немедленно возвращается устаревшая запись DNS из кэша, а обновление кэша происходит в фоновом режиме. Это снижает Latency.
> `disableFallback`: true | false
`true` отключает fallback-запросы DNS. По умолчанию `false` (не отключено).
> `disableFallbackIfMatch`: true | false
`true` отключает fallback-запросы, если сработал список приоритетных доменов DNS-сервера. По умолчанию `false` (не отключено).
> `enableParallelQuery`: true | false
`true` включает параллельные запросы. По умолчанию `false` (не включено).
Отказоустойчивость (failover) DNS по умолчанию последовательна: запрос к следующему серверу отправляется только после неудачи предыдущего или несовпадения `expectedIPs` / `unexpectedIPs`.
При включении параллельных запросов они отправляются асинхронно ко всем выбранным DNS-серверам, и применяется стратегия «Динамическая группировка, гонка внутри группы, откат между группами».
**Динамическая группировка**: **соседние** серверы в списке выбранных считаются одной группой, если их параметры `clientIP`, `skipFallback`, `queryStrategy`, `tag`, `domains`, `expectedIPs`, `unexpectedIPs` **полностью** совпадают.
**Гонка внутри группы**: если любой DNS-сервер в группе успешно выполнил запрос и полученный IP соответствует `expectedIPs` / `unexpectedIPs`, группа считается успешной. Результаты остальных серверов группы игнорируются.
**Откат между группами**: пока первая группа выполняет запрос, система ждет. Если первая группа успешна — возвращается IP. Если все серверы первой группы потерпели неудачу или IP не подошел — происходит откат (fallback) к следующей группе. Если все группы потерпели неудачу, возвращается пустой ответ.
> `useSystemHosts`: true | false
Если `true`, системный файл hosts добавляется к hosts встроенного DNS.
> `tag`: string
Для трафика запросов, исходящих от встроенного DNS (кроме режимов `localhost`, `fakedns`, `TCPL`, `DOHL` и `DOQL`), можно использовать этот тег для сопоставления в маршрутизации через `inboundTag`.
### DnsServerObject
```json
{
"address": "1.2.3.4",
"port": 5353,
"domains": ["domain:xray.com"],
"expectedIPs": ["geoip:cn"],
"unexpectedIPs": ["geoip:cloudflare"],
"skipFallback": false,
"finalQuery": false,
"tag": "dns-tag",
"clientIP": "1.2.3.4",
"queryStrategy": "UseIPv4",
"disableCache": false
}
```
> `address`: address
Список DNS-серверов. Поддерживаются два типа: адрес DNS (строка) и DnsServerObject.
Если значение `"localhost"`, используется конфигурация DNS локальной системы.
Если значение — адрес DNS `"IP"`, например, `"8.8.8.8"`, Xray будет использовать указанный UDP-порт этого адреса для DNS-запроса. Запрос следует правилам маршрутизации. По умолчанию используется порт 53.
Если значение в формате `"tcp://host"`, например, `"tcp://8.8.8.8"`, Xray будет использовать `DNS over TCP`. Запрос следует правилам маршрутизации. По умолчанию порт 53.
Если значение в формате `"tcp+local://host"`, например, `"tcp+local://8.8.8.8"`, Xray будет использовать `TCP Local Mode (TCPL)`. DNS-запрос не проходит через компонент маршрутизации, а отправляется напрямую через Freedom outbound для снижения задержек. Если порт не указан, по умолчанию используется 53.
Если значение в формате `"https://host:port/dns-query"`, например, `"https://dns.google/dns-query"`, Xray будет использовать `DNS over HTTPS` (RFC8484, сокращенно DoH). Некоторые провайдеры имеют сертификаты для IP-адресов, поэтому можно указывать IP напрямую, например, `https://1.1.1.1/dns-query`. Также можно использовать нестандартные порты и пути, например, `"https://a.b.c.d:8443/my-dns-query"`.
Если значение в формате `"https+local://host:port/dns-query"`, например, `"https+local://dns.google/dns-query"`, Xray будет использовать `DoH Local Mode (DOHL)`. DoH-запрос не проходит через компонент маршрутизации, а отправляется напрямую через Freedom outbound для снижения задержек. Обычно подходит для использования на сервере. Поддерживаются нестандартные порты и пути.
Если значение в формате `"quic+local://host:port"`, например, `"quic+local://dns.adguard.com"`, Xray будет использовать `DOQ Local Mode (DOQL)`. DNS-запрос не проходит через компонент маршрутизации, а отправляется напрямую через Freedom outbound. Требуется поддержка DNS over QUIC сервером. По умолчанию используется порт 853, можно указать нестандартный.
Если значение `fakedns`, используется функционал FakeDNS.
::: tip О режиме local и доменах самих DNS-серверов
DNS-запросы, отправляемые модулем DNS, бывают двух типов:
Режим `local`: соединение устанавливается ядром напрямую во внешнюю сеть. Если адрес является доменом, он будет разрешен самой системой. Логика здесь проста.
В режиме `non-local` DNS-запросы поступают в систему маршрутизации как внутренние запросы, а их `inboundTag` задается полем `tag` в конфигурации DNS. Если запрос направлен в локальное исходящее подключение Freedom, доменное имя самого DNS-сервера разрешается согласно `sockopt.domainStrategy` этого подключения (возможны петли). Если запрос направлен в исходящее подключение удаленного прокси, домен можно передать удаленной стороне для разрешения.
Поскольку обычным пользователям сложно разобраться в этой логике, рекомендуется (особенно в среде Transparent Proxy) напрямую указывать соответствующие IP для серверов с доменными именами в опции `hosts` модуля DNS, чтобы предотвратить возникновение петель (loop).
Кстати, DNS-запросы в режиме `non-local` автоматически пропускают этапы резолвинга `IPIfNonMatch` и `IPOnDemand` в модуле маршрутизации, чтобы их резолвинг не был отправлен обратно в модуль DNS, вызывая бесконечный цикл.
:::
> `port`: number
Порт DNS-сервера, например `53`. Если не указано, по умолчанию `53`. Для режимов DOH, DOHL, DOQL этот параметр недействителен; нестандартные порты следует указывать в URL.
> `domains`: \[string\]
Список доменов. Домены из этого списка будут приоритетно запрашиваться через данный сервер. Формат доменов аналогичен [конфигурации маршрутизации](./routing.md#ruleobject).
> `expectedIPs`:\[string\]
Список диапазонов IP. Формат аналогичен [конфигурации маршрутизации](./routing.md#ruleobject).
Если этот параметр настроен, Xray DNS проверит возвращенный IP и вернет его только в том случае, если он входит в список `expectedIPs`.
Если в списке присутствует `*`, и после фильтрации IP не найден, будет возвращен исходный IP, чтобы запрос не завершился ошибкой.
> `unexpectedIPs`: [string]
Обратная версия `expectedIPs`. Исключает IP, входящие в этот список. Звездочка работает так же.
> `skipFallback`: true | false
`true` — пропускать этот сервер при выполнении DNS fallback запросов. По умолчанию `false` (не пропускать).
> `timeoutMs`: number
Таймаут DNS-сервера. По умолчанию 4000 мс.
Это не влияет на `localhost` DNS (системный DNS), который всегда следует поведению таймаута DNS в Golang (cgo и pure go могут немного отличаться).
> `finalQuery`: true | false
Если `true`, запрос к этому DNS-серверу будет последней попыткой; fallback не будет инициирован.
> `queryStrategy`: "UseIP" | "UseIPv4" | "UseIPv6" | "UseSystem"
Если не указано, наследуется из глобальной конфигурации. Если указано, позволяет дополнительно ограничить возможности этого сервера, а также задать значение по умолчанию для типов IP-запросов, инициированных самим Xray.
Внимание: этот параметр всегда ограничен глобальным `queryStrategy`.
### Следующие параметры, если не указаны, наследуются из глобальной конфигурации, но могут переопределять её здесь
> `tag`: string
> `clientIP`: [string]
> `disableCache`: true | false
> `serveStale`: true | false
> `serveExpiredTTL`: number