Встроенный DNS-сервер
DNS-сервер
Встроенный модуль DNS в Xray имеет три основных назначения:
На этапе маршрутизации (Routing): резолвинг доменов в IP и сопоставление правил на основе полученных IP для разделения трафика. Будет ли выполняться резолвинг и разделение трафика, зависит от значения
domainStrategyв конфигурации модуля маршрутизации. Встроенный DNS-сервер используется для запросов только при установке следующих двух значений:"IPIfNonMatch": при запросе домена сначала выполняется сопоставление по правилам
domain. Если совпадений нет, выполняется запрос к встроенному DNS-серверу для получения IP, после чего снова выполняется сопоставление правил маршрутизации по IP."IPOnDemand": при обнаружении любого правила, основанного на IP, домен немедленно резолвится в IP для сопоставления.
Резолвинг целевого адреса для подключения:
Например, в
freedomOutbound, еслиdomainStrategyустановлен вUseIP, запрос, исходящий из этого Outbound, сначала будет разрешен в IP через встроенный сервер, а затем произойдет подключение.Например, в
sockopt, еслиdomainStrategyустановлен вUseIP, системное подключение, инициированное этим Outbound, сначала будет разрешено в IP встроенным сервером.Перехват DNS-трафика в режиме Transparent Proxy или работа в качестве рекурсивного DNS-сервера, открытого на порту 53.
TIP 1
DNS-запросы, отправляемые встроенным DNS-сервером, автоматически перенаправляются в соответствии с конфигурацией маршрутизации (Routing).
TIP 2
Поддерживаются только базовые IP-запросы (записи A и AAAA). Записи CNAME будут запрашиваться повторно до тех пор, пока не будет возвращена запись A/AAAA. Другие типы запросов не попадают во встроенный DNS-сервер, а либо отбрасываются, либо передаются другим серверам в зависимости от вашей конфигурации Outbound.
Процесс обработки DNS
Если запрашиваемый домен:
- Попадает в маппинг «домен - IP» или «домен - массив IP» в
hosts, то этот IP или массив возвращается как результат DNS-резолвинга. - Попадает в маппинг «домен - домен» в
hosts, то значение (другой домен) становится текущим запрашиваемым доменом и снова проходит процесс обработки DNS, пока не будет получен IP или пустой ответ. - Не попал в
hosts, но попал в список доменовdomainsодного (или нескольких) DNS-серверов, то запрос выполняется через эти серверы в порядке приоритета правил. Если запрос к выбранному серверу не удался илиexpectedIPsне совпали, используется следующий подходящий сервер; в противном случае возвращается полученный IP. Если все подходящие серверы не смогли выполнить запрос илиexpectedIPsне совпали, компонент DNS: - По умолчанию выполняет «DNS Fallback запрос»: последовательно опрашиваются серверы, которые «не использовались в предыдущем неудачном раунде и имеют
skipFallbackсо значением по умолчаниюfalse». Если запрос не удался илиexpectedIPsне совпали, возвращается пустой ответ; иначе — полученный IP. - Если
disableFallbackустановлено вtrue, «DNS Fallback запрос» не выполняется. - Не попал ни в
hosts, ни в спискиdomainsDNS-серверов, то: - По умолчанию последовательно используются «серверы с
skipFallbackпо умолчаниюfalse». Если первый выбранный сервер не смог выполнить запрос илиexpectedIPsне совпали, используется следующий; иначе возвращается IP. Если все выбранные серверы потерпели неудачу, возвращается пустой ответ. - Если количество «серверов с
skipFallbackпо умолчаниюfalse» равно 0 илиdisableFallbackустановлено вtrue, используется первый DNS-сервер из конфигурации. При неудаче возвращается пустой ответ, при успехе — IP.
DnsObject
DnsObject соответствует разделу dns в конфигурационном файле.
{
"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"
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
hosts: map{string: address} | map
Список статических IP. Значениями являются пары "домен": "адрес" или "домен": ["адрес 1","адрес 2"]. Адрес может быть IP или доменом. При резолвинге, если домен совпадает с записью в этом списке:
- Если адрес является IP, результатом будет этот IP.
- Если адрес является доменом, для получения IP будет использоваться этот новый домен, а не исходный.
- Если в адресе указано несколько IP и доменов, будет возвращен только первый домен, остальные IP и домены игнорируются.
- Если первое значение адреса начинается с решетки и цифры (например,
#3), при использовании DNS Outbound ядро вернет пустой ответ и соответствующийrcode(код отказа), чтобы отклонить запрос. Если запрос пришел из внутреннего источника, он будет считаться неудачным. - Если запрашиваемый домен совпадает с несколькими доменами в списке, возвращаются все связанные IP.
Формат сопоставления (domain:, full: и т.д.) аналогичен domain в системе маршрутизации. Отличие в том, что без префикса здесь по умолчанию используется full: (аналогично стандартному файлу hosts).
servers: [string | DnsServerObject ]
Список DNS-серверов. Поддерживаются два типа: адрес DNS (строка) и 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 1
При использовании localhost DNS-запросы системы не контролируются Xray. Требуется дополнительная настройка, чтобы перенаправить системные DNS-запросы в Xray.
TIP 2
DNS-клиенты, инициализированные различными правилами, будут отображаться в логе запуска Xray с уровнем info, например, режимы local DOH, remote DOH и udp.
TIP 3
(v1.4.0+) В логах можно включить журналирование DNS-запросов.
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, чтобы ограничить возможности серверов и установить тип запроса. В ОС с графическим интерфейсом проверка выполняется в реальном времени, в среде командной строки — только один раз.
"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 записи
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
TIP 1
Глобальное значение "queryStrategy" имеет приоритет. Если "queryStrategy" во вложенном элементе конфликтует с глобальным "queryStrategy", запрос вложенного элемента вернет пустой ответ.
TIP 2
Если параметр "queryStrategy" во вложенном элементе не указан, используется глобальное значение "queryStrategy". Поведение аналогично версиям Xray-core до v1.8.6.
Например:
Глобальный "queryStrategy": "UseIPv6" и вложенный "queryStrategy": "UseIPv4" — конфликт.
Глобальный "queryStrategy": "UseIPv4" и вложенный "queryStrategy": "UseIPv6" — конфликт.
Глобальный "queryStrategy": "UseIP" и вложенный "queryStrategy": "UseIPv6" — не конфликтуют.
Глобальный "queryStrategy": "UseIP" и вложенный "queryStrategy": "UseIPv4" — не конфликтуют.
"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"
}2
3
4
5
6
7
8
9
10
11
12
13
14
Запрос домена 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
{
"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
}2
3
4
5
6
7
8
9
10
11
12
13
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.
О режиме local и доменах самих DNS-серверов
DNS-запросы, отправляемые модулем DNS, бывают двух типов:
Режим local: соединение устанавливается ядром напрямую во внешнюю сеть. Если адрес является доменом, он будет разрешен самой системой. Логика здесь проста.
Режим non-local: по умолчанию запрос рассматривается как входящий из Inbound с тегом dns.tag (не знаете где это? нажмите ctrl+f в браузере и найдите inboundTag). Он проходит через стандартный процесс обработки ядра и может быть направлен модулем маршрутизации в локальный freedom или другой удаленный Outbound. Там он будет разрешен согласно domainStrategy в freedom (осторожно, возможна петля) или передан в удаленный узел в виде домена для разрешения согласно методу сервера.
Поскольку обычным пользователям сложно разобраться в этой логике, рекомендуется (особенно в среде Transparent Proxy) напрямую указывать соответствующие IP для серверов с доменными именами в опции hosts модуля DNS, чтобы предотвратить возникновение петель (loop).
Кстати, DNS-запросы в режиме non-local автоматически пропускают этапы резолвинга IPIfNonMatch и IPOnDemand в модуле маршрутизации, чтобы их резолвинг не был отправлен обратно в модуль DNS, вызывая бесконечный цикл.
port: number
Порт DNS-сервера, например 53. Если не указано, по умолчанию 53. Для режимов DOH, DOHL, DOQL этот параметр недействителен; нестандартные порты следует указывать в URL.
domains: [string]
Список доменов. Домены из этого списка будут приоритетно запрашиваться через данный сервер. Формат доменов аналогичен конфигурации маршрутизации.
expectedIPs:[string]
Список диапазонов IP. Формат аналогичен конфигурации маршрутизации.
Если этот параметр настроен, 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