yiguodev:Xray 本地 DoH 上游的主机名引导解析可能绕回被接管的系统 DNS,实测 4 秒超时
在 Xray-core PR 6773 的复测说明中表示,混合 localhost 的拒绝接管与两条回滚错误信息的保留已通过追加验证。在 autoSystemDNS 开启、TUN/53 走 DNS outbound、上游为 https+local://dns.google/dns-query 时,本地 DoH 路径会以该上游主机名调用 DialSystem,而 MayUseSystemResolver() 未识别这一间接依赖,预检仍会放行。他在 Linux ARM64 / systemd-resolved 259 上用两组各 8 个用例、共 16 个全新 Core 与 TUN 实例实测:接口绑定并启用 DNS 接管后该上游查询超时约 4.0 秒,仅为该主机名补一条系统 /etc/hosts 记录后即恢复(约 0.22 秒);抓包显示引导查询先到系统存根再到 TUN DNS 地址。他建议本 PR 先只记录「上游解析(含引导)必须独立于被重定向的解析路径」这一配置限制,运行期改进留作后续,方向是在 DNS 查询拨号路径使用带接口绑定的 Go 默认解析器,并强调这仅为建议、未经本次实验实现或验证。他另说明约 4 秒是客户端超时上限,实验只验证 TUN 下的 DNS。
作者原文@yiguodevThanks for the update. I rechecked
8f7c97d0: the mixed-localhostrefusal and preservation of both rollback error messages pass the additional probes. The source-port-independent requirement is also clear now.One additional configuration limitation: local DoH bootstrap
With
autoSystemDNSenabled and TUN/53 routed to the DNS outbound, consider an upstream such ashttps+local://dns.google/dns-query. The local DoH path callsDialSystemwith the upstream hostname, so establishing the connection can require system DNS. The currentMayUseSystemResolver()detects the empty/explicit-LocalNameServercases, but not this bootstrap dependency, and preflight accepts it.If that bootstrap lookup is itself redirected through the same DNS outbound, with no independent way to resolve the upstream hostname, the dependency becomes:
resolved -> TUN -> DNS outbound -> DoH hostname bootstrap -> resolvedThis can prevent resolution through that upstream. Successful
resolvectlcalls would not trigger the configuration-failure rollback merely because later DNS queries fail.Evidence limit: I used real Core/router/DNS/DoH objects with a reserved
.invalidupstream hostname, without starting Core/TUN. The command runner only recorded calls; Go's resolverDialwas intercepted to return a controlled error without sending packets. In all three runs, the dependency check returned false, the takeover path attempted three recorded commands, and the actual DoH lookup reached the system-resolver hook. This confirms the missed dependency, not a live reproduction of post-takeover DNS failure; no host DNS was changed.Either handling is reasonable
- Extend the refusal check for this bootstrap case and add regression coverage; or
- Keep the limited preflight and explicitly document this as an unsupported configuration: upstream resolution, including bootstrap, must remain independent of the resolver path being redirected. Clarify that the check detects specific known cases rather than all indirect dependencies. A warm cache or existing connection is not a lasting guarantee after expiry/reconnection.
My earlier wording about refusing system-resolver dependencies should not imply that this PR needs a general dependency analyzer. I would not require a runtime fix before merging if this is made an explicit configuration limitation. I'll leave that choice to you.