Skip to content

Fix IPv6 fake-IP routing for dual-stack DNS#545

Open
atavism wants to merge 2 commits into
mainfrom
atavism/issue-3649
Open

Fix IPv6 fake-IP routing for dual-stack DNS#545
atavism wants to merge 2 commits into
mainfrom
atavism/issue-3649

Conversation

@atavism

@atavism atavism commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Proposed fix for https://github.com/getlantern/engineering/issues/3649

Routes both A and AAAA queries through dual-stack fake-IP so domain rules can handle IPv6 DNS results before the IPv6 reject fallback.

Server DNS overrides also keep this fake-IP fallback

Summary by CodeRabbit

  • New Features
    • Added dual-stack fake-IP DNS handling so both IPv4 (A) and IPv6 (AAAA) queries can be routed consistently.
    • DNS fallback is applied without changing the existing DNS rules structure.
  • Bug Fixes
    • Improved DNS merge behavior to avoid unintended mutation and to apply the correct fallback when overwriting DNS settings.
    • Refined IPv6 rejection ordering to block proxied IPv6 more reliably.
  • Documentation
    • Updated routing-order guidance to clarify rule evaluation placement.
  • Tests
    • Expanded coverage for dual-stack fake-IP DNS behavior and updated IPv6 ordering assertions.

Copilot AI review requested due to automatic review settings June 30, 2026 14:40
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0017b63e-18af-4cbf-873c-4690cfb45b44

📥 Commits

Reviewing files that changed from the base of the PR and between dc3d17e and 4142301.

📒 Files selected for processing (4)
  • vpn/boxoptions.go
  • vpn/boxoptions_test.go
  • vpn/dnsoptions.go
  • vpn/dnsoptions_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • vpn/dnsoptions_test.go
  • vpn/boxoptions_test.go
  • vpn/boxoptions.go
  • vpn/dnsoptions.go

📝 Walkthrough

Walkthrough

Refactors fake-IP DNS to dual-stack: adds IPv4/IPv6 range constants and a dedicated fakeIPServer(), rewrites buildDNSRules and fakeIPRule to route both A and AAAA queries, adds addFakeIPDNSFallback/setFakeIPServer/hasAddressFakeIPRule helpers, and switches mergeAndCollectTags from AAAA suppression to the new fallback path. Comments and tests are updated accordingly.

Changes

Dual-stack fake-IP DNS refactor

Layer / File(s) Summary
Dual-stack fake-IP constants, server, and routing rules
vpn/dnsoptions.go
Adds fakeIPServerTag, fakeIPv4Range, fakeIPv6Range constants; replaces inline server construction with fakeIPServer() configuring both ranges; rewrites buildDNSRules to return fakeIPRule routing both A and AAAA; adds addFakeIPDNSFallback, setFakeIPServer, and hasAddressFakeIPRule helpers.
mergeAndCollectTags DNS overwrite and comment updates
vpn/boxoptions.go
Switches mergeAndCollectTags from prepending suppressAAAARule to cloning src DNS and calling addFakeIPDNSFallback; updates inline comments in baseRoutingRules and rejectIPv6Rule to reflect non-fake-IP IPv6 rejection semantics.
Tests
vpn/dnsoptions_test.go, vpn/boxoptions_test.go
Removes TestBuildDNSRules_SuppressesAAAA; adds TestBuildDNSServers_FakeIPDualStack, TestBuildDNSRules_RoutesAddressQueriesToFakeIP, and TestMergeAndCollectTags_AddsDualStackFakeIPDNS with helpers asserting dual-stack configuration and no source mutation; updates assertion messages in TestBuildOptions_RejectsIPv6WhenCaptured.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop hop, the DNS got a glow-up today,
Both A and AAAA now routed the fake-IP way!
No more suppressing the IPv6 trail,
Dual-stack ranges ensure we don't fail.
The rabbit rejoices—packets find their place,
Through IPv4 and IPv6 address space! 🌐

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: IPv6 fake-IP routing now works for dual-stack DNS with A and AAAA handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch atavism/issue-3649

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates Radiance’s sing-box DNS and routing configuration so both A and AAAA DNS answers can be represented via fake-IP, preserving domain context for routing decisions in dual-stack scenarios before IPv6-reject fallback behavior applies.

Changes:

  • Extend the fake-IP DNS server to dual-stack (IPv4 + IPv6) and route both A/AAAA DNS queries through it.
  • Add logic to ensure server-provided DNS overrides still get a dual-stack fake-IP server and a fallback rule appended after server rules.
  • Update and add tests covering dual-stack fake-IP server configuration and merge behavior for server DNS overrides.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
vpn/dnsoptions.go Adds dual-stack fake-IP server/rule helpers and fallback injection for server DNS overrides.
vpn/dnsoptions_test.go Updates DNS options tests to validate dual-stack fake-IP behavior and removal of AAAA suppression.
vpn/boxoptions.go Adjusts DNS merge behavior to preserve server options and append fake-IP fallback; updates related comments.
vpn/boxoptions_test.go Adds coverage ensuring merge preserves server DNS rule ordering while adding fake-IP dual-stack fallback.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread vpn/boxoptions.go Outdated
Comment thread vpn/boxoptions.go Outdated
Comment thread vpn/dnsoptions.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
vpn/dnsoptions_test.go (2)

152-197: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add Go doc comments above the new functions.

These new package-level functions are missing doc comments, and the helper contracts are not obvious from the names alone. As per coding guidelines, **/*.go: Use Go doc comments (// Foo ...) for exported identifiers and any unexported ones with non-obvious contracts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vpn/dnsoptions_test.go` around lines 152 - 197, Add Go doc comments above the
new helper/test functions in dnsoptions_test.go, especially
TestBuildDNSServers_FakeIPDualStack,
TestBuildDNSRules_RoutesAddressQueriesToFakeIP, requireFakeIPServer, and
requireDualStackFakeIPServer. Use short descriptive comments that explain each
function’s contract so the purpose is clear from the identifier and comment
together.

Source: Coding guidelines


178-184: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Match fakeIPServerTag when selecting the fake-IP server.

This helper returns the first DNSTypeFakeIP entry, so it will start failing against the wrong server as soon as another fake-IP server is added. Filtering by tag here keeps the test aligned with the routing contract asserted below.

Suggested change
 func requireFakeIPServer(t *testing.T, servers []option.DNSServerOptions) option.DNSServerOptions {
 	t.Helper()
 	idx := slices.IndexFunc(servers, func(server option.DNSServerOptions) bool {
-		return server.Type == constant.DNSTypeFakeIP
+		return server.Type == constant.DNSTypeFakeIP && server.Tag == fakeIPServerTag
 	})
 	require.NotEqual(t, -1, idx, "expected a fake-IP DNS server")
 	return servers[idx]
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vpn/dnsoptions_test.go` around lines 178 - 184, The requireFakeIPServer
helper currently selects the first DNSTypeFakeIP entry, which can pick the wrong
server once multiple fake-IP servers exist. Update the selection logic in
requireFakeIPServer to match the fakeIPServerTag on DNSServerOptions so it
returns the tagged fake-IP server that the routing tests expect.
vpn/boxoptions_test.go (1)

211-211: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a Go doc comment above the new test function.

As per coding guidelines, **/*.go: Use Go doc comments (// Foo ...) for exported identifiers and any unexported ones with non-obvious contracts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vpn/boxoptions_test.go` at line 211, Add a Go doc comment directly above the
new test function TestMergeAndCollectTags_AddsDualStackFakeIPDNS. The issue is
that this test has no comment even though it follows a non-obvious contract, so
update the declaration in boxoptions_test.go with a brief descriptive Go-style
comment that explains what the test covers.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@vpn/boxoptions_test.go`:
- Around line 229-230: The tests around mergeAndCollectTags only verify slice
lengths, so they can still pass if src.DNS.Servers or src.DNS.Rules are mutated
in place. Update the assertions in boxoptions_test.go to check the original
source values remain unchanged after calling mergeAndCollectTags, using the
existing src.DNS.Servers and src.DNS.Rules setup plus the corresponding
destination result checks, so the “must not mutate source” contract is actually
covered.

---

Nitpick comments:
In `@vpn/boxoptions_test.go`:
- Line 211: Add a Go doc comment directly above the new test function
TestMergeAndCollectTags_AddsDualStackFakeIPDNS. The issue is that this test has
no comment even though it follows a non-obvious contract, so update the
declaration in boxoptions_test.go with a brief descriptive Go-style comment that
explains what the test covers.

In `@vpn/dnsoptions_test.go`:
- Around line 152-197: Add Go doc comments above the new helper/test functions
in dnsoptions_test.go, especially TestBuildDNSServers_FakeIPDualStack,
TestBuildDNSRules_RoutesAddressQueriesToFakeIP, requireFakeIPServer, and
requireDualStackFakeIPServer. Use short descriptive comments that explain each
function’s contract so the purpose is clear from the identifier and comment
together.
- Around line 178-184: The requireFakeIPServer helper currently selects the
first DNSTypeFakeIP entry, which can pick the wrong server once multiple fake-IP
servers exist. Update the selection logic in requireFakeIPServer to match the
fakeIPServerTag on DNSServerOptions so it returns the tagged fake-IP server that
the routing tests expect.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0ee66b01-b4a1-492b-bcbc-9491d0821075

📥 Commits

Reviewing files that changed from the base of the PR and between a8b1916 and dc3d17e.

📒 Files selected for processing (4)
  • vpn/boxoptions.go
  • vpn/boxoptions_test.go
  • vpn/dnsoptions.go
  • vpn/dnsoptions_test.go

Comment thread vpn/boxoptions_test.go Outdated
@atavism atavism requested a review from garmr-ulfr June 30, 2026 16:49
@garmr-ulfr

Copy link
Copy Markdown
Collaborator

Routes both A and AAAA queries through dual-stack fake-IP so domain rules can handle IPv6 DNS results before the IPv6 reject fallback.

We need to reject IPv6 DNS queries as well. Since the fakeip server doesn't actually do any lookup, sing-box sets the request destination to the fully-qualified domain, so it won't be caught by the IPv6 reject routing rule.

Server DNS overrides also keep this fake-IP fallback

The sing-box options in the config should be treated as the authoritative source. DNS and routing options should be applied as specified, unless the options depend on something the server cannot know; such as whether the client has IPv6 or not. If the fakeip server and rule aren't included, that would be intentional or a bug in lantern-cloud.

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.

3 participants