Files
MasterHttpRelayVPN-RUST/docs/changelog/v1.8.0.md
T
therealaleph cb3732f920 feat: v1.8.0 — DPI evasion, active-probing defense, full-mode usage counters
Five user-visible changes shipping together. Each is independently
useful + bounded; bundled because they're all "small architectural
hardening" that benefits from one release announcement.

1. Random payload padding (#313, #365 §1)

   Every outbound Apps Script JSON request now carries a `_pad` field
   of uniform-random length 0..1024 bytes (base64). Defeats DPI that
   fingerprints on the tight length distribution of mhrv-rs's previous
   per-mode-bound packet sizes. ~25% bandwidth on a typical 2 KB batch,
   negligible against Apps Script's per-call latency floor. Backward-
   compatible — old `Code.gs` deployments ignore the unknown field.
   Applied at all three payload-build sites: single relay, single
   tunnel op, batch tunnel.

2. Active-probing decoy: GAS bad-auth → 200 HTML (#365 §3)

   `Code.gs` and `CodeFull.gs` now return a benign Apps-Script-style
   placeholder HTML page on bad/missing AUTH_KEY instead of the JSON
   `{"e":"unauthorized"}`. To an active scanner the deployment looks
   like one of the millions of forgotten public Apps Script projects
   rather than an obvious API endpoint. New `DIAGNOSTIC_MODE` const
   restores JSON errors during setup; default false (production-strong).

3. Active-probing decoy: tunnel-node bad-auth → 404 nginx (#365 §3)

   `tunnel-node` returns an HTTP 404 with an nginx-style HTML body on
   bad auth instead of `{"e":"unauthorized"}`. Active scanners cataloging
   the host see "static web server, nothing tunnel-shaped here." New
   `MHRV_DIAGNOSTIC=1` env var restores verbose JSON during setup.

4. Fix: Full-mode usage counter stuck at zero (#230, #362)

   `today_calls` / `today_bytes` were only being incremented on the
   apps_script-mode relay path. Full-mode batches go through
   `tunnel_client::fire_batch` which never wired into the counter.
   Now `fire_batch` calls `record_today(response_bytes)` after each
   successful batch — bytes estimated from the `d` (TCP payload) and
   `pkts` (UDP datagrams) sizes in the BatchTunnelResponse. Full-mode
   users now see real usage numbers.

5. Fix: quota reset countdown was UTC, should be PT (#230, #362)

   Apps Script's UrlFetchApp daily quota resets at midnight Pacific
   Time, not UTC. We were displaying the countdown to UTC midnight,
   off by 7-8h depending on DST. New `current_pt_day_key()` and
   `seconds_until_pacific_midnight()` helpers with hand-rolled US DST
   detection (2nd Sunday March → 1st Sunday November = PDT, else PST)
   so we don't pull `chrono-tz` and a ~3 MB IANA tzdb just for one
   helper. UI label "UTC day" → "PT day". Tests pin DST window
   boundaries against March/November of 2024, 2026, 2027 to catch
   regressions in the day-of-week math.

Tested:
- cargo test --lib: 154 passed (was 152, +2 for DST window + day-of-week)
- cargo build --release: clean
- cargo build --release --bin mhrv-rs-ui --features ui: clean (macOS arm64)
- tunnel-node cargo test: 30 passed
- Android: ./gradlew assembleDebug succeeds; APK installs + launches
  on mhrv_test emulator (arm64-v8a), no UnsatisfiedLink, no crash

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 01:39:47 +03:00

13 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- see docs/changelog/v1.1.0.md for the file format: Persian, then `---`, then English. -->
• Padding random برای پایلود Apps Script ([#313](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/313)، [#365](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/365) Section 1): هر request به Apps Script حالا یک فیلد `_pad` با طول uniform-random بین ۰-۱۰۲۴ بایت اضافه می‌کنه — به‌صورت base64 encoded. بدون این، طول request body در هر mode تقریباً ثابت می‌مونه + DPI ایران می‌تونه بر اساس distribution طول fingerprint بزنه. حالا packet sizes uniformly distributed هستن + length-clustering match نمی‌کنه. تأثیر bandwidth: متوسط ۵۱۲ بایت اضافه به batch ~۲KB = +۲۵٪، negligible در برابر floor latency Apps Script. backward-compatible: Code.gs قدیم هم کار می‌کنه (unknown JSON fields ignore می‌شن).
• Defense active probing: decoy 200 HTML در Code.gs / CodeFull.gs روی AUTH_KEY بد ([#365](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/365) Section 3): قبلاً request بدون auth `{"e":"unauthorized"}` JSON برمی‌گردوند — fingerprint مشخص "این یه API endpoint هست". حالا یه HTML benign placeholder برمی‌گردونه که شبیه یه Apps Script web app forgotten-but-public هست. scanner active که با AUTH_KEY ساختگی POST می‌کنه categorize می‌کنه به‌عنوان "non-tunnel، nothing interesting". flag `DIAGNOSTIC_MODE` برای setup که response قدیمی JSON رو برمی‌گردونه — default `false` (production-strong)
• Defense active probing: decoy 404 nginx در tunnel-node روی auth بد: tunnel-node قبلاً `{"e":"unauthorized"}` JSON برمی‌گردوند. حالا response 404 با body HTML شبیه nginx default error می‌فرسته (active scanners "static web server هست، tunnel نیست" تشخیص می‌دن). env var `MHRV_DIAGNOSTIC=1` برای setup behavior قدیمی رو فعال می‌کنه
• رفع باگ "Usage today (estimated) در Full mode همیشه ۰" ([#230](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/230)، [#362](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/362)): counter `today_calls` و `today_bytes` فقط روی apps_script-mode relay path در `domain_fronter::relay()` افزایش می‌یافت. Full mode از `tunnel_client::fire_batch` می‌گذره که کانتر رو زد. حالا fire_batch بعد از batch موفق `record_today(response_bytes)` رو صدا می‌زنه — bytes از sum طول `d` و `pkts` در BatchTunnelResponse تخمین زده می‌شه. Full mode users حالا "Usage today" واقعی می‌بینن
• رفع باگ "quota reset countdown با time UTC به‌جای PT نشون داده می‌شه" ([#230](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/230)، [#362](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/362)): Apps Script's UrlFetchApp quota در 00:00 **Pacific Time** ریست می‌شه (PST/PDT با DST)، نه UTC. ما UTC midnight رو نشون می‌دادیم — ۷-۸ ساعت off. fix: helpers جدید `current_pt_day_key()` + `seconds_until_pacific_midnight()` با hand-rolled DST detection (بدون اضافه کردن chrono-tz / 3MB tzdb). UI label "UTC day" → "PT day" تغییر کرد. ۲ test جدید برای DST window boundaries (مارس ۲۰۲۴/۲۰۲۶/۲۰۲۷، نوامبر ۲۰۲۴/۲۰۲۶) + Sakamoto's day-of-week
---
• Random payload padding for Apps Script requests ([#313](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/313), [#365](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/365) Section 1): every outbound request to Apps Script now carries a `_pad` field of uniform-random length 01024 bytes (base64 encoded). Before this, request body sizes within each mode were tightly clustered, giving ISP DPI a clean length-distribution fingerprint to match against. Now packet sizes are spread uniformly across the range so length-clustering DPI heuristics can't match. Bandwidth cost: ~512 bytes added to a typical 2 KB tunnel batch = +25%, negligible against Apps Script's per-call latency floor. Backward-compatible: old Code.gs deployments ignore the unknown field. Applied at all three payload-build sites: single relay, single tunnel op, batch tunnel.
• Active-probing defense: decoy 200 HTML on bad AUTH_KEY in `Code.gs` and `CodeFull.gs` ([#365](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/365) Section 3): previously a request with a missing/wrong AUTH_KEY got `{"e":"unauthorized"}` as a JSON body — a clear "this is some kind of API endpoint" signal that active scanners can fingerprint. Now bad-auth requests get a benign HTML placeholder page that looks like a forgotten-but-public Apps Script web app, indistinguishable from the millions of stale Apps Script projects on Google's infrastructure. New `DIAGNOSTIC_MODE` const (default `false`) restores the old JSON error response for setup/debugging — flip to `true` while configuring a misconfigured client, then back to `false` before sharing the deployment widely.
• Active-probing defense: decoy 404 nginx-style HTML on bad auth in `tunnel-node` ([#365](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/365) Section 3): previously a bad-auth request got `{"e":"unauthorized"}`. Now it gets an HTTP 404 with an `nginx`-style error page body, looking like a vanilla static web server. Active scanners that POST malformed payloads to `/tunnel` to discover proxy endpoints categorize this host as "boring" and move on. New `MHRV_DIAGNOSTIC=1` env var restores the verbose JSON error during setup; default is the production decoy.
• Fix "Usage today (estimated) is always 0 in Full mode" ([#230](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/230), [#362](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/362)): the daily-usage counters (`today_calls` / `today_bytes`) were incremented only on the `apps_script`-mode relay path inside `domain_fronter::relay()`. Full-mode traffic goes through `tunnel_client::fire_batch` which never wired the counter. Now `fire_batch` calls `record_today(response_bytes)` after each successful batch — bytes are estimated from the sum of per-session `d` (TCP payload) and `pkts` (UDP datagrams) lengths in the `BatchTunnelResponse`, which is a stable proxy for "how much did this batch move." Full mode users now see real usage numbers instead of stuck-at-zero.
• Fix "quota reset countdown shown in UTC instead of Pacific Time" ([#230](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/230), [#362](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/362)): Apps Script's `UrlFetchApp` quota actually resets at midnight Pacific Time (PST/PDT — observes DST), not midnight UTC. We were displaying the countdown to UTC midnight, which is 78 hours off depending on DST. Fix: new `current_pt_day_key()` + `seconds_until_pacific_midnight()` helpers using a hand-rolled US DST detector (2nd Sunday of March → 1st Sunday of November = PDT, otherwise PST) so we don't pull `chrono-tz` and a ~3 MB IANA tzdb just for one helper. UI label updated from "UTC day" to "PT day". Two new tests pin down the DST window boundaries (March 2024 / 2026 / 2027, November 2024 / 2026) and Sakamoto's day-of-week formula.