DNS Outbound: Clear desc

This commit is contained in:
Fangliding
2026-04-26 12:19:15 +08:00
parent 7795776367
commit 19559ad7c9
3 changed files with 18 additions and 300 deletions
+6 -100
View File
@@ -73,111 +73,17 @@ DNS 是一个出站协议,用于接收由 routing 送入的 DNS 查询,并
- `direct`: 直接放行到目标 DNS 服务器;若同时配置了出站级别的 `network`、`address` 或 `port`,则按改写后的目标继续转发。
- `hijack`: 将查询导入内置的 [DNS 服务器](../dns.md) 继续处理,可用于按照内置 DNS 的配置进一步分流;目前仅支持 A 和 AAAA 记录。
- `drop`: 直接丢弃请求,不返回响应。
- `reject`: 返回显式拒绝响应,相比 `drop` 可以避免应用长时间等待 DNS 超时。
- `reject`: 返回显式拒绝响应,相比 `drop` 可以避免部分应用长时间等待 DNS 超时或反复重试。
> `qtype`: number | string
匹配 DNS 查询类型,有三种形式:
匹配 DNS 查询类型,形式如下:
- `"a-b"`:`a` 和 `b` 均为整数。这个范围是一个前后闭合区间,当查询类型落在此范围内时,此规则生效。
- `a`:`a` 为整数。当查询类型为 `a` 时,此规则生效。
- 以上两种形式的混合,以逗号 `,` 分隔。形如:`"1,3,23-24"`。
- 整型数值 具体的查询类型,如 `"qtype": 1` 代表 A 查询,`"qtype": 28` 代表 AAAA 查询。
- 字符串:可以是一个只有数字的字符串,如 `"qtype": "28"`;或者一个数值范围,如 `"qtype": "5-10"` 表示type 5 到 type 10,这 6 个类型。可以使用逗号进行分段,如 `11,13,15-17` 表示type 11、type 13、type 15 到 type 17 这 5 个类型。
常见类型编号可参考 [DNS 记录类型列表](https://zh.wikipedia.org/zh-cn/DNS%E8%AE%B0%E5%BD%95%E7%B1%BB%E5%9E%8B%E5%88%97%E8%A1%A8)。
省略时表示匹配所有查询类型。
具体数字编号可参考 [IANA 文档](https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml)。
> `domain`: [string]
匹配域名列表,写法与 [路由规则中的 `domain`](../routing.md#ruleobject) 一致,例如 `domain:example.com`、`full:example.com`、`geosite:cn`。省略时表示不限制域名。
## DNS 配置实例
下面的示例演示一个实际场景:透明代理环境中,入站开启 `sniffing` 做域名 / SNI 分流,国外域名走代理,其余 IP 流量直连;同时通过 `dns-out` 拒绝国外域名的 HTTPS 记录,以减少客户端获取 ECH 配置后影响明文 SNI 分流的情况,并将常见的 MX、TXT、SRV 等查询转发到指定上游;代理服务器没有 IPv6 环境因此还需要屏蔽 AAAA 查询。
```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 目标域名进行分流,同时保留原始目标地址。
- 来自 `all-in`、发往 53 端口的 UDP/TCP 明文 DNS 查询,会被 routing 规则分流到 `dns-out`。
- 普通流量中,`geosite:geolocation-!cn` 走 `proxy`,未命中该域名规则的流量自动默认走第一个出站 `direct`。
- `geosite:geolocation-!cn` 中域名的 `qtype` 为 `65` 的 HTTPS 记录会被显式拒绝,可用于配合基于明文 SNI 的分流。
- `geosite:geolocation-!cn` 中域名的 `qtype` 为 `28` 的 AAAA 查询会被显式拒绝,可用于屏蔽国外域名的 IPv6 解析。
- `qtype` 为 `15-16,33` 的查询会被直接放行,并按出站配置转发到 `1.1.1.1:53`,传输方式改为 TCP。
- 其余未命中的查询会进入默认兜底逻辑:A 和 AAAA 查询被导入内置 DNS 模块,其它类型被显式拒绝;内置 DNS 再通过 `https+local://1.1.1.1/dns-query` 向上游发起查询,避免形成回环。
匹配域名列表,写法与 [路由规则中的 `domain`](../routing.md#ruleobject) 一致。
+6 -100
View File
@@ -73,111 +73,17 @@ Defines the action to take when the rule matches.
- `direct`: Allows the query directly to the target DNS server. If outbound-level `network`, `address`, or `port` is also configured, the query is forwarded to the rewritten target.
- `hijack`: Imports the query into the built-in [DNS server](../dns.md) for further processing. This can be used for additional routing based on the built-in DNS configuration. Currently, only A and AAAA records are supported.
- `drop`: Drops the request directly without returning a response.
- `reject`: Returns an explicit refusal response. Compared with `drop`, this can prevent applications from waiting too long for a DNS timeout.
- `reject`: Returns an explicit refusal response. Compared with `drop`, this can prevent some applications from waiting too long for a DNS timeout or repeatedly retrying.
> `qtype`: number | string
Matches DNS query types. It has three forms:
Matches DNS query types. The forms are as follows:
- `"a-b"`: `a` and `b` are both integers. This is a closed interval; the rule takes effect when the query type falls within this range.
- `a`: `a` is an integer. The rule takes effect when the query type is `a`.
- A comma-separated mix of the two forms above. For example: `"1,3,23-24"`.
- Integer value: a specific query type, such as `"qtype": 1` for an A query, or `"qtype": 28` for an AAAA query.
- String: can be a digits-only string such as `"qtype": "28"`, or a numeric range such as `"qtype": "5-10"`, which represents the 6 types from type 5 to type 10. Commas can be used for segmentation, such as `11,13,15-17`, which represents the 5 types: type 11, type 13, and type 15 to type 17.
Common type numbers can be found in the [List of DNS record types](https://en.wikipedia.org/wiki/List_of_DNS_record_types).
If omitted, all query types are matched.
For specific type numbers, refer to the [IANA documentation](https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml).
> `domain`: [string]
Matches a list of domains. The syntax is the same as [`domain` in routing rules](../routing.md#ruleobject), such as `domain:example.com`, `full:example.com`, and `geosite:cn`. If omitted, domains are not restricted.
## DNS Configuration Example
The following example demonstrates a practical scenario: in a transparent proxy environment, the inbound enables `sniffing` for domain / SNI routing, foreign domains go through the proxy, and other IP traffic goes directly. At the same time, `dns-out` refuses HTTPS records for foreign domains to reduce cases where clients obtain ECH configuration and affect plaintext SNI routing, forwards common MX, TXT, SRV, and similar queries to a specified upstream, and refuses AAAA queries because the proxy server has no IPv6 environment.
```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": {
// Omitted...
}
},
{
"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"
}
]
}
}
```
The example behaves as follows:
- `all-in` enables `sniffing` and uses `routeOnly: true`, allowing routing to split traffic based on sniffed HTTP, TLS, and QUIC target domains while preserving the original target address.
- UDP/TCP plaintext DNS queries from `all-in` to port 53 are routed to `dns-out`.
- For regular traffic, `geosite:geolocation-!cn` goes through `proxy`; traffic that does not match this domain rule automatically uses the first outbound, `direct`.
- HTTPS records with `qtype` `65` for domains in `geosite:geolocation-!cn` are explicitly refused, which can help with plaintext SNI-based routing.
- AAAA queries with `qtype` `28` for domains in `geosite:geolocation-!cn` are explicitly refused, which can be used to block IPv6 resolution for foreign domains.
- Queries with `qtype` `15-16,33` are allowed directly and forwarded to `1.1.1.1:53` according to the outbound configuration, using TCP as the transport.
- Queries that do not match any rule enter the built-in fallback logic: A and AAAA queries are imported into the built-in DNS module, while other query types are explicitly refused. The built-in DNS then queries upstream through `https+local://1.1.1.1/dns-query`, avoiding a loop.
Matches a list of domains. The syntax is the same as [`domain` in routing rules](../routing.md#ruleobject).
+6 -100
View File
@@ -73,111 +73,17 @@ DNS-запросы сопоставляются с правилами по по
- `direct`: напрямую пропускает запрос к целевому DNS-серверу. Если на уровне outbound также настроены `network`, `address` или `port`, запрос пересылается к измененной цели.
- `hijack`: направляет запрос во встроенный [DNS-сервер](../dns.md) для дальнейшей обработки. Это можно использовать для дополнительного разделения трафика через конфигурацию встроенного DNS. В настоящее время поддерживаются только записи A и AAAA.
- `drop`: напрямую отбрасывает запрос и не возвращает ответ.
- `reject`: возвращает явный отказ. По сравнению с `drop`, это может предотвратить слишком долгое ожидание DNS timeout приложениями.
- `reject`: возвращает явный отказ. По сравнению с `drop`, это может предотвратить долгое ожидание DNS timeout или повторные попытки у некоторых приложений.
> `qtype`: number | string
Сопоставляет типы DNS-запросов. Есть три формы:
Сопоставляет типы DNS-запросов. Формы записи:
- `"a-b"`: `a` и `b` — целые числа. Это закрытый интервал; правило срабатывает, когда тип запроса попадает в этот диапазон.
- `a`: `a` — целое число. Правило срабатывает, когда тип запроса равен `a`.
- Комбинация двух форм выше через запятую. Например: `"1,3,23-24"`.
- Целое число: конкретный тип запроса, например `"qtype": 1` соответствует запросу A, `"qtype": 28` — запросу AAAA.
- Строка: может быть строкой только из цифр, например `"qtype": "28"`; или диапазоном значений, например `"qtype": "5-10"` — это типы с 5 по 10, всего 6 типов. Можно использовать запятую для разделения, например `11,13,15-17` — это 5 типов: тип 11, тип 13 и типы с 15 по 17.
Распространенные номера типов можно посмотреть в [List of DNS record types](https://en.wikipedia.org/wiki/List_of_DNS_record_types).
Если не указано, сопоставляются все типы запросов.
Конкретные номера типов смотрите в [документации IANA](https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml).
> `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`, избегая зацикливания.
Сопоставляет список доменов. Синтаксис такой же, как у [`domain` в правилах routing](../routing.md#ruleobject).