Skip to content

Commit bcdb3e7

Browse files
committed
v0.7.0: editable SNI rotation pool with reachability probes
New feature — users can now edit exactly which SNI names are rotated through the outbound Google-edge tunnel, and probe each one's reachability. Useful when an ISP selectively blocks individual Google subdomains (e.g. mail.google.com in Iran at various times). === Data model === Config gains an optional 'sni_hosts' field: "sni_hosts": ["www.google.com", "drive.google.com"] Precedence in domain_fronter::build_sni_pool_for(): 1. If sni_hosts is set & non-empty, use that list verbatim. 2. Else, if front_domain is one of the default Google-edge names, auto-expand to {www, mail, drive, docs, calendar}.google.com. 3. Else, use just [front_domain]. Empty / all-disabled list saves as None so the backend falls back to the defaults instead of having zero names to rotate through. === New scan_sni module === probe_one(ip, sni) / probe_all(ip, snis) does, for each candidate: 1. DNS lookup on the SNI (catches typos / non-existent names — Google GFE returns a valid wildcard cert for ANY *.google.com, so the TLS handshake alone can't tell apart a real name from gibberish). 2. TCP connect to google_ip:443 (3s timeout). 3. TLS handshake with the candidate SNI (3s timeout). RST mid- handshake signals DPI block. 4. Small HTTP HEAD over the tunnel to confirm it's still speaking HTTP (catches weird misroutes). Returns ProbeResult { latency_ms, error } per candidate. === New 'test-sni' CLI subcommand === $ mhrv-rs test-sni Probing 5 SNI candidates against google_ip=216.239.38.120 ... SNI LATENCY STATUS www.google.com 142 ms ok drive.google.com 138 ms ok mail.google.com - handshake RST (SNI may be blocked) ... Working: 3 / 5 Exit 0 if >=1 passed, non-zero otherwise. Uses the same probe logic the UI uses. === UI editor === New 'SNI pool... (active/total)' button in the main form, styled with a solid blue fill + white text so it's clearly actionable. Opens a floating egui::Window (resizable, movable, closable) with: - Action bar: 'Test all' | 'Keep working only' | 'Enable all' | 'Clear status' | 'Reset to defaults' - Scrollable list of rows, each: checkbox, monospaced name editor (230px), status cell (150px, 'ok 142 ms' green / 'fail <reason>' red / 'testing...' gray / 'untested' gray), per-row 'Test' and 'remove' buttons - Bottom: text input + '+ Add' that auto-probes the newly added name immediately (instead of leaving it silently 'untested') All rendered with ASCII status text instead of unicode check/cross glyphs, since egui's default font doesn't ship them on some hosts and they rendered as a missing-glyph box. Changes only commit when the user hits Save config in the main window; probe state is held in UiState::sni_probe so it survives opening and closing the editor. === README === English + Persian 'SNI pool editor' sections with the two workflows (UI button + 'sni_hosts' config field), plus a 'test-sni' line added to the Diagnostics section. Feature list updated.
1 parent 6999a1e commit bcdb3e7

9 files changed

Lines changed: 759 additions & 25 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mhrv-rs"
3-
version = "0.6.1"
3+
version = "0.7.0"
44
edition = "2021"
55
description = "Rust port of MasterHttpRelayVPN -- DPI bypass via Google Apps Script relay with domain fronting"
66
license = "MIT"

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,26 @@ Memory footprint is ~15-20 MB resident — fine on anything with ≥128 MB RAM.
236236

237237
- **`mhrv-rs test`** — sends one request through the relay and reports success/latency. Use this first whenever something breaks — it isolates "relay is up" from "client config is wrong".
238238
- **`mhrv-rs scan-ips`** — parallel TLS probe of 28 known Google frontend IPs, sorted by latency. Take the winner and put it in `google_ip`. The UI has the same thing behind the **scan** button next to the Google IP field.
239+
- **`mhrv-rs test-sni`** — parallel TLS probe of every SNI name in your rotation pool against the configured `google_ip`. Tells you which front-domain names actually pass through your ISP's DPI. The UI has the same thing in the **SNI pool…** floating window, with checkboxes, per-row **Test** buttons, and a **Keep ✓ only** button that auto-trims to what worked.
239240
- **Periodic stats** are logged every 60 s at `info` level (relay calls, cache hit rate, bytes relayed, active vs. blacklisted scripts). The UI shows them live.
240241

242+
### SNI pool editor
243+
244+
By default `mhrv-rs` rotates through `{www, mail, drive, docs, calendar}.google.com` on outbound TLS connections to your Google IP, to avoid fingerprinting one name too heavily. Some of those may be locally blocked — e.g. `mail.google.com` has been specifically targeted in Iran at various times.
245+
246+
Either:
247+
248+
- Open the UI, click **SNI pool…**, hit **Test all**, then **Keep ✓ only** to auto-trim. Add custom names via the text field at the bottom. Save.
249+
- Or edit `config.json` directly:
250+
251+
```json
252+
{
253+
"sni_hosts": ["www.google.com", "drive.google.com", "docs.google.com"]
254+
}
255+
```
256+
257+
Leaving `sni_hosts` unset gives you the default auto-pool. Run `mhrv-rs test-sni` to verify what works from your network before saving.
258+
241259
## What's implemented vs. not
242260

243261
This port focuses on the **`apps_script` mode** — the only one that reliably works against a modern censor in 2026. Implemented:
@@ -265,6 +283,7 @@ This port focuses on the **`apps_script` mode** — the only one that reliably w
265283
- [x] Per-connection SNI rotation across a pool of Google subdomains (`www/mail/drive/docs/calendar.google.com`), so outbound connection counts aren't concentrated on one SNI.
266284
- [x] Optional parallel script-ID dispatch (`parallel_relay`): fan out a relay request to N script instances concurrently, return first success, kill p95 latency at the cost of N× quota.
267285
- [x] Per-site stats drill-down in the UI (requests, cache hit %, bytes, avg latency per host) for live debugging.
286+
- [x] Editable SNI rotation pool (UI window + `sni_hosts` config field) with per-name reachability probes (`mhrv-rs test-sni` CLI or **Test** / **Test all** / **Keep working only** buttons). DNS + TLS-handshake based, catches both DPI-blocked names and typos.
268287
- [x] OpenWRT / Alpine / musl builds — static binaries, procd init script included.
269288

270289
Intentionally **not** implemented (rationale included so future contributors don't spend cycles on them):
@@ -455,6 +474,23 @@ Firefox cert store خودش را جدا دارد؛ installer تلاش می‌ک
455474

456475
HTTP/HTTPS هیچ تغییری نمی‌کند (همچنان از Apps Script می‌رود) و تونل SNI-rewrite برای `google.com` / `youtube.com` / … هم سر جای خودش است — پس یوتوب مثل قبل سریع می‌ماند و تلگرام بالاخره یک تونل واقعی می‌گیرد.
457476

477+
### ویرایشگر SNI pool
478+
479+
به‌صورت پیش‌فرض `mhrv-rs` بین `{www, mail, drive, docs, calendar}.google.com` روی اتصال‌های TLS خروجی به IP گوگل می‌چرخد تا یک نام تنها fingerprint نشود. بعضی از این‌ها ممکن است در شبکهٔ شما بلاک باشند — مثلاً `mail.google.com` در ایران چند بار هدف گرفته شده.
480+
481+
یا:
482+
483+
- UI را باز کنید، روی **SNI pool…** کلیک کنید، **Test all** را بزنید، بعد **Keep ✓ only** برای trim خودکار. از textbox پایین می‌توانید نام‌های دلخواه اضافه کنید. Save بزنید.
484+
- یا مستقیماً در `config.json`:
485+
486+
```json
487+
{
488+
"sni_hosts": ["www.google.com", "drive.google.com", "docs.google.com"]
489+
}
490+
```
491+
492+
اگر `sni_hosts` را نگذارید، pool پیش‌فرض اعمال می‌شود. قبل از ذخیره، `mhrv-rs test-sni` را اجرا کنید تا ببینید چه نامی از شبکهٔ شما رد می‌شود.
493+
458494
### اجرا روی OpenWRT (یا هر سیستم musl)
459495

460496
آرشیوهای `*-linux-musl-*` یک CLI کاملاً static می‌دهند که روی OpenWRT، Alpine و هر userland لینوکسی بدون glibc اجرا می‌شود. باینری را روی روتر بگذارید و به‌عنوان سرویس راه بیندازید:

0 commit comments

Comments
 (0)