mirror of
https://github.com/XTLS/Xray-docs-next.git
synced 2026-10-06 22:08:16 +03:00
DNS outbound: Add rules (matches qtype, domain, then action)
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
- Например, в `freedom` Outbound, если `domainStrategy` установлен в `UseIP`, запрос, исходящий из этого Outbound, сначала будет разрешен в IP через встроенный сервер, а затем произойдет подключение.
|
||||
- Например, в `sockopt`, если `domainStrategy` установлен в `UseIP`, системное подключение, инициированное этим Outbound, сначала будет разрешено в IP встроенным сервером.
|
||||
|
||||
- Перехват DNS-трафика в режиме Transparent Proxy или работа в качестве рекурсивного DNS-сервера, открытого на порту 53.
|
||||
- Перехват DNS-трафика в режиме TUN/Transparent Proxy через связку routing и DNS outbound, чтобы направлять DNS-трафик в этот модуль; либо работа в качестве рекурсивного DNS-сервера, открытого на порту 53.
|
||||
|
||||
::: tip TIP 1
|
||||
DNS-запросы, отправляемые встроенным DNS-сервером, автоматически перенаправляются в соответствии с конфигурацией маршрутизации (Routing).
|
||||
|
||||
+149
-20
@@ -1,54 +1,183 @@
|
||||
# DNS
|
||||
|
||||
DNS — это исходящий протокол, который в основном используется для перехвата и пересылки DNS-запросов.
|
||||
DNS — это исходящий протокол, который принимает DNS-запросы, переданные routing, и пересылает или обрабатывает их по правилам.
|
||||
|
||||
Этот исходящий протокол может принимать только DNS-трафик (включая запросы по протоколам UDP и TCP), другие типы трафика вызовут ошибку.
|
||||
Этот outbound поддерживает только традиционный открытый DNS, то есть запросы по UDP и TCP; нестандартные для него варианты, такие как DoH, DoT и DoQ, к этому outbound не применимы. Типичные сценарии: TUN, прозрачный прокси или `dokodemo-door` принимают DNS-трафик, после чего routing направляет его в этот outbound.
|
||||
|
||||
При обработке DNS-запросов этот исходящий протокол пересылает запросы IP-адресов (то есть A и AAAA) на встроенный [DNS-сервер](../dns.md). Другие типы запросов см. в разделе `nonIPQuery` ниже.
|
||||
По правилам он может пропускать запросы к целевому DNS-серверу, выполнять `hijack` во встроенный [DNS-сервер](../dns.md) для дальнейшей обработки, отбрасывать запросы или явно отказывать в них. Также он может изменять целевой адрес, порт и транспортный протокол.
|
||||
|
||||
## OutboundConfigurationObject
|
||||
|
||||
```json
|
||||
{
|
||||
"network": "tcp",
|
||||
"network": "udp",
|
||||
"address": "1.1.1.1",
|
||||
"port": 53,
|
||||
"userLevel": 0,
|
||||
"nonIPQuery": "drop",
|
||||
"blockTypes": []
|
||||
"rules": [
|
||||
{
|
||||
"action": "reject",
|
||||
"domain": ["domain:example.com"]
|
||||
},
|
||||
{
|
||||
"action": "direct",
|
||||
"qtype": 65,
|
||||
"domain": ["geosite:geolocation-!cn"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> `network`: "tcp" | "udp"
|
||||
Пример выше только демонстрирует синтаксис полей. Полную конфигурацию см. в примере ниже.
|
||||
|
||||
Изменяет транспортный протокол DNS-трафика. Допустимые значения: `"tcp"` и `"udp"`. Если не указано, используется исходный транспортный протокол.
|
||||
> `network`: [ "tcp" | "udp" ]
|
||||
|
||||
Изменяет транспортный протокол DNS-трафика. Допустимые значения: `"tcp"` и `"udp"`. Если не указано, исходный транспортный способ сохраняется.
|
||||
|
||||
> `address`: address
|
||||
|
||||
Изменяет адрес DNS-сервера. Если не указано, используется адрес, указанный в источнике.
|
||||
Изменяет адрес DNS-сервера. Если не указано, сохраняется адрес, указанный источником.
|
||||
|
||||
> `port`: number
|
||||
|
||||
Изменяет порт DNS-сервера. Если не указано, используется порт, указанный в источнике.
|
||||
Изменяет порт DNS-сервера. Если не указано, сохраняется порт, указанный источником.
|
||||
|
||||
> `userLevel`: number
|
||||
|
||||
Уровень пользователя. Соединение будет использовать [локальную политику](../policy.md#levelpolicyobject), соответствующую этому уровню пользователя.
|
||||
Уровень пользователя. Соединения будут использовать [локальную политику](../policy.md#levelpolicyobject), соответствующую этому уровню пользователя.
|
||||
|
||||
Значение `userLevel` соответствует значению `level` в [policy](../policy.md#policyobject). Если не указано, по умолчанию используется значение `0`.
|
||||
Значение `userLevel` соответствует значению `level` в [policy](../policy.md#policyobject). Если не указано, по умолчанию используется `0`.
|
||||
|
||||
> `nonIPQuery`: string
|
||||
> `rules`: \[[RuleObject](#ruleobject)\]
|
||||
|
||||
Управляет запросами, не относящимися к IP-адресам (не A и AAAA). `"drop"` — отклонять, `"skip"` — не обрабатывать встроенным DNS-сервером, а пересылать на целевой сервер. В отличие от `"drop"`, это позволяет избежать ситуации, когда приложение тратит слишком много времени в ожидании ответа DNS до тайм-аута.
|
||||
DNS-запросы сопоставляются с правилами по порядку; поддерживается детальное управление по `qtype` и `domain`.
|
||||
|
||||
Значение по умолчанию — `"reject"`.
|
||||
Если ни одно правило не совпало, используется встроенное правило по умолчанию: запросы A и AAAA направляются во встроенный DNS-модуль, а запросы других типов явно отклоняются.
|
||||
|
||||
> `blockTypes`: array
|
||||
## RuleObject
|
||||
|
||||
Массив целых чисел (`int`), определяющий типы DNS-запросов, которые необходимо блокировать. Например, `"blockTypes": [65,28]` означает блокировку типа 65 (HTTPS) и 28 (AAAA). Распространенный сценарий использования — блокировка типа 65 для предотвращения инициализации ECH браузерами.
|
||||
```json
|
||||
{
|
||||
"action": "hijack",
|
||||
"qtype": 1,
|
||||
"domain": ["geosite:cn"]
|
||||
}
|
||||
```
|
||||
|
||||
Поскольку опция `nonIPQuery` по умолчанию отбрасывает (`drop`) все запросы, кроме A и AAAA, необходимо переключить её в режим `skip`, чтобы данная настройка могла вступить в силу (для типов, отличных от A/AAAA). Разумеется, можно не изменять `nonIPQuery` и использовать эту опцию исключительно для блокировки A или AAAA (отключение IPv4/IPv6), однако делать это **крайне не рекомендуется**. Для этих целей лучше использовать настройку `queryStrategy` во встроенном DNS.
|
||||
Все условия сопоставления внутри правила объединяются логикой AND. Если условие не указано, ограничение по этому условию не применяется.
|
||||
|
||||
Внимание: если вы используете `blockTypes` только для блокировки A или AAAA, и при этом `nonIPQuery` установлен в значение `reject`, то блокировка также будет осуществляться путем возврата ответа DNS reject, а не простым отбрасыванием пакета.
|
||||
> `action`: [ "direct" | "hijack" | "drop" | "reject" ]
|
||||
|
||||
## Примеры конфигурации DNS <Badge text="В РАЗРАБОТКЕ" type="warning"/>
|
||||
Определяет действие при совпадении правила.
|
||||
|
||||
- `direct`: напрямую пропускает запрос к целевому DNS-серверу. Если на уровне outbound также настроены `network`, `address` или `port`, запрос пересылается к измененной цели.
|
||||
- `hijack`: направляет запрос во встроенный [DNS-сервер](../dns.md) для дальнейшей обработки. Это можно использовать для дополнительного разделения трафика через конфигурацию встроенного DNS. В настоящее время поддерживаются только записи A и AAAA.
|
||||
- `drop`: напрямую отбрасывает запрос и не возвращает ответ.
|
||||
- `reject`: возвращает явный отказ. По сравнению с `drop`, это может предотвратить слишком долгое ожидание DNS timeout приложениями.
|
||||
|
||||
> `qtype`: number | string
|
||||
|
||||
Сопоставляет типы DNS-запросов. Есть три формы:
|
||||
|
||||
- `"a-b"`: `a` и `b` — целые числа. Это закрытый интервал; правило срабатывает, когда тип запроса попадает в этот диапазон.
|
||||
- `a`: `a` — целое число. Правило срабатывает, когда тип запроса равен `a`.
|
||||
- Комбинация двух форм выше через запятую. Например: `"1,3,23-24"`.
|
||||
|
||||
Распространенные номера типов можно посмотреть в [List of DNS record types](https://en.wikipedia.org/wiki/List_of_DNS_record_types).
|
||||
|
||||
Если не указано, сопоставляются все типы запросов.
|
||||
|
||||
> `domain`: [string]
|
||||
|
||||
Сопоставляет список доменов. Синтаксис такой же, как у [`domain` в правилах routing](../routing.md#ruleobject), например `domain:example.com`, `full:example.com`, `geosite:cn`. Если не указано, домены не ограничиваются.
|
||||
|
||||
## Пример конфигурации DNS
|
||||
|
||||
Следующий пример показывает практический сценарий: в прозрачном прокси inbound включает `sniffing` для разделения по домену / SNI, зарубежные домены идут через proxy, а остальной IP-трафик идет напрямую. При этом `dns-out` отклоняет HTTPS-записи для зарубежных доменов, чтобы уменьшить случаи, когда клиент получает ECH-конфигурацию и это влияет на разделение по открытому SNI; распространенные запросы вроде MX, TXT и SRV пересылаются указанному upstream, а запросы AAAA блокируются, потому что у proxy-сервера нет IPv6-среды.
|
||||
|
||||
```json
|
||||
{
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "all-in",
|
||||
"port": 12345,
|
||||
"protocol": "dokodemo-door",
|
||||
"settings": {
|
||||
"network": "tcp,udp",
|
||||
"followRedirect": true
|
||||
},
|
||||
"sniffing": {
|
||||
"enabled": true,
|
||||
"destOverride": ["http", "tls", "quic"],
|
||||
"routeOnly": true
|
||||
},
|
||||
"streamSettings": {
|
||||
"sockopt": {
|
||||
"tproxy": "tproxy"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dns": {
|
||||
"servers": ["https+local://1.1.1.1/dns-query"]
|
||||
},
|
||||
"outbounds": [
|
||||
{
|
||||
"tag": "direct",
|
||||
"protocol": "freedom"
|
||||
},
|
||||
{
|
||||
"tag": "proxy",
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
// Опущено...
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "dns-out",
|
||||
"protocol": "dns",
|
||||
"settings": {
|
||||
"network": "tcp",
|
||||
"address": "1.1.1.1",
|
||||
"port": 53,
|
||||
"rules": [
|
||||
{
|
||||
"action": "reject",
|
||||
"qtype": "28,65",
|
||||
"domain": ["geosite:geolocation-!cn"]
|
||||
},
|
||||
{
|
||||
"action": "direct",
|
||||
"qtype": "15-16,33"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"routing": {
|
||||
"domainStrategy": "AsIs",
|
||||
"rules": [
|
||||
{
|
||||
"inboundTag": ["all-in"],
|
||||
"network": "tcp,udp",
|
||||
"port": "53",
|
||||
"outboundTag": "dns-out"
|
||||
},
|
||||
{
|
||||
"domain": ["geosite:geolocation-!cn"],
|
||||
"outboundTag": "proxy"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Поведение примера:
|
||||
|
||||
- `all-in` включает `sniffing` и использует `routeOnly: true`, позволяя routing разделять трафик по определенным целевым доменам HTTP, TLS и QUIC, сохраняя исходный целевой адрес.
|
||||
- Открытые DNS-запросы UDP/TCP от `all-in` к порту 53 направляются правилом routing в `dns-out`.
|
||||
- Для обычного трафика `geosite:geolocation-!cn` идет через `proxy`; трафик, который не совпал с этим доменным правилом, автоматически использует первый outbound — `direct`.
|
||||
- HTTPS-записи с `qtype` `65` для доменов из `geosite:geolocation-!cn` явно отклоняются, что может помочь при разделении по открытому SNI.
|
||||
- AAAA-запросы с `qtype` `28` для доменов из `geosite:geolocation-!cn` явно отклоняются; это можно использовать для блокировки IPv6-резолвинга зарубежных доменов.
|
||||
- Запросы с `qtype` `15-16,33` напрямую разрешаются и пересылаются на `1.1.1.1:53` согласно конфигурации outbound, используя TCP в качестве транспорта.
|
||||
- Запросы, которые не совпали ни с одним правилом, попадают во встроенную fallback-логику: запросы A и AAAA направляются во встроенный DNS-модуль, а другие типы запросов явно отклоняются. Затем встроенный DNS обращается к upstream через `https+local://1.1.1.1/dns-query`, избегая зацикливания.
|
||||
|
||||
Reference in New Issue
Block a user