Route the full tunnel in tethering compatibility mode (#699) - #700
Merged
Conversation
Before the static VPN route set landed, the tun carried a plain 0.0.0.0/0 route, so tethered traffic — including the downstream subnets and the DHCP broadcast — went through TrackerControl. On devices whose own tethering path is broken, that is what made tethering work at all. The split-tunnel route set removed the default route and, with it, the subnet/tethering/lan preferences, leaving affected users with no way back other than downgrading. Reuse the existing (opt-in, default off) tethering compatibility mode: alongside the TCP MSS clamp it now installs a single 0.0.0.0/0 route, restoring the previous behaviour for the users who need it while the split-tunnel route set stays the default for everyone else. WireGuard keeps precedence — a full tunnel would hand LAN and reserved ranges to the peer, which drops them — so an active profile's AllowedIPs still decide the routes. On Android 13+ the carrier ePDG excludeRoute() calls still apply on top of the default route, so Wi-Fi calling is unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FhD7ETjNc5qb5hSw9taYtS
kasnder
marked this pull request as ready for review
August 1, 2026 22:27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #699 — tethering worked on 2026.04.03 and stopped on 2026.07.27; downgrading restores it. The reporter's device has a broken tethering path of its own, and TrackerControl was what made tethering work.
Why it regressed
68fcd531(#546, 2026-04-06, first released in 2026.04.27 — three days after the reporter's last working build) replaced the tun's catch-all route with the static split-tunnel route set:subnetdefaulted tofalse, sogetBuilder()fell through tobuilder.addRoute("0.0.0.0", 0)and the tun captured everything.VpnRoutes.getRoutes()covers public IPv4 only. Permanently excluded are10/8,172.16/12,192.168/16(which contains the tethering downstreams 192.168.42/43/44/49),100.64/10,169.254/16and224.0.0.0/3— the last of which contains the255.255.255.255DHCP broadcast thatcheck_dhcp()answers for tethered clients.The same commit also deleted the
subnet,tetheringandlanpreferences, so there is no longer any toggle that restores the old behaviour — which is why downgrading is the reporter's only recourse.The likely mechanism is that some devices only forward tethered traffic into the tun while the VPN carries a real default route. Without one, tethering falls back to the device's own path, which on such devices is broken.
What this changes
The opt-in, default-off "Tethering compatibility mode" (added for #478, previously MSS clamp only) now also installs a single
0.0.0.0/0route, restoring the pre-2026.04.27 behaviour for users who need it. The split-tunnel route set stays the default for everyone else.VpnRoutes.getTetheringRoutes()— the full-tunnel route list, with the rationale documented.ServiceSinkhole.getBuilder()— picks it when the mode is on. WireGuard keeps precedence: a full tunnel would hand LAN and reserved ranges to the peer, which drops them, so an active profile'sAllowedIPsstill decide the routes (Allow traffic towards private internal endpoints via WireGuard #593), and the override is logged when it applies.excludeRoute()calls still apply on top of the default route, so Wi-Fi calling is unaffected.VpnRoutesTestcovers the new route list and that it does not disturb the cached default one.No new preference — this reuses the switch that already exists, and it is a breakage-recovery control rather than a general firewall knob.
Testing
Not built or run: this environment has no Android SDK, so
:app:testGithubDebugUnitTestcould not be executed here. CI should cover compilation and the unit tests.Still needs on-device confirmation from the reporter that enabling the mode restores tethering on 2026.07.27 — the route mechanism above is inferred from the change history, not yet observed on an affected device.
Generated by Claude Code