feat: multi-edge fronting_groups + rename google_only to direct#488
Merged
therealaleph merged 2 commits intotherealaleph:mainfrom Apr 29, 2026
Merged
Conversation
Closed
therealaleph
added a commit
that referenced
this pull request
Apr 29, 2026
…p + hotspot sharing Three substantive PRs landed for this release plus an Iran-safe DoH default: - #488 by @dazzling-no-more (with credit to @patterniha): fronting_groups config field generalizes the Google-edge SNI-rewrite trick to any multi-tenant CDN edge (Vercel, Fastly, etc.). Renames `mode = "google_only"` → `mode = "direct"` with a deprecated alias keeping existing configs working. This is the v1.9.0 headline — new top-level config field + public mode-string rename are minor-bump territory. xmux moves to v1.10.0. - #494 by @dazzling-no-more: edge-cache DNS at Apps Script (CodeFull.gs) using CacheService. udp_open / port=53 ops served from cache or DoH fallback chain (Cloudflare → Google → Quad9). Cache hits drop typical first-hop DNS latency from 600-1200ms to 200-400ms. Default-on, opt-out via ENABLE_EDGE_DNS_CACHE; every failure mode falls through to existing tunnel-node forward path (zero regression). - #483 by @yyoyoian-pixel: default listen_host from 127.0.0.1 to 0.0.0.0 so an Android phone running the tunnel + an iPhone/laptop on the same hotspot can use it as proxy. Old configs with explicit 127.0.0.1 are honored (not overwritten). Plus: default `tunnel_doh: true` (flipped from false in v1.8.x) per #468 — Iran ISPs filter direct connections to dns.google, chrome.cloudflare-dns.com, and other pinned DoH hosts. The bypass-on default silently broke DNS for the dominant Iranian userbase. The safe default keeps DoH inside the tunnel; non-Iran users can opt back into the bypass for the latency win. Backwards-compatible — any config with explicit tunnel_doh keeps its setting. 169 mhrv-rs lib tests + 33 tunnel-node tests + 11 edge-DNS JS tests all passing. Clean release + UI builds.
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
fronting_groupsconfig field — generalizes the Google-edge SNI-rewrite trick to any multi-tenant CDN edge (Vercel, Fastly, …). Each group is{name, ip, sni, domains}; matched hosts get MITM-decrypted at the local CA and re-encrypted upstream againstipwithsnias the TLS SNI.mode = "google_only"→mode = "direct". The old name no longer described the mode now that it reaches more than Google. Both Rust and Android Kotlin keep"google_only"as a deprecated alias on parse — no existing config / saved settings break.v1.8.6: a new top-level config field + a public mode-string rename are minor-bump territory, not a patch. Users onv1.8.xconfigs are unaffected (alias preserves them), but the feature surface justifies it.What's new
fronting_groups: [{name, ip, sni, domains}]inconfig.json. Wins over the built-in Google SNI-rewrite suffix list; loses topassthrough_hostsand DoH bypass. Skipped inmode = full(which preserves end-to-end TLS and can't MITM).config.fronting-groups.example.json.docs/fronting-groups.md— recipe for picking(ip, sni), routing precedence, and an explicitgoogle_only→directrenameMode::GoogleOnly→Mode::Direct. Parser accepts both strings.Mode.GOOGLE_ONLY→Mode.DIRECT. Same parse-time alias.config.google-only.example.json→config.direct.example.json.google_onlybefore v1.9 — old name still works" note for users following older guides / Telegram posts.Review fixes folded in
Config::validate()parsesServerName::try_from(sni)so invalid SNIs fail at the load gate, not later at proxy startup.RewriteCtx::fronting_groups: Vec<Arc<FrontingGroupResolved>>— per-CONNECT match is refcount-only, noVec<String>clone of normalized domains.is_dot_anchored_matchhelper: byte-level slicing replaces per-matchformat!(".{}", entry)allocation.mode = full && !fronting_groups.is_empty()(groups never fire), and duplicate group names (log lines become ambiguous). Both follow the existingbypass_doh_hosts + tunnel_dohprecedent.Test plan
cargo build --releasecleancargo test --lib— 169 passed, 0 failed (+8 new: dispatch matching, config validation, alias back-compat)Credit
Multi-edge fronting technique + the Vercel/Fastly example IPs are from @patterniha's MITM-DomainFronting. This PR ports the idea into mhrv-rs's existing MITM + dispatch infrastructure, validates SNIs through rustls, and exposes it as a first-class config field.