From 658e72fe0df6fc701520a10008ce6bd114cb4815 Mon Sep 17 00:00:00 2001 From: therealaleph Date: Thu, 23 Apr 2026 21:22:17 +0300 Subject: [PATCH] v1.2.6: rust-cache bin pruning fix + PR #83 scan-sni v1.2.4 and v1.2.5 both cut clean tags but CI failed downstream for different self-hosted reasons: - v1.2.4 failed on parallel apt-lock race (fixed) - v1.2.5 failed with "TOML parse error at line 5 column 9" because rust-cache v2's default cache-bin=true prunes $CARGO_HOME/bin of any binary not installed via `cargo install`. `rustup` itself is installed by rustup-init, not cargo install, so it got flagged as "unknown" and deleted on cache save. Next job hits the cargo symlink that points at a missing rustup, which resolves somehow to a very old cargo that can't parse our Cargo.toml. Fix: - Set `cache-bin: "false"` on every Swatinem/rust-cache@v2 call. We still cache target/ + registry (the big win), just not bin/. Binaries are stable across runs on our self-hosted box anyway. - Reinstalled rustup inside each per-runner CARGO_HOME on the server to recover from the broken state. Also in this release: - PR #83: new `mhrv-rs scan-sni` subcommand. Pulls Google's published IP ranges, does PTR lookups via dns.google on each IP, filters to Google-related hostnames, then TLS-probes each discovered SNI against the configured google_ip to see which ones bypass DPI. Useful for rebuilding a working SNI pool on a new ISP. Adds the `url` crate dep. Same user-facing code as v1.2.4/v1.2.5 (PRs #78, #79, README Android note) plus PR #83 and the CI fixes on top. --- .github/workflows/release.yml | 14 ++++++++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- android/app/build.gradle.kts | 4 ++-- docs/changelog/v1.2.5.md | 10 ---------- docs/changelog/v1.2.6.md | 13 +++++++++++++ 6 files changed, 31 insertions(+), 14 deletions(-) delete mode 100644 docs/changelog/v1.2.5.md create mode 100644 docs/changelog/v1.2.6.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b9e31c..6837a96 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -106,10 +106,19 @@ jobs: # `git clean -ffdx` wipes target/ between runs and every build is # cold. With it, warm builds are sub-minute even for the full # release profile. + # + # cache-bin: false is MANDATORY on our self-hosted runners. With + # the default (true), rust-cache aggressively prunes $CARGO_HOME/bin + # of binaries it didn't install via `cargo install`, including the + # `rustup` binary that cargo/rustc/etc. are symlinked to. The next + # job then hits "command not found" or a broken-symlink TOML parse + # error from a stale cargo. We want target/ + registry caching, NOT + # bin pruning. rustup is pre-installed on the runners anyway. - uses: Swatinem/rust-cache@v2 if: matrix.mipsel_softfloat != true with: key: ${{ matrix.target }} + cache-bin: "false" # eframe needs a few system libs on Linux for window management, keyboard, # and OpenGL/X11/Wayland. Gated to GitHub-hosted runners only — the @@ -343,9 +352,14 @@ jobs: # Cache cargo + target/ across Android release builds. Four cargo-ndk # release builds back-to-back with LTO is where the cold cost comes # from; rust-cache brings warm runs down to ~3–4 min from ~9 min cold. + # cache-bin: false — see the rationale on the matrix build job above. + # On top of that, `cargo-ndk` lives in /usr/local/bin/ on our runners + # (not $CARGO_HOME/bin), specifically so rust-cache's default bin + # pruning can't delete it. - uses: Swatinem/rust-cache@v2 with: key: android-universal + cache-bin: "false" # cargo-ndk writes into `target//release/`, all # four of which we want to cache. workspaces: | diff --git a/Cargo.lock b/Cargo.lock index 91121b1..8294883 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2186,7 +2186,7 @@ dependencies = [ [[package]] name = "mhrv-rs" -version = "1.2.5" +version = "1.2.6" dependencies = [ "base64 0.22.1", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 260bc46..2255bac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mhrv-rs" -version = "1.2.5" +version = "1.2.6" edition = "2021" description = "Rust port of MasterHttpRelayVPN -- DPI bypass via Google Apps Script relay with domain fronting" license = "MIT" diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 288e795..c96af86 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -14,8 +14,8 @@ android { applicationId = "com.therealaleph.mhrv" minSdk = 24 // Android 7.0 — covers 99%+ of live devices. targetSdk = 34 - versionCode = 125 - versionName = "1.2.5" + versionCode = 126 + versionName = "1.2.6" // Ship all four mainstream Android ABIs: // - arm64-v8a — 95%+ of real-world Android phones since 2019 diff --git a/docs/changelog/v1.2.5.md b/docs/changelog/v1.2.5.md deleted file mode 100644 index 8fbf323..0000000 --- a/docs/changelog/v1.2.5.md +++ /dev/null @@ -1,10 +0,0 @@ - -• سخت‌کردن range-parallel: اعتبارسنجی هدر `Content-Range` قبل از دوختن پاسخ‌های ۲۰۶. پاسخ‌های نامعتبر دیگه به صورت ۲۰۰ OK جعلی ترکیب نمی‌شن — probe نامعتبر به GET تکی برمی‌گرده، چانک‌های نامعتبر به پاسخ probe برمی‌گرده (PR #78) -• رد configهایی که HTTP و SOCKS5 رو روی یک پورت تنظیم کرده‌اند قبل از bind failure زمان اجرا. هم در load config و هم در فرم UI چک می‌شه (PR #79) -• یادداشت README درباره محدودیت user-CA اندروید 7+ — اپ‌هایی مثل Telegram / WhatsApp / Instagram به CA ما اعتماد نمی‌کنن، برای اون‌ها از PROXY_ONLY یا upstream_socks5 استفاده کنید (issues #74 #81) -• رفع زیرساخت CI: مراحل apt-get در buildهای Linux فقط روی runnerهای GitHub-hosted اجرا می‌شن. روی runnerهای self-hosted جدید، چندین job موازی روی `/var/lib/apt/lists/lock` رقابت می‌کردن و همه fail می‌شدن. بسته‌ها اکنون در setup runner پیش‌نصب هستند ---- -• Range-parallel hardening: validate `Content-Range` before stitching 206 responses. Invalid responses no longer combine into a fake 200 OK — invalid probe falls back to a normal single GET, invalid later chunks fall back to the probe response (PR #78) -• Reject configs that set HTTP and SOCKS5 to the same port before the runtime bind failure. Enforced both at config-load time and in the UI form (PR #79) -• README note on the Android 7+ user-CA trust limit — apps like Telegram / WhatsApp / Instagram don't trust user-installed CAs, use PROXY_ONLY or upstream_socks5 for those (issues #74 #81) -• CI infrastructure fix: apt-get steps on Linux build jobs gated to GitHub-hosted runners only. On the new self-hosted runners, multiple parallel matrix jobs were racing on `/var/lib/apt/lists/lock` and failing all at once. Packages now pre-installed at runner setup time diff --git a/docs/changelog/v1.2.6.md b/docs/changelog/v1.2.6.md new file mode 100644 index 0000000..7688c64 --- /dev/null +++ b/docs/changelog/v1.2.6.md @@ -0,0 +1,13 @@ + +• سخت‌کردن range-parallel: اعتبارسنجی هدر `Content-Range` قبل از دوختن پاسخ‌های ۲۰۶. پاسخ‌های نامعتبر دیگه به صورت ۲۰۰ OK جعلی ترکیب نمی‌شن — probe نامعتبر به GET تکی برمی‌گرده، چانک‌های نامعتبر به پاسخ probe برمی‌گرده (PR #78) +• رد configهایی که HTTP و SOCKS5 رو روی یک پورت تنظیم کرده‌اند قبل از bind failure زمان اجرا. هم در load config و هم در فرم UI چک می‌شه (PR #79) +• یادداشت README درباره محدودیت user-CA اندروید 7+ — اپ‌هایی مثل Telegram / WhatsApp / Instagram به CA ما اعتماد نمی‌کنن، برای اون‌ها از PROXY_ONLY یا upstream_socks5 استفاده کنید (issues #74 #81) +• رفع زیرساخت CI (دور دوم): rust-cache v2 به صورت پیش‌فرض `$CARGO_HOME/bin` رو در پایان هر job pruneمی‌کرد و باینری `rustup` رو (که توسط rustup-init نصب شده، نه `cargo install`) پاک می‌کرد. این باعث می‌شد jobهای بعدی روی symlinkهای شکسته به TOML parse error برخورد کنن. حالا `cache-bin: "false"` تنظیم کردیم و `cargo-ndk` هم به `/usr/local/bin/` منتقل شده +• اسکن SNI خودکار: دستور جدید `mhrv-rs scan-sni` که از رنج IPهای Google با PTR lookup روی dns.google شروع می‌کنه، روی هر IP SNIهای Google-related رو کشف می‌کنه، و هر کدوم رو با TLS handshake علیه `google_ip` تست می‌کنه تا ببینه DPI رو رد می‌کنن یا نه (PR #83) +--- +• Range-parallel hardening: validate `Content-Range` before stitching 206 responses. Invalid responses no longer combine into a fake 200 OK — invalid probe falls back to a normal single GET, invalid later chunks fall back to the probe response (PR #78) +• Reject configs that set HTTP and SOCKS5 to the same port before the runtime bind failure. Enforced both at config-load time and in the UI form (PR #79) +• README note on the Android 7+ user-CA trust limit — apps like Telegram / WhatsApp / Instagram don't trust user-installed CAs, use PROXY_ONLY or upstream_socks5 for those (issues #74 #81) +• CI infrastructure fix (round 1): apt-get steps on Linux build jobs gated to GitHub-hosted runners only. On the new self-hosted runners, multiple parallel matrix jobs were racing on `/var/lib/apt/lists/lock` and failing all at once. Packages now pre-installed at runner setup time +• CI infrastructure fix (round 2): rust-cache v2's default bin-pruning was wiping the `rustup` binary at end of each job (since rustup wasn't installed via `cargo install`, rust-cache considered it an "unknown" bin). Next job then hit TOML parse errors from broken cargo symlinks. Set `cache-bin: "false"` and moved `cargo-ndk` to `/usr/local/bin/` out of rust-cache's reach +• New `mhrv-rs scan-sni` subcommand: pulls Google's IP ranges, does PTR lookups via dns.google on each IP to discover Google-related hostnames, then TLS-probes each discovered SNI against the configured `google_ip` to see if it bypasses DPI. Useful for rebuilding a working SNI pool on a new ISP (PR #83)