fix: block DoH by default + fix Android tunnel_doh config mismatch#763
Merged
therealaleph merged 1 commit intotherealaleph:mainfrom May 5, 2026
Merged
Conversation
Problem: PR therealaleph#468 changed `tunnel_doh` default to `true` (tunnel DoH through Apps Script) to avoid ISP-blocked DoH on censored networks. But this added ~1.5s of Apps Script round-trip per DNS lookup — every page load got noticeably slower because Chrome's DoH connections had to traverse the full tunnel path before the page could even start connecting. The Android side had a separate bug: `tunnelDoh` defaulted to `false` but only emitted `tunnel_doh` to JSON when `true`. Since the Rust default is `true`, omitting the field meant Rust always tunneled DoH regardless of the Android UI setting — bypass_doh was silently broken on Android. Fix: - Add `block_doh` config option: immediately reject (RST) connections to known DoH endpoints. Browsers fall back to system DNS, which tun2proxy handles via virtual DNS (instant, zero tunnel cost). Eliminates the DoH round-trip without exposing DoH connections to the ISP (unlike bypass_doh which sends DoH direct). - Default `block_doh: true` on Android — tested on Chrome/Brave, falls back to virtual DNS correctly. - Fix Android `tunnelDoh` default to `true` (matches Rust). - Always emit `tunnel_doh` and `block_doh` explicitly in Android JSON serialization — no more default-mismatch bugs. - Add Block DoH and Bypass DoH toggles in Android Advanced UI. Block DoH takes priority; Bypass DoH is disabled when Block is on. Tested on Pixel 6 Pro: zero chrome.cloudflare-dns.com tunnel sessions with block_doh=true. All DNS resolves instantly via tun2proxy virtual DNS. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Owner
|
@yyoyoian-pixel — reviewed locally (179 lib + 35 tunnel-node tests still pass). Merging. The DoH block is the right call — DoH-via-Apps-Script was wasting tunnel quota on a use case (encrypted DNS) where browsers will happily fall back to system DNS, which tun2proxy resolves via virtual DNS at zero cost. The Block > Bypass priority + the disabled Bypass switch when Block is on is a good UX pattern. The Android Will ship in the next release. [reply via Anthropic Claude | reviewed by @therealaleph] |
therealaleph
added a commit
that referenced
this pull request
May 5, 2026
Wraps three already-merged PRs into a release: - PR #763 (@yyoyoian-pixel): block_doh: true default; rejects browser DoH at SOCKS5 listener so it falls back to system DNS via tun2proxy virtual DNS instead of paying ~1.5s tunnel round-trip per name lookup. Also fixes the Android tunnel_doh config mismatch (was false on Android, true on Rust — silently broke bypass_doh_hosts). - PR #751 (@yyoyoian-pixel): TLS pool refill loop keeping ≥8 ready connections, freshest-first acquire, pool TTL 45→60s, coalesce step 10→200ms (more conservative revert from v1.9.8 for full-mode batch packing). - PR #747 (@Shjpr9): added github.io to Fastly fronting group example. Tests: 179 lib + 35 tunnel-node green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
therealaleph
added a commit
that referenced
this pull request
May 5, 2026
…doh field Both v1.9.11 and v1.9.12 release CI runs failed because PR #763 added a new `block_doh: bool` field to `Config` but didn't update `src/bin/ui.rs::FormState::to_config()` which builds Config via a struct literal — caught by `cargo build --features ui --bin mhrv-rs-ui` only, not by the lib `cargo test` I'd run during PR review. Added the field to FormState (round-trip from Config), to ConfigWire (skip_serializing_if = "is_true" so default-true configs stay clean), and a new is_true helper. Verified mhrv-rs-ui release build green locally before pushing. Net effect: v1.9.13 ships everything v1.9.11 and v1.9.12 were supposed to ship (DoH block by default, TLS pool refill loop, github.io fronting group, parallel_relay safe-method gating) plus this UI fix. No additional behavior change. Tests: 180 lib + 35 tunnel-node + UI release-mode build all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
therealaleph
added a commit
that referenced
this pull request
May 5, 2026
PR #763 added `block_doh: bool` with `#[serde(default)]`, which resolves to Rust's `Default::default() = false` for bool, not the `true` PR #763's docs intended. Existing configs upgrading from v1.9.10 → v1.9.13 had no block_doh field, so they got `false` paired with `tunnel_doh: true` (new default from #468) — every browser DoH lookup got tunneled through Apps Script, adding ~1.5s overhead per page load. User-perceived as "v1.9.13 is slower than v1.9.10" in #773. Switched to a named-default function `default_block_doh() -> bool { true }` so the upgrade path actually delivers the fast block-then-system-DNS behaviour PR #763 advertised. Power users who specifically want browser DoH (with the latency cost) can still opt in with explicit `block_doh: false`. Tests: 180 lib + 35 tunnel-node + UI release-mode build all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
block_doh: true): immediately reject connections to known DoH endpoints (chrome.cloudflare-dns.com, dns.google, etc.). Browsers fall back to system DNS, which tun2proxy handles via virtual DNS — instant, zero tunnel cost. Saves ~1.5s per domain lookup vs tunneling DoH through Apps Script.tunnelDohdefaulted tofalseon Android buttrueon Rust. When Android omitted the field (default = don't emit), Rust used its own default (true) — sobypass_dohwas silently broken on Android. Now Android always emitstunnel_dohexplicitly and defaults match Rust.Context
PR #468 changed
tunnel_dohtotruebecause Iranian ISPs block direct DoH endpoints. This was the right call for censorship resistance, but it made every page load ~1.5s slower per domain (Chrome's DoH connections now traversed the full Apps Script tunnel).block_dohsolves both problems: no ISP-visible DoH connection (the connection never leaves the device), no tunnel round-trip (system DNS is instant via tun2proxy virtual DNS).Test plan
chrome.cloudflare-dns.comtunnel sessions withblock_doh=true🤖 Generated with Claude Code