mirror of
https://github.com/XTLS/Xray-docs-next.git
synced 2026-09-26 16:48:32 +03:00
DNS outbound: Add rules (matches qtype, domain, then action)
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@ Xray 内置的 DNS 模块,主要有三大用途:
|
||||
- 如 在 `freedom` 出站中,将 `domainStrategy` 设置为 `UseIP`, 由此出站发出的请求, 会先将域名通过内置服务器解析成 IP, 然后进行连接。
|
||||
- 如 在 `sockopt` 中,将 `domainStrategy` 设置为 `UseIP`, 此出站发起的系统连接,将先由内置服务器解析为 IP, 然后进行连接。
|
||||
|
||||
- 透明代理时劫持 DNS 流量;或直接对外暴露 53 端口充当递归 DNS 服务器。
|
||||
- TUN/透明代理时通过路由和 DNS 出站组合,以劫持 DNS 流量到此模块;或直接对外暴露 53 端口充当递归 DNS 服务器。
|
||||
|
||||
::: tip TIP 1
|
||||
DNS 服务器默认进入路由系统进行匹配,除非其包含 `+local` 在其中使用域名时,注意可能的回环问题,`hosts` 可能有帮助。
|
||||
|
||||
+146
-17
@@ -1,27 +1,38 @@
|
||||
# DNS
|
||||
|
||||
DNS 是一个出站协议,主要用于拦截和转发 DNS 查询。
|
||||
DNS 是一个出站协议,用于接收由 routing 送入的 DNS 查询,并按规则转发或处理。
|
||||
|
||||
此出站协议只能接收 DNS 流量(包含基于 UDP 和 TCP 协议的查询),其它类型的流量会导致错误。
|
||||
此出站只支持传统明文 DNS,即基于 UDP 和 TCP 的查询;DoH、DoT、DoQ 等非传统明文 DNS 不适用于此出站。常见场景是 TUN、透明代理或 `dokodemo-door` 接收到 DNS 流量后,再由 routing 将其分流到此出站。
|
||||
|
||||
在处理 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
|
||||
|
||||
@@ -35,20 +46,138 @@ DNS 是一个出站协议,主要用于拦截和转发 DNS 查询。
|
||||
|
||||
用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。
|
||||
|
||||
userLevel 的值,对应 [policy](../policy.md#policyobject) 中 `level` 的值。如不指定,默认为 0。
|
||||
`userLevel` 的值,对应 [policy](../policy.md#policyobject) 中 `level` 的值。如不指定,默认为 `0`。
|
||||
|
||||
> `nonIPQuery`: string
|
||||
> `rules`: \[[RuleObject](#ruleobject)\]
|
||||
|
||||
控制非 IP 查询(非 A 和 AAAA),`"drop"` 丢弃; `"skip"` 不由内置 DNS 服务器处理,将转发给目标; `"reject"` 返回一个 DNS reject 响应,直接显式拒绝请求,相比 `"drop"` 可以避免应用程序消耗过长时间等待 DNS 响应到超时。
|
||||
按顺序匹配 DNS 查询规则,并支持按 `qtype` 和 `domain` 进行细粒度控制。
|
||||
|
||||
默认值为 `"reject"`。
|
||||
若未命中任何规则,则使用内置兜底规则:A 和 AAAA 查询会被导入内置 DNS 模块,其它类型会被显式拒绝。
|
||||
|
||||
> `blockTypes`: array
|
||||
## RuleObject
|
||||
|
||||
为一个 int 数组,屏蔽数组中的查询类型,如 `"blockTypes": [65,28]` 表示屏蔽 type 65(HTTPS) 和 28(AAAA). 常见用途包括屏蔽 type 65 以阻止浏览器发起 ECH.
|
||||
```json
|
||||
{
|
||||
"action": "hijack",
|
||||
"qtype": 1,
|
||||
"domain": ["geosite:cn"]
|
||||
}
|
||||
```
|
||||
|
||||
由于 `nonIPQuery` 默认 drop 所有非 A 和 AAAA 查询, 所以需要将其设置为 skip 本选项才能进一步发挥作用。当然也可以不修改,单纯用来屏蔽 A 或者 AAAA 来屏蔽 IPv4/IPv6 查询,但非常不推荐那么做,建议在内置 DNS 的 `queryStrategy` 对相关内容进行设置。
|
||||
规则中的各匹配条件为与关系;省略某个条件时,表示对此条件不作限制。
|
||||
|
||||
注意:当只使用 `blockTypes` 屏蔽 A 或 AAAA 时, 如果 `nonIPQuery` 设置为了 `reject` 那么屏蔽方式也会是返回 DNS reject 而不是丢弃。
|
||||
> `action`: [ "direct" | "hijack" | "drop" | "reject" ]
|
||||
|
||||
## DNS 配置实例 <Badge text="WIP" type="warning"/>
|
||||
定义规则命中后的动作。
|
||||
|
||||
- `direct`: 直接放行到目标 DNS 服务器;若同时配置了出站级别的 `network`、`address` 或 `port`,则按改写后的目标继续转发。
|
||||
- `hijack`: 将查询导入内置的 [DNS 服务器](../dns.md) 继续处理,可用于按照内置 DNS 的配置进一步分流;目前仅支持 A 和 AAAA 记录。
|
||||
- `drop`: 直接丢弃请求,不返回响应。
|
||||
- `reject`: 返回显式拒绝响应,相比 `drop` 可以避免应用长时间等待 DNS 超时。
|
||||
|
||||
> `qtype`: number | string
|
||||
|
||||
匹配 DNS 查询类型,有三种形式:
|
||||
|
||||
- `"a-b"`:`a` 和 `b` 均为整数。这个范围是一个前后闭合区间,当查询类型落在此范围内时,此规则生效。
|
||||
- `a`:`a` 为整数。当查询类型为 `a` 时,此规则生效。
|
||||
- 以上两种形式的混合,以逗号 `,` 分隔。形如:`"1,3,23-24"`。
|
||||
|
||||
常见类型编号可参考 [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)。
|
||||
|
||||
省略时表示匹配所有查询类型。
|
||||
|
||||
> `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` 向上游发起查询,避免形成回环。
|
||||
|
||||
@@ -12,7 +12,7 @@ The built-in DNS module in Xray has three main purposes:
|
||||
- For example, in a `freedom` outbound, if `domainStrategy` is set to `UseIP`, requests sent from this outbound will first resolve the domain to an IP using the built-in server before connecting.
|
||||
- For example, in `sockopt`, if `domainStrategy` is set to `UseIP`, system connections initiated by this outbound will first resolve to an IP using the built-in server before connecting.
|
||||
|
||||
- **DNS Traffic Hijacking (Transparent Proxy) or Acting as a Recursive DNS Server:** Directly exposing port 53 to serve as a DNS server.
|
||||
- **TUN/Transparent Proxy DNS Traffic Hijacking:** Combines routing with the DNS outbound to hijack DNS traffic into this module; or directly exposes port 53 to act as a recursive DNS server.
|
||||
|
||||
::: tip TIP 1
|
||||
The DNS server enters the routing system for matching by default unless it contains `+local`. When using domain names within it, be aware of potential routing loops; `hosts` may help.
|
||||
|
||||
+149
-20
@@ -1,54 +1,183 @@
|
||||
# DNS
|
||||
|
||||
DNS is an outbound protocol, mainly used to intercept and forward DNS queries.
|
||||
DNS is an outbound protocol used to receive DNS queries sent in by routing, then forward or process them according to rules.
|
||||
|
||||
This outbound protocol can only receive DNS traffic (including queries based on UDP and TCP protocols); other types of traffic will cause errors.
|
||||
This outbound only supports traditional plaintext DNS queries over UDP and TCP; non-plaintext DNS protocols such as DoH, DoT, and DoQ are not applicable to this outbound. Common scenarios include TUN, transparent proxy, or `dokodemo-door` receiving DNS traffic and then routing sending that traffic to this outbound.
|
||||
|
||||
When processing DNS queries, this outbound protocol forwards IP queries (i.e., A and AAAA) to the built-in [DNS server](../dns.md). For other types of query traffic, see `nonIPQuery` below.
|
||||
It can allow queries to the target DNS server, `hijack` them to the built-in [DNS server](../dns.md) for further processing, drop them, or explicitly refuse them according to rules. It can also rewrite the target address, port, and transport protocol.
|
||||
|
||||
## 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"
|
||||
The example above only demonstrates the field syntax. See the full example below for a complete configuration.
|
||||
|
||||
Modifies the transport layer protocol for DNS traffic. Optional values are `"tcp"` and `"udp"`. When unspecified, the source transport method remains unchanged.
|
||||
> `network`: [ "tcp" | "udp" ]
|
||||
|
||||
Modifies the transport protocol used for DNS traffic. Available values are `"tcp"` and `"udp"`. If omitted, the original transport method is preserved.
|
||||
|
||||
> `address`: address
|
||||
|
||||
Modifies the DNS server address. When unspecified, the address specified in the source remains unchanged.
|
||||
Modifies the DNS server address. If omitted, the address specified by the source is preserved.
|
||||
|
||||
> `port`: number
|
||||
|
||||
Modifies the DNS server port. When unspecified, the port specified in the source remains unchanged.
|
||||
Modifies the DNS server port. If omitted, the port specified by the source is preserved.
|
||||
|
||||
> `userLevel`: number
|
||||
|
||||
User level. Connections will use the [Local Policy](../policy.md#levelpolicyobject) corresponding to this user level.
|
||||
User level. Connections will use the [local policy](../policy.md#levelpolicyobject) corresponding to this user level.
|
||||
|
||||
The value of `userLevel` corresponds to the value of `level` in [policy](../policy.md#policyobject). If not specified, it defaults to 0.
|
||||
The value of `userLevel` corresponds to the `level` value in [policy](../policy.md#policyobject). If omitted, it defaults to `0`.
|
||||
|
||||
> `nonIPQuery`: string
|
||||
> `rules`: \[[RuleObject](#ruleobject)\]
|
||||
|
||||
Controls non-IP queries (non-A and non-AAAA). `"drop"` means discard; `"skip"` means it is not processed by the built-in DNS server and is forwarded to the destination; `"reject"` returns a DNS reject response, explicitly refusing the request immediately. Compared to `"drop"`, this avoids applications waiting too long for a DNS response until timeout.
|
||||
Matches DNS query rules in order, and supports fine-grained control by `qtype` and `domain`.
|
||||
|
||||
The default value is `"reject"`.
|
||||
If no rule is matched, the built-in fallback rule is used: A and AAAA queries are imported into the built-in DNS module, while other query types are explicitly refused.
|
||||
|
||||
> `blockTypes`: array
|
||||
## RuleObject
|
||||
|
||||
An integer array used to block query types listed in the array. For example, `"blockTypes": [65,28]` means blocking type 65 (HTTPS) and 28 (AAAA). Common uses include blocking type 65 to prevent browsers from initiating ECH.
|
||||
```json
|
||||
{
|
||||
"action": "hijack",
|
||||
"qtype": 1,
|
||||
"domain": ["geosite:cn"]
|
||||
}
|
||||
```
|
||||
|
||||
Since `nonIPQuery` drops all non-A and non-AAAA queries by default, this option requires `nonIPQuery` to be set to `skip` to take further effect on other types. Of course, you can also use it solely to block A or AAAA (IPv4/IPv6 queries), but this is highly discouraged. It is recommended to configure `queryStrategy` in the built-in DNS settings for relevant content instead.
|
||||
All matching conditions in a rule are combined with AND logic. If a condition is omitted, that condition is not restricted.
|
||||
|
||||
Note: When using `blockTypes` to block only A or AAAA, if `nonIPQuery` is set to `reject`, the blocking method will also be to return a DNS reject response instead of dropping.
|
||||
> `action`: [ "direct" | "hijack" | "drop" | "reject" ]
|
||||
|
||||
## DNS Configuration Examples <Badge text="WIP" type="warning"/>
|
||||
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.
|
||||
|
||||
> `qtype`: number | string
|
||||
|
||||
Matches DNS query types. It has three forms:
|
||||
|
||||
- `"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"`.
|
||||
|
||||
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.
|
||||
|
||||
> `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.
|
||||
|
||||
@@ -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