Refine domainStrategy

This commit is contained in:
Meow
2026-09-12 06:38:54 +08:00
parent ab204432b9
commit 46c680b71b
9 changed files with 90 additions and 42 deletions
+14 -5
View File
@@ -4,20 +4,29 @@
Xray 内置的 DNS 模块,主要有三大用途:
- 在路由阶段,解析域名为 IP, 并且根据域名解析得到的 IP 进行规则匹配以分流。<br>
是否解析域名用以分流,与路由模块中 `routing.domainStrategy` 的值有关,只有在设置以下两种值时,才会使用内置 DNS 服务器进行 DNS 查询:
- "IPIfNonMatch", 请求目标是域名且不附带 IP 时,先用其它条件进行一轮匹配,若本轮没有命中任何一条路由规则,则对这个域名使用内置 DNS 服务器进行 DNS 查询,并且使用查询返回的 IP 地址再重新进行一轮路由匹配。
- "IPOnDemand", 请求目标是域名且不附带 IP 时,当路由匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配。
- 在路由阶段,解析域名为 IP, 并且根据域名解析得到的 IP 进行规则匹配以分流。
::: details 详细说明
是否解析域名用以 IP 分流,取决于 `routing.domainStrategy` 的值,只有在设置以下两种值时,才有可能使用内置 DNS 服务器进行 DNS 查询:
- `"IPIfNonMatch"`:第一轮路由匹配未命中任何规则时,只要存在包含 `ip` 条件的规则且目标包含域名,就会使用内置 DNS 解析域名。
- `"IPOnDemand"`:只要目标包含域名,并遇到包含 `ip` 条件的规则,就会使用内置 DNS 解析域名。
- 在出站阶段,解析目标域名,用于连接或发送给远端代理服务器:
:::
- 在出站阶段,解析目标域名,用于连接或发送给远端代理服务器。
::: details 详细说明
- 如在 VLESS 出站中,将 `targetStrategy` 设置为 `UseIP`,会先通过本地的内置 DNS 模块解析被代理请求的目标域名,再将解析得到的 IP 发给远端代理服务器。
- 如在 VLESS 出站中,将 `sockopt.domainStrategy` 设置为 `UseIP`,会通过内置 DNS 模块解析 VLESS 服务器的域名,再连接解析得到的 IP。
- 如在 Freedom 出站中,将 `sockopt.domainStrategy` 设置为 `UseIP`,会通过内置 DNS 模块解析请求的目标域名,再连接解析得到的 IP。
- 如在 Wireguard 出站中,协议不允许传递域名作为目标,可选用内置 DNS 模块解析为 IP。
:::
- TUN/透明代理时通过路由和 DNS 出站组合,以劫持 DNS 流量到此模块;或利用 [Tunnel](./inbounds/tunnel.md) 直接对外暴露 53 端口充当递归 DNS 服务器。
::: details 详细说明
- 只支持最基本的 IP 查询(A 和 AAAA 记录),CNAME 记录将会重复查询直至返回 A/AAAA 记录为止。其它查询不会进入内置 DNS 服务器,而是根据你在出站中的配置可以丢弃或透传给其它服务器。
:::
## DNS 处理流程
域名将先执行 Hosts 映射检查(详见 `hosts` 字段),若没有查出需要的 IP,则继续使用 DNS 服务器进行查询。
+5 -7
View File
@@ -24,15 +24,13 @@
域名解析策略,根据不同的设置使用不同的策略。
- `"AsIs"`:不进行额外操作,使用目标地址里的域名或者 sniff 到的域名。默认值;
- `"IPIfNonMatch"`:一整轮匹配结束后,当没有命中任何规则时,将域名解析成 IP 再次进行二次匹配;
- `"IPOnDemand"`:在开始进行匹配前,直接先将域名解析为 IP 进行匹配;
- `"AsIs"`:不进行 DNS 解析。默认值;
- `"IPIfNonMatch"`:先不进行域名解析,若一整轮匹配结束后未命中任何规则且目标包含域名,则重新开始第二轮匹配;第二轮遇到包含 `ip` 条件的规则时,使用内置 DNS 将域名解析为 IP 后进行匹配;
- `"IPOnDemand"`:若目标包含域名,遇到包含 `ip` 条件的规则时,使用内置 DNS 将域名解析为 IP 后进行匹配;若解析失败,则使用原始目标 IP 进行匹配;
实际解析行为会被推迟到第一次遇到 IP 规则以降低延迟。结果将同时包含 IPv4 与 IPv6(你可以在内置 DNS 的 `queryStrategy` 进行二次限制) 域名解析出多条 IP 时每条规则将依次尝试全部 IP,只要任意一 IP 符合要求即视为命中规则。
解析结果将同时包含 IPv4 与 IPv6(可通过内置 DNS 的 `queryStrategy` 进一步限制)。域名解析出多个 IP 时,每条规则会依次尝试所有 IP;任一 IP 符合条件,即视为命中该规则。
当开启 sniff + routeOnly 使路由系统可以同时看见 IP 和域名时,如果发生上述的解析,路由系统只能看到由域名解析出的 IP 而无法看见原始目标 IP, 除非解析失败。
当存在两个域名时(目标域名 + sniff 结果), 无论是用于解析还是用于域名匹配,sniff 结果的优先级总是更高。
原始目标可能是 IP,也可能是域名。当开启 [`sniffing`](./inbound.md#sniffingobject) 且启用 `routeOnly` 时,路由系统除了原始目标外,还能看到嗅探得到的域名。因此,即使没有进行 DNS 解析,只要原始目标中已有 IP,路由系统仍可使用该 IP 进行规则匹配。当原始目标域名与嗅探结果同时存在时,无论用于 DNS 解析还是域名匹配,嗅探结果的优先级始终更高。
无论解析与否,路由系统不会影响真正目标地址,请求的目标仍然是原始目标。
+11 -2
View File
@@ -97,7 +97,12 @@ Sockopt 用于配置底层网络行为。
默认值 `"AsIs"`。
当出站需要连接的地址为域名时,此选项控制域名的解析方式:
此选项控制出站建立底层连接时,对连接目标域名的解析方式。
- VLESS、VMess、Trojan 等代理出站:底层连接的目标是代理服务器,因此此选项控制代理服务器域名的解析。被代理请求中的目标域名是否在本地解析,由出站的 [`targetStrategy`](../outbound.md#outboundobject) 控制。
- Freedom 出站:底层连接的目标就是请求的目标,因此此选项控制请求目标域名的解析。
各策略的含义如下:
- 当使用 `"AsIs"` 时,Xray 将域名交给 Go 按操作系统 DNS 设置解析并连接。通常 TCP 优先尝试 IPv6,并在连接不顺利时尝试 IPv4;UDP 则优先使用 IPv4。
@@ -106,7 +111,9 @@ Sockopt 用于配置底层网络行为。
使用纯 Go 编译的 Xray 时,地址按照 RFC 6724 的精简规则排序,条件相当时通常优先 IPv6,不读取 `/etc/gai.conf`。Xray 官方 release 版大多采用这种方式;部分操作系统或下游项目编译的版本行为可能略有不同不再赘述。参见 [Go 地址排序实现](https://go.dev/src/net/addrselect.go)。
UDP 优先选择解析结果中的 IPv4 地址,没有 IPv4 时才选择 IPv6;发送失败不会自动切换到另一地址族。`Use` 策略回退到 `AsIs` 时也遵循此行为。参见 [Go UDP 地址选择实现](https://go.dev/src/net/ipsock.go)。
UDP 优先选择解析结果中的 IPv4 地址,没有 IPv4 时才选择 IPv6;发送失败不会自动切换到另一地址族。参见 [Go UDP 地址选择实现](https://go.dev/src/net/ipsock.go)。
注意,`Use` 策略可能因解析失败或结果不符合要求而回退到 `AsIs`,此时 TCP 和 UDP 均遵循上述行为。
:::
- 当填写其他值时,将使用 Xray [内置 DNS 模块](../dns.md) 进行解析。若未配置 `DNSObject`,则使用系统 DNS。若有多个符合条件的 IP 地址,默认随机选择一个;TCP 启用 `sockopt.happyEyeballs` 后则通过竞速选择。
@@ -136,6 +143,8 @@ Sockopt 用于配置底层网络行为。
8. 问题出现。步骤 3 中连接的建立,需要等待步骤 7 中的查询结果;步骤 7 完成查询,需要等待步骤 3 中的连接完全建立。
9. Good Game!
Freedom 直连也可能出现同样的问题:若连接 DNS 服务器前,需要通过该服务器解析其自身域名,就会形成循环依赖。
解决方案:
- 改内置 DNS 服务器的分流。