Skip to content

Commit 059f3e0

Browse files
feat(config): migrate config format to TOML
Migrates the project configuration format from JSON to TOML with automatic legacy JSON upgrade support, updates docs/examples/scripts, and keeps Android + UI paths on the new format. Verified locally on the current GitHub merge ref: - `cargo test --lib` - `cargo build --release` - `cargo build --bin mhrv-rs-ui --release --features ui` - Android `:app:assembleDebug` with Android Studio JBR and local Android SDK --- Answered via LLM, Supervised @therealaleph
1 parent 63a6085 commit 059f3e0

40 files changed

Lines changed: 1030 additions & 629 deletions

Cargo.lock

Lines changed: 54 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ base64 = "0.22"
4444
bytes = "1"
4545
httparse = "1"
4646
rand = "0.8"
47+
toml = "0.8"
4748
h2 = "0.4"
4849
http = "1"
4950
flate2 = "1"

SF_README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Click **Connect** (or **Start** on desktop). Done. Your browser, Telegram, etc.
4949
### Common issues (most people hit at least one)
5050

5151
**YouTube videos look "restricted" or comments are missing? ([#61](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/61))**
52-
Turn on **"Send YouTube through relay (no SNI rewrite)"** in the desktop UI's Advanced section, or set `youtube_via_relay: true` in `config.json`. YouTube then goes through the Apps Script relay instead of the direct Google tunnel, which avoids YouTube's SafeSearch-on-SNI behaviour. Trade-off: slightly slower video, and it counts against your daily quota.
52+
Turn on **"Send YouTube through relay (no SNI rewrite)"** in the desktop UI's Advanced section, or set `youtube_via_relay = true` in `config.toml`. YouTube then goes through the Apps Script relay instead of the direct Google tunnel, which avoids YouTube's SafeSearch-on-SNI behaviour. Trade-off: slightly slower video, and it counts against your daily quota.
5353

5454
**"Verify you are human" loop on Cloudflare-protected sites?**
5555
This can't be fixed in this app. Every Apps Script request comes from a different Google datacenter IP, and Cloudflare's challenge cookie is locked to one IP — so the next request fails the check and re-challenges you. Sites that only check once per session work fine. Sites that check every page won't.
@@ -58,7 +58,7 @@ This can't be fixed in this app. Every Apps Script request comes from a differen
5858
Your Apps Script deployment isn't responding. Go back to <https://script.google.com>, **Deploy → Manage deployments → Edit (pencil)**, change "Version" to **New version**, click Deploy. Copy the **new** Deployment ID and paste it into the app.
5959

6060
**Hit your daily limit?**
61-
Free Google accounts get **20,000 relay requests per day**. The desktop and Android apps show a "Usage today" card with how many you've used. Add multiple Deployment IDs (one per line in the UI, or a JSON array in `config.json`) — each ID has its own quota and they're rotated automatically. You can also click "View quota on Google" to see the official number on Google's dashboard.
61+
Free Google accounts get **20,000 relay requests per day**. The desktop and Android apps show a "Usage today" card with how many you've used. Add multiple Deployment IDs (one per line in the UI, or an array in `config.toml`) — each ID has its own quota and they're rotated automatically. You can also click "View quota on Google" to see the official number on Google's dashboard.
6262

6363
**App says it's connected but websites don't load?**
6464
- Open the **SNI pool** section and click **Test all**. If everything fails, your `google_ip` value is unreachable from your network — click **Auto-detect google_ip** to fix.
@@ -120,7 +120,7 @@ This project is free and run by volunteers. If it helped you and you can spare a
120120
### مشکلات رایج (اکثر کاربران حداقل یکی از این‌ها را می‌بینند)
121121

122122
**ویدیوهای یوتیوب «محدود» نشان داده می‌شوند یا کامنت‌ها دیده نمی‌شوند؟ ([#61](https://github.com/therealaleph/MasterHttpRelayVPN-RUST/issues/61))**
123-
در بخش Advanced دسکتاپ گزینهٔ **«Send YouTube through relay (no SNI rewrite)»** را روشن کنید، یا در `config.json` مقدار `youtube_via_relay: true` بگذارید. در این حالت یوتیوب از مسیر ریلهٔ Apps Script رد می‌شود و فیلتر SafeSearch-on-SNI گوگل دور می‌خورد. تریدآف: ویدیو کمی کندتر و مصرف از سهمیهٔ روزانه.
123+
در بخش Advanced دسکتاپ گزینهٔ **«Send YouTube through relay (no SNI rewrite)»** را روشن کنید، یا در `config.toml` مقدار `youtube_via_relay = true` بگذارید. در این حالت یوتیوب از مسیر ریلهٔ Apps Script رد می‌شود و فیلتر SafeSearch-on-SNI گوگل دور می‌خورد. تریدآف: ویدیو کمی کندتر و مصرف از سهمیهٔ روزانه.
124124

125125
**روی سایت‌های پشت Cloudflare loop «Verify you are human» می‌خورد؟**
126126
این مشکل در این ابزار قابل حل نیست. هر درخواست Apps Script از یک IP متفاوت دیتاسنتر گوگل خارج می‌شود و کوکی challenge کلودفلر به یک IP خاص قفل است — درخواست بعدی از IP دیگر دوباره چالش می‌خورد. سایت‌هایی که فقط یک‌بار در ابتدای session چک می‌کنند درست کار می‌کنند. سایت‌هایی که هر صفحه چک می‌کنند، نه.
@@ -129,7 +129,7 @@ This project is free and run by volunteers. If it helped you and you can spare a
129129
Apps Script شما پاسخ نمی‌دهد. به <https://script.google.com> برگردید، **Deploy → Manage deployments → Edit (آیکن مداد)** را بزنید، گزینهٔ "Version" را روی **New version** بگذارید و Deploy کنید. **آی‌دی جدید** Deployment را کپی کنید و در برنامه جای‌گذاری کنید.
130130

131131
**سهمیهٔ روزانه تمام شده؟**
132-
هر حساب گوگل رایگان روزانه **۲۰٬۰۰۰ درخواست ریله** دارد. کارت «مصرف امروز» در دسکتاپ و اندروید مقدار مصرف فعلی را نشان می‌دهد. می‌توانید چند Deployment ID (هر کدام در یک خط، یا به‌صورت JSON array در `config.json`) اضافه کنید — هر آی‌دی سهمیهٔ خودش را دارد و به‌صورت چرخشی استفاده می‌شوند. دکمهٔ «مشاهدهٔ سهمیه در گوگل» شما را به داشبورد رسمی گوگل می‌برد.
132+
هر حساب گوگل رایگان روزانه **۲۰٬۰۰۰ درخواست ریله** دارد. کارت «مصرف امروز» در دسکتاپ و اندروید مقدار مصرف فعلی را نشان می‌دهد. می‌توانید چند Deployment ID (هر کدام در یک خط، یا در `config.toml`) اضافه کنید — هر آی‌دی سهمیهٔ خودش را دارد و به‌صورت چرخشی استفاده می‌شوند. دکمهٔ «مشاهدهٔ سهمیه در گوگل» شما را به داشبورد رسمی گوگل می‌برد.
133133

134134
**برنامه می‌گوید وصل است ولی سایت‌ها باز نمی‌شوند؟**
135135
- بخش **SNI pool** را باز کنید و **Test all** بزنید. اگر همه fail شدند، یعنی `google_ip` فعلی از شبکهٔ شما در دسترس نیست — روی **Auto-detect google_ip** بزنید تا اصلاح شود.

assets/apps_script/Code.cfw.gs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
* 6. Set WORKER_URL to your *.workers.dev URL (must include https://).
6060
* 7. Deploy → New deployment → Web app
6161
* Execute as: Me | Who has access: Anyone
62-
* 8. Copy the Deployment ID into mhrv-rs config.json as "script_id".
62+
* 8. Copy the Deployment ID into mhrv-rs config.toml as "script_id".
6363
* mhrv-rs does not need to know about Cloudflare; it talks to
6464
* Apps Script the same way it always has.
6565
*

assets/apps_script/Code.gs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* 4. (Optional) Set CACHE_SPREADSHEET_ID to enable caching
2727
* 5. Click Deploy → New deployment
2828
* 6. Type: Web app | Execute as: Me | Who has access: Anyone
29-
* 7. Copy the Deployment ID into config.json as "script_id"
29+
* 7. Copy the Deployment ID into config.toml as "script_id"
3030
*
3131
* CHANGE THE AUTH KEY BELOW TO YOUR OWN SECRET!
3232
*/

assets/cloudflare/README.fa.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mhrv-rs ──► Apps Script (Code.cfw.gs) ──► Cloudflare Worker ──
1111
▲ فقط احراز هویت و فوروارد ▲ گرفتن داده + base64
1212
```
1313

14-
پشتیبان استاندارد ([`assets/apps_script/Code.gs`](../apps_script/Code.gs)) خودِ `Apps Script` کار `fetch` به مقصد را انجام می‌دهد. این نسخه‌ٔ جایگزین، `Apps Script` را به یک رلهٔ نازک تبدیل می‌کند و کارِ اصلی را به لبهٔ `Cloudflare` می‌سپارد. **خود `mhrv-rs` تغییر نمی‌کند** — همان پاکت `JSON` روی سیم، همان `mode: "apps_script"` در `config.json`، همان `script_id`. تنها تفاوت این است که `Apps Script` مستقر شدهٔ شما بعد از احراز هویت چه می‌کند.
14+
پشتیبان استاندارد ([`assets/apps_script/Code.gs`](../apps_script/Code.gs)) خودِ `Apps Script` کار `fetch` به مقصد را انجام می‌دهد. این نسخه‌ٔ جایگزین، `Apps Script` را به یک رلهٔ نازک تبدیل می‌کند و کارِ اصلی را به لبهٔ `Cloudflare` می‌سپارد. **خود `mhrv-rs` تغییر نمی‌کند** — همان پاکت `JSON` روی سیم، همان `mode = "apps_script"` در `config.toml`، همان `script_id`. تنها تفاوت این است که `Apps Script` مستقر شدهٔ شما بعد از احراز هویت چه می‌کند.
1515

1616
ایدهٔ اصلی: <https://github.com/denuitt1/mhr-cfw>. این کپی یک بررسی `AUTH_KEY` روی خود `Worker` اضافه می‌کند، رفتار «صفحهٔ تقلبی برای کلید نامعتبر» را از `Code.gs` به ارث می‌برد، و یک محافظ در برابر حلقه‌شدن دارد.
1717

@@ -33,7 +33,7 @@ mhrv-rs ──► Apps Script (Code.cfw.gs) ──► Cloudflare Worker ──
3333

3434
## راه‌اندازی
3535

36-
سه رشتهٔ هم‌خوان نیاز دارید: یک `AUTH_KEY` که بین `worker.js`، `Code.cfw.gs` و `config.json` خود `mhrv-rs` مشترک است. یک رمز تصادفی قوی انتخاب کنید و در هر سه جا paste کنید.
36+
سه رشتهٔ هم‌خوان نیاز دارید: یک `AUTH_KEY` که بین `worker.js`، `Code.cfw.gs` و `config.toml` خود mhrv-rs مشترک است. یک رمز تصادفی قوی انتخاب کنید و در هر سه جا paste کنید.
3737

3838
### ۱. استقرار `Worker`
3939

@@ -58,14 +58,13 @@ mhrv-rs ──► Apps Script (Code.cfw.gs) ──► Cloudflare Worker ──
5858

5959
### ۳. اشاره دادن `mhrv-rs` به این `Apps Script`
6060

61-
در `config.json` (یا از طریق فرم `UI`):
61+
در `config.toml` (یا از طریق فرم `UI`):
6262

63-
```json
64-
{
65-
"mode": "apps_script",
66-
"script_id": "PASTE_DEPLOYMENT_ID_HERE",
67-
"auth_key": "SAME_SECRET_AS_BOTH_FILES_ABOVE"
68-
}
63+
```toml
64+
[relay]
65+
mode = "apps_script"
66+
auth_key = "YOUR_SHARED_SECRET"
67+
script_ids = ["YOUR_DEPLOYMENT_ID"]
6968
```
7069

7170
تمام. `mhrv-rs` لازم نیست بداند `Cloudflare` در کار است؛ از نگاه او این `script_id` مثل هر `Deployment` دیگری رفتار می‌کند. اگر چند `Deployment` دارید (بعضی استاندارد، بعضی `CFW`)، می‌توانید همه را در `script_ids: [...]` بگذارید — `round-robin` و `parallel-relay` همچنان روی همه‌شان کار می‌کند.

assets/cloudflare/README.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mhrv-rs ──► Apps Script (Code.cfw.gs) ──► Cloudflare Worker ──
99
▲ thin auth + forward ▲ outbound fetch + base64
1010
```
1111

12-
The standard backend (`assets/apps_script/Code.gs`) does the outbound fetch from inside Apps Script directly. This variant makes Apps Script a thin relay and pushes the actual fetch to Cloudflare's edge. **mhrv-rs itself is unchanged** — same JSON envelope on the wire, same `mode: "apps_script"` in `config.json`, same `script_id`. The only thing that's different is what your deployed Apps Script does after it authenticates the request.
12+
The standard backend (`assets/apps_script/Code.gs`) does the outbound fetch from inside Apps Script directly. This variant makes Apps Script a thin relay and pushes the actual fetch to Cloudflare's edge. **mhrv-rs itself is unchanged** — same JSON envelope on the wire, same `mode = "apps_script"` in `config.toml`, same `script_id`. The only thing that's different is what your deployed Apps Script does after it authenticates the request.
1313

1414
Original idea: <https://github.com/denuitt1/mhr-cfw>. This copy adds an `AUTH_KEY` check on the Worker, the decoy-on-bad-auth treatment from `Code.gs`, and a hop-loop guard.
1515

@@ -26,7 +26,7 @@ Original idea: <https://github.com/denuitt1/mhr-cfw>. This copy adds an `AUTH_KE
2626

2727
## Setup
2828

29-
You need three matching strings: an `AUTH_KEY` shared between `worker.js`, `Code.cfw.gs`, and your `mhrv-rs` `config.json`. Pick a strong random secret once and paste it into all three.
29+
You need three matching strings: an `AUTH_KEY` shared between `worker.js`, `Code.cfw.gs`, and your mhrv-rs `config.toml`. Pick a strong random secret once and paste it into all three.
3030

3131
### 1. Deploy the Worker
3232

@@ -47,14 +47,13 @@ You need three matching strings: an `AUTH_KEY` shared between `worker.js`, `Code
4747

4848
### 3. Point mhrv-rs at the Apps Script
4949

50-
In `config.json` (or via the UI's config form):
50+
In `config.toml` (or via the UI's config form):
5151

52-
```json
53-
{
54-
"mode": "apps_script",
55-
"script_id": "PASTE_DEPLOYMENT_ID_HERE",
56-
"auth_key": "SAME_SECRET_AS_BOTH_FILES_ABOVE"
57-
}
52+
```toml
53+
[relay]
54+
mode = "apps_script"
55+
auth_key = "YOUR_SHARED_SECRET"
56+
script_ids = ["YOUR_DEPLOYMENT_ID"]
5857
```
5958

6059
That's it. mhrv-rs doesn't need to know Cloudflare exists; from its perspective, the `script_id` deployment behaves like any other. If you have multiple deployments (some plain, some CFW), `script_ids: [...]` round-robins across all of them and the parallel-relay fan-out still works.

assets/cloudflare/worker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
* 1. Cloudflare dashboard → Workers & Pages → Create → Hello World
5858
* 2. Edit code → delete the template, paste this entire file
5959
* 3. Change AUTH_KEY below to the same value you set in Code.cfw.gs
60-
* AND in your mhrv-rs config.json (auth_key). All three must match.
60+
* AND in your mhrv-rs config.toml (auth_key). All three must match.
6161
* 4. Deploy. Note the *.workers.dev URL; paste it into Code.cfw.gs as
6262
* WORKER_URL.
6363
*

assets/exit_node/README.fa.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,14 @@ APIهای web-standard (`Request`، `Response`، `fetch`) استفاده می‌
6565
جلوی serve شدن به‌عنوان open relay accidentally گرفته بشه.
6666
۲. فایل رو روی host انتخابی **deploy** کنید (گزینه‌ها در ادامه).
6767
۳. URL public deployment رو **copy** کنید.
68-
۴. در `config.json` mhrv-rs، block `exit_node` اضافه کنید:
69-
```json
70-
"exit_node": {
71-
"enabled": true,
72-
"relay_url": "https://your-deployed-exit-node.example.com",
73-
"psk": "<همان PSK که در گام ۱ گذاشتید>",
74-
"mode": "selective",
75-
"hosts": ["chatgpt.com", "claude.ai", "x.com", "grok.com", "openai.com"]
76-
}
68+
۴. در `config.toml` mhrv-rs، section `[exit_node]` اضافه کنید:
69+
```toml
70+
[exit_node]
71+
enabled = true
72+
relay_url = "https://your-deployed-exit-node.example.com"
73+
psk = "<همان PSK که در گام ۱ گذاشتید>"
74+
mode = "selective"
75+
hosts = ["chatgpt.com", "claude.ai", "x.com", "grok.com", "openai.com"]
7776
```
7877
۵. mhrv-rs رو **restart** کنید (Disconnect + Connect، یا `kill` +
7978
restart binary).
@@ -127,7 +126,7 @@ PSK تنها چیز است که مانع می‌شه endpoint deployed یک publ
127126
- **publicly share نکنید** PSK رو. هر کسی که هم URL هم PSK رو داره
128127
می‌تونه quota host شما رو به‌عنوان proxy خود استفاده کنه.
129128
- **rotate** اگر leak مشکوک هست. PSK رو در source deployed تغییر بدید،
130-
redeploy کنید، سپس `psk` در `config.json` mhrv-rs رو update + restart.
129+
redeploy کنید، سپس `psk` در `config.toml` mhrv-rs رو update + restart.
131130

132131
اسکریپت همچنین شامل **loop guard** هست (refuse می‌کنه fetch host خود)
133132
+ **placeholder check** (در صورت `PSK === "CHANGE_ME_TO_A_STRONG_SECRET"`
@@ -147,7 +146,7 @@ Grok اهمیت می‌دن opt in؛ همه‌ی دیگران lighter اجرا
147146
## Troubleshooting
148147

149148
**`exit node refused or errored: unauthorized`** — PSK mismatch.
150-
بررسی کنید `psk` در `config.json` دقیقاً با `PSK` constant در source
149+
بررسی کنید `psk` در `config.toml` دقیقاً با `PSK` constant در source
151150
deployed match هست. whitespace + quoting مهم است.
152151

153152
**`exit node refused or errored: exit_node misconfigured: PSK is still

0 commit comments

Comments
 (0)