Repository navigation
fix: restore usable iOS routing and explicit UDP policy - #41
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6999f4c01d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .and_then(|v| parse_bool_env(&v)) | ||
| }) | ||
| .unwrap_or(true); | ||
| .unwrap_or(false); |
There was a problem hiding this comment.
Update the generated config to preserve UDP opt-in
When a first-time CLI user runs without arguments, main writes DEFAULT_CONFIG_TEMPLATE, but the embedded crates/proxy-client/config.template.toml still explicitly sets udp = true and says omission defaults to enabled. After the user fills in the server and restarts, that explicit value wins before this new fallback, so the normal first-run workflow still enables UDP without an opt-in; README.md likewise advertises the old default. Update the generated template, its configuration comment, and the README to match the new default.
AGENTS.md reference: AGENTS.md:L339-L350
Useful? React with 👍 / 👎.
| && !ip.is_unspecified() | ||
| && !ip.is_multicast() | ||
| && !matches!(ip, IpAddr::V4(v4) if v4.is_broadcast()) |
There was a problem hiding this comment.
Keep local multicast and broadcast UDP on the direct route
For captured local-discovery traffic such as mDNS (224.0.0.251/ff02::fb), this new filter discards the destination before is_local_network_host can classify it as local; limited IPv4 broadcasts are discarded similarly. The UDP router therefore returns Reject when UDP proxying is off or sends the packet to the remote proxy when it is enabled, breaking LAN discovery and contradicting the fixed policy that local-network UDP is direct. Preserve these local UDP destinations in the direct branch, potentially by separating UDP classification from the stricter TCP address filtering.
Useful? React with 👍 / 👎.
Apple packet tunnels could leave Edge Google searches waiting on direct foreign QUIC, and node probes ran through the selected VPN node. Apply one UDP destination policy before opening a relay: mainland/local addresses are direct; foreign UDP is rejected immediately unless explicitly enabled, in which case it is proxied. Server UDP readiness is required before installing tunnel routes. TCP Auto/reverse settings do not alter this UDP policy, and DNS stays available.
Use the same bounded, TTL-aware address cache for TCP and UDP decisions instead of caching a transport-specific route. Keep optional UDP disabled in legacy imports/default client entry points. Connected Apple node probes now execute in the provider with four-worker concurrency and reconnect guards. Include the locally built 2.0.11+84 UI source revision; no generated binaries are committed.
Dependencies: acking-you/ipstack#3 (ICMP v4/v6 feedback), acking-you/tun2proxy#12 (destination policy), Proxy-UI/Proxy-UI-Flutter#29 (controls/provider probes). No remote proxy wire format or existing C ABI layout changes. Updated
docs/ios-development.mdanddocs/client-usage.mddistinguish Apple packet-tunnel rules from desktop TUN behavior.Validation:
cargo test --workspacecargo test -p proxy-client --features network-extension --test packet_tunnelcargo test -p proxy-client --features network-extension --lib packet_routingcargo clippy -p proxy-crypto -p proxy-core -p proxy-client -p proxy-server -p proxy-tui -p proxy-ffi --all-targets --all-features --no-deps -- -D warningscargo check -p proxy-client --no-default-features --lockedfvm flutter analyze --no-fatal-infos;fvm flutter test(190 passed, 7 skipped), final focused Apple/UDP testspython3 scripts/ios/build.py --team <development-team> --configuration Release, signatures and matching app/extension versions verified locallyPhysical iPhone acceptance: real Edge Google search results; mainland TCP direct and foreign TCP proxy egress; mainland UDP by IP and domain succeeded in 51/104 ms; foreign UDP was rejected in 1/13 ms; 100 MB downloaded with no provider restart or dropped packets (peak footprint about 34 MB); terminating the containing app preserved forwarding. A real legacy node rejected UDP enablement before readiness, and restoring UDP-off successfully reconnected. Final Release 84 device checks additionally verified five provider-owned probes (146–443 ms), all ten HTTP/HTTPS acceptance requests, mainland UDP direct (57/97 ms), foreign UDP rejection (1/17 ms), and actual UDP proxy egress on a capable node. Three Edge Google searches, including restarting Edge, showed the reload icon and no progress bar by about 4.3 seconds; one cold search rendered results by 2.4 seconds. This checks load completion, not just visible results.
A further throughput comparison found a selected node slow on the phone network: 25 MB downloads exceeded their deadline both through TUN and through an explicit local SOCKS connection bypassing TUN. The invalid-SOCKS-port control failed immediately, confirming that the comparison actually used the explicit proxy. This is not reported as a passing stability test; final acceptance uses the independently verified working node. Timing evidence and captures remain local; no personal device data is published.
Final Release 84 on the working node completed all four 25 MB transfers (55.46 / 6.01 / 6.50 / 4.49 s; 100 MB total), with ten HTTP/HTTPS checks passing, distinct mainland/foreign egress, zero packet-queue drops, no provider restart, and a peak reported footprint of 25,166,696 bytes. Mainland UDP replies took 34–45 ms and foreign rejection 1–15 ms. The first bulk transfer was slower than subsequent transfers; these timings are retained rather than summarized as uniformly fast.
Final browsing boundary: the working-node Google “network latency” page reached 100% around 12.3 s (bar hidden by 14.3 s); subsequent “network protocol” and “network latency meaning” searches completed by about 4.3 s. In the packet trace, main Google-related TCP first responses were about 30–120 ms. The intermittent page-completion tail is not claimed to be eliminated or proven to originate in the VPN; result rendering alone is not the completion criterion.