Skip to content

fix: always append IPv6 bootstrap DNS servers#25

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

fix: always append IPv6 bootstrap DNS servers#25
Itsusinn merged 1 commit into
mainfrom
fix/ipv6-bootstrap-always-append

Conversation

@Itsusinn

Copy link
Copy Markdown
Member

Problem

On an IPv6-only uplink (e.g. 464XLAT cellular, where the network interface has no IPv4 address), the app fails to resolve any domain — every connection logs dns error: no DNS clients available for query.

Trace from a real device log (rmnet_data5 has v4: None, only a global IPv6 address):

  1. DNS bootstrap (default_nameserver) runs with IPv4-only servers (114.114.114.114, 8.8.8.8) → both unreachable → every bootstrap query times out.
  2. Because bootstrap failed, the DoT main nameservers (dns.alidns.com:853, dot.pub:853) can't be resolved → initializing DNS client ... with error dns error: request timed out.
  3. all components initialized, but with zero usable DNS clientsno DNS clients available for query on every subsequent connection.

Why #24 didn't cover this

#24 added IPv6 bootstrap servers, but only inside the if config.dns.default_nameserver.is_empty() branch. This device's profile supplies its own default-nameserver (the IPv4-only 114.114.114.114 value — not present anywhere in our code — confirms it), so it took the else branch and the IPv6 fallback was silently dropped.

Change

  • Always append the IPv6 bootstrap servers (AliDNS 2400:3200::1 / 2400:3200:baba::1, Google 2001:4860:4860::8888) to default_nameserver, whether the list came from the built-in defaults or from the profile. A dedup check (url::Host derives PartialEq) avoids duplicates.
  • Factored the repeated NameServer { … } literals into a small udp_bootstrap closure.

Reviewer notes

  • Type-correct: the dedup compare compiles because Host is url::Host (derives PartialEq); the closure borrow in .any() ends before the push move.
  • Not yet verified with an Android NDK build / on-device test on an IPv6-only network — would appreciate a check before release. Expected behavior: bootstrap also tries the IPv6 clients and at least dns.alidns.com:853 initializes successfully.
  • Out of scope: a profile supplying its own IPv4-only nameserver (the main resolvers, not bootstrap) would still fail on IPv6-only. Not the case here (the main resolvers are DoT domains, which resolve fine once bootstrap works).

🤖 Generated with Claude Code

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>
@Itsusinn
Itsusinn merged commit ac85128 into main Jun 15, 2026
1 check passed
@Itsusinn
Itsusinn deleted the fix/ipv6-bootstrap-always-append branch June 25, 2026 19:32
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