Skip to content

fix: add IPv6 bootstrap DNS servers for IPv6-only uplinks#24

Merged
Itsusinn merged 1 commit into
mainfrom
fix/dns-ipv6-bootstrap
Jun 15, 2026
Merged

fix: add IPv6 bootstrap DNS servers for IPv6-only uplinks#24
Itsusinn merged 1 commit into
mainfrom
fix/dns-ipv6-bootstrap

Conversation

@Itsusinn

Copy link
Copy Markdown
Member

Problem

On IPv6-only mobile networks (e.g. China Mobile / 464XLAT cellular), the selected outbound interface has only a global IPv6 address and no IPv4 address. The built-in DNS bootstrap (default-nameserver) servers are all IPv4, so every query is routed out an interface that cannot send IPv4 — and times out:

initializing dns client: UDP: 114.114.114.114:53 bind: rmnet_data5 (v4: None, v6: 240a:...)
resolve error client="UDP#114.114.114.114:53" err=dns error: request timed out
resolve error client="UDP#8.8.8.8:53" err=dns error: request timed out
initializing DNS client DoT://dns.alidns.com:853 with error dns error: request timed out

With no bootstrap client available, the DoT nameservers can't resolve either, leaving the resolver empty. Every domain-based connection then fails while literal-IP traffic keeps working:

failed to establish remote connection [TCP] ... -> developers.google.cn:80,
error: dns error: no DNS clients available for query

Changes

In uniffi/clash-android-ffi/src/lib.rs, the built-in default_nameserver list:

  • Adds IPv6 bootstrap servers so resolution works on IPv6-only uplinks: AliDNS 2400:3200::1, 2400:3200:baba::1, and Google 2001:4860:4860::8888.
  • Switches the hardcoded defaults from Host::Domain to typed Host::Ipv4 / Host::Ipv6. This is required, not cosmetic: bootstrap clients are constructed with no parent resolver (father: None in clash-lib's EnhancedResolver::new), so a Host::Domain entry takes the resolve path and fails to initialize. The previous hardcoded IPv4 Host::Domain defaults were a latent bug that only worked when a profile supplied its own default-nameserver (which clash-rs pre-parses into typed Host::Ipv4).

Notes for reviewers

  • This only affects the default bootstrap list (used when a profile does not set default-nameserver). A profile that sets its own IPv4-only default-nameserver is still used verbatim and will need an IPv6 entry to work on IPv6-only networks.
  • The IPv6 toggle is unaffected — ProfileOverride.ipv6 already defaults to true and feeds both general.ipv6 and dns.ipv6.

Testing

cargo check -p clash-android-ffi --target aarch64-linux-android passes.

On IPv6-only mobile networks (e.g. 464XLAT cellular) the outbound
interface has no IPv4 address, so the IPv4-only default bootstrap
nameservers all time out. Every DNS client then fails to initialize,
leaving "no DNS clients available for query" and breaking all
domain-based connections while literal-IP traffic still works.

Add AliDNS/Google IPv6 servers to the built-in default-nameserver list
so bootstrap resolution works over IPv6.

Also switch the hardcoded defaults from Host::Domain to typed
Host::Ipv4/Host::Ipv6. Bootstrap clients are built with no parent
resolver, so a Host::Domain entry hits the resolve path and fails to
initialize; literal IPs must use the typed variants.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Itsusinn
Itsusinn merged commit 57cfe25 into main Jun 15, 2026
1 check passed
@Itsusinn
Itsusinn deleted the fix/dns-ipv6-bootstrap branch June 15, 2026 14:56
Itsusinn added a commit that referenced this pull request Jun 15, 2026
Commit #24 added IPv6 bootstrap nameservers for IPv6-only uplinks, but
gated them behind `if config.dns.default_nameserver.is_empty()`. When a
profile supplies its own `default-nameserver` (typically IPv4-only), the
else branch cloned that list verbatim and the IPv6 fallback was dropped.

On an IPv6-only uplink (e.g. 464XLAT cellular, interface has no IPv4
address) the IPv4 bootstrap servers are unreachable, so every bootstrap
query times out, the DoT main nameservers cannot be resolved, and the
resolver ends up with zero usable clients -> "no DNS clients available
for query" on every connection.

Always append the IPv6 bootstrap servers (with a dedup check) regardless
of whether the list came from defaults or the profile, so resolution can
still proceed on IPv6-only networks. Also factor the repeated NameServer
literals into a small udp_bootstrap closure.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant