Skip to content

fix(network): suppress external AAAA when host IPv6 egress is unavailable#637

Open
mdsalnikov wants to merge 2 commits intosuperradcompany:mainfrom
mdsalnikov:fix/607-filter-aaaa-without-ipv6-egress
Open

fix(network): suppress external AAAA when host IPv6 egress is unavailable#637
mdsalnikov wants to merge 2 commits intosuperradcompany:mainfrom
mdsalnikov:fix/607-filter-aaaa-without-ipv6-egress

Conversation

@mdsalnikov
Copy link
Copy Markdown

@mdsalnikov mdsalnikov commented Apr 29, 2026

Summary

Fixes #607

This PR prevents guests from receiving external AAAA DNS answers when the host cannot route external IPv6 traffic. In that case, the DNS forwarder now returns a successful NODATA response for external AAAA queries, allowing clients such as httpx.AsyncClient to fall back to IPv4.

The internal host.microsandbox.internal AAAA response is preserved.

Motivation

Async HTTP clients may attempt IPv6 connections when the guest receives AAAA records. On hosts without usable external IPv6 routing, those connections fail before the client reaches the working IPv4 path, causing errors such as:

httpx.RemoteProtocolError: Server disconnected without sending a response

Synchronous clients often avoid the issue by using IPv4 first, which is why the failure was client-dependent.

Changes

  • Probe host IPv6 egress once when building the DNS forwarder.
  • Suppress external AAAA responses with DNS NoError and no answers when IPv6 egress is unavailable.
  • Keep A records and host.microsandbox.internal AAAA behavior unchanged.
  • Add unit tests for:
    • NODATA response shape.
    • AAAA suppression decision logic.
    • IPv4 queries remaining unaffected.
    • Host alias AAAA remaining available.

Test Plan

  • cargo fmt --all --check
  • cargo build -p microsandbox-cli
  • cargo test --workspace
  • cargo clippy --workspace -- -D warnings
  • cargo doc --workspace --no-deps
  • pre-commit run --all-files
    • Passed all hooks except no-commit-to-branch, because the local branch was protected.
  • Manual local repro with signed msb:
    • requests client succeeds.
    • httpx.AsyncClient client succeeds.

View in Codesmith
Need help on this PR? Tag @codesmith with what you need.

  • Let Codesmith autofix CI failures and bot reviews

Comment thread crates/network/lib/dns/forwarder.rs Outdated
Comment on lines +546 to +551
let probe_addr = Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111);
TcpStream::connect_timeout(
&SocketAddr::new(IpAddr::V6(probe_addr), 443),
Duration::from_millis(250),
)
.is_ok()
Copy link
Copy Markdown
Member

@toksdotdev toksdotdev Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm. opening a TCP connection here increases latency significantly. plus, it makes us dependent on cloudflare, which isn't something we want.

i really do think there's more to the bug than is. for sanity, can you try running the following on your host:

curl -6 -m 5 -s -o /dev/null -w '%{http_code}\n' https://[2606:4700:4700::1111]/

trying to distill if this is some issue in our DNS interception layer, or somewhere else? if you're free, can you shoot me a message on discord so we can troubleshoot?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curl -6 -m 5 -s -o /dev/null -w '%{http_code}\n' https://[2606:4700:4700::1111]/
000

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced to 0x2001, 0x0db8, 0, 0, 0, 0, 0, 1 that is reserved specifically for documentation examples
And in this version it should be faster

Return DNS NODATA for external AAAA queries when the host cannot route IPv6, while preserving IPv4 fallback and internal host alias resolution.
@mdsalnikov mdsalnikov force-pushed the fix/607-filter-aaaa-without-ipv6-egress branch from a0d02c6 to 76a57b0 Compare April 30, 2026 08:42
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.

Bug: Async HTTP requests fail with RemoteProtocolError when --secret is provided

2 participants