yiguodevOneXray 开发者
GitHub·2026.09.23 12:22:05(UTC+8)

yiguodev:Xray 本地 DoH 上游主机名可能绕回被接管的系统 DNS

在 PR 6773 复测中,yiguodev 指出 autoSystemDNS + TUN/53 走 DNS outbound、上游为 https+local 时,本地 DoH 可能以主机名 DialSystem,而预检未识别该间接依赖;Linux ARM64 实测约 4 秒超时。完整探针说明见原文。

作者原文@yiguodev

Thanks for the update. I rechecked 8f7c97d0: the mixed-localhost refusal 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 autoSystemDNS enabled and TUN/53 routed to the DNS outbound, consider an upstream such as https+local://dns.google/dns-query. The local DoH path calls DialSystem with the upstream hostname, so establishing the connection can require system DNS. The current MayUseSystemResolver() detects the empty/explicit-LocalNameServer cases, 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 -> resolved

This can prevent resolution through that upstream. Successful resolvectl calls 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 .invalid upstream hostname, without starting Core/TUN. The command runner only recorded calls; Go's resolver Dial was 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

  1. Extend the refusal check for this bootstrap case and add regression coverage; or
  2. 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.