mirror of
https://github.com/masterking32/MasterHttpRelayVPN.git
synced 2026-05-17 21:24:37 +03:00
refactor: remove Val Town references and update exit node documentation
This commit is contained in:
@@ -174,15 +174,14 @@ Some websites block Google datacenter IPs when traffic exits directly from Apps
|
||||
To fix that, configure an exit node so traffic path becomes:
|
||||
|
||||
```text
|
||||
Browser -> Local Proxy -> Apps Script -> Exit Node (Val Town / Cloudflare / Deno) -> Target website
|
||||
Browser -> Local Proxy -> Apps Script -> Exit Node (Cloudflare / Deno / VPS) -> Target website
|
||||
```
|
||||
|
||||
You can deploy any one of these free exit-node templates:
|
||||
You can deploy any one of these exit-node backends:
|
||||
|
||||
1. Val Town: [`apps_script/valtown.ts`](apps_script/valtown.ts)
|
||||
2. Cloudflare Workers: [`apps_script/cloudflare_worker.js`](apps_script/cloudflare_worker.js)
|
||||
3. Deno Deploy: [`apps_script/deno_deploy.ts`](apps_script/deno_deploy.ts)
|
||||
4. Your own VPS server
|
||||
1. Cloudflare Workers: [`apps_script/cloudflare_worker.js`](apps_script/cloudflare_worker.js)
|
||||
2. Deno Deploy: [`apps_script/deno_deploy.ts`](apps_script/deno_deploy.ts)
|
||||
3. Your own VPS server
|
||||
|
||||
Full step-by-step deployment guide (all providers):
|
||||
- [docs/exit-node/EXIT_NODE_DEPLOYMENT.md](docs/exit-node/EXIT_NODE_DEPLOYMENT.md)
|
||||
@@ -194,8 +193,8 @@ Then configure provider switching like this:
|
||||
```json
|
||||
"exit_node": {
|
||||
"enabled": true,
|
||||
"provider": "valtown",
|
||||
"url": "https://YOUR-NAME.web.val.run",
|
||||
"provider": "cloudflare",
|
||||
"url": "https://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev",
|
||||
"psk": "CHANGE_ME_TO_A_STRONG_SECRET",
|
||||
"mode": "full",
|
||||
"hosts": [
|
||||
@@ -218,7 +217,7 @@ Production recommendation:
|
||||
- Keep `verify_ssl: true`
|
||||
- Keep `listen_host: 127.0.0.1` unless LAN sharing is explicitly needed
|
||||
- Rotate both secrets periodically
|
||||
- Never publish your live val URL with valid PSK
|
||||
- Never publish your live exit-node URL with valid PSK
|
||||
|
||||
### Step 4: Run
|
||||
|
||||
@@ -311,7 +310,7 @@ By default, the proxy only listens on `127.0.0.1` (localhost), meaning only your
|
||||
|
||||
## Modes Overview
|
||||
|
||||
This project is centered on the **Apps Script** relay (free, no VPS needed). For destinations that block Google egress, you can optionally chain a free edge exit node (Val Town, Cloudflare Workers, or Deno Deploy).
|
||||
This project is centered on the **Apps Script** relay (free, no VPS needed). For destinations that block Google egress, you can optionally chain an edge exit node (Cloudflare Workers, Deno Deploy, or your own VPS).
|
||||
|
||||
---
|
||||
|
||||
@@ -350,7 +349,7 @@ This project is centered on the **Apps Script** relay (free, no VPS needed). For
|
||||
| `direct_google_exclude` | see [config.example.json](config.example.json) | Google apps that must use the MITM relay path instead of the fast direct tunnel. |
|
||||
| `hosts` | `{}` | Manual DNS override: map a hostname to a specific IP. |
|
||||
| `youtube_via_relay` | `false` | Route YouTube (`youtube.com`, `youtu.be`, `youtube-nocookie.com`) through the Apps Script relay instead of the SNI-rewrite path. The SNI-rewrite path uses Google's frontend IP which enforces SafeSearch and can cause **"Video Unavailable"** errors. Setting this to `true` fixes playback at the cost of using more Apps Script executions and slightly higher latency. |
|
||||
| `exit_node.provider` | `valtown` | Selected exit-node backend: `valtown`, `cloudflare`, `deno`, or `custom`. |
|
||||
| `exit_node.provider` | `cloudflare` | Selected exit-node backend: `cloudflare`, `deno`, `vps`, or `custom`. |
|
||||
| `exit_node.url` | `""` | Beginner-friendly single URL for the selected provider. |
|
||||
|
||||
### Optional Dependencies
|
||||
@@ -472,7 +471,6 @@ MasterHttpRelayVPN/
|
||||
├── requirements.txt # Python dependencies
|
||||
├── apps_script/
|
||||
│ ├── Code.gs # The relay script you deploy to Google Apps Script
|
||||
│ ├── valtown.ts # Exit node template for val.town
|
||||
│ ├── cloudflare_worker.js # Exit node template for Cloudflare Workers
|
||||
│ └── deno_deploy.ts # Exit node template for Deno Deploy
|
||||
├── ca/ # Generated MITM CA (do NOT share)
|
||||
|
||||
+8
-10
@@ -137,15 +137,14 @@ cp config.example.json config.json
|
||||
برای حل این مورد، نود خروجی (exit node) را فعال کنید تا مسیر اینگونه شود:
|
||||
|
||||
```text
|
||||
مرورگر -> پراکسی محلی -> Apps Script -> Exit Node (Val Town / Cloudflare / Deno) -> سایت مقصد
|
||||
مرورگر -> پراکسی محلی -> Apps Script -> Exit Node (Cloudflare / Deno / VPS) -> سایت مقصد
|
||||
```
|
||||
|
||||
میتوانید یکی از این template های رایگان را deploy کنید:
|
||||
میتوانید یکی از این backend های نود خروجی را deploy کنید:
|
||||
|
||||
1. Val Town: [apps_script/valtown.ts](apps_script/valtown.ts)
|
||||
2. Cloudflare Workers: [apps_script/cloudflare_worker.js](apps_script/cloudflare_worker.js)
|
||||
3. Deno Deploy: [apps_script/deno_deploy.ts](apps_script/deno_deploy.ts)
|
||||
4. سرور VPS شخصی
|
||||
1. Cloudflare Workers: [apps_script/cloudflare_worker.js](apps_script/cloudflare_worker.js)
|
||||
2. Deno Deploy: [apps_script/deno_deploy.ts](apps_script/deno_deploy.ts)
|
||||
3. سرور VPS شخصی
|
||||
|
||||
راهنمای کامل مرحلهبهمرحله برای هر provider:
|
||||
- [docs/exit-node/EXIT_NODE_DEPLOYMENT_FA.md](docs/exit-node/EXIT_NODE_DEPLOYMENT_FA.md) (فارسی)
|
||||
@@ -158,8 +157,8 @@ cp config.example.json config.json
|
||||
```json
|
||||
"exit_node": {
|
||||
"enabled": true,
|
||||
"provider": "valtown",
|
||||
"url": "https://YOUR-NAME.web.val.run",
|
||||
"provider": "cloudflare",
|
||||
"url": "https://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev",
|
||||
"psk": "CHANGE_ME_TO_A_STRONG_SECRET",
|
||||
"mode": "full",
|
||||
"hosts": [
|
||||
@@ -294,7 +293,7 @@ json
|
||||
| `bypass_hosts` | `["localhost", ".local", ".lan", ".home.arpa"]` | هاستهایی که مستقیم میروند (بدون MITM و بدون رله). برای منابع داخلی شبکه یا سایتهایی که با MITM مشکل دارند. |
|
||||
| `direct_google_exclude` | مراجعه به [config.example.json](config.example.json) | اپهای Google که باید از مسیر MITM برای رله استفاده کنند بهجای tunnel مستقیم. |
|
||||
| `youtube_via_relay` | `false` | مسیردهی YouTube (`youtube.com`، `youtu.be`، `youtube-nocookie.com`) از طریق رله Apps Script بهجای مسیر SNI-rewrite. مسیر SNI-rewrite از IP فرانتاند Google عبور میکند که SafeSearch را اجباری میکند و میتواند باعث خطای **«ویدیو در دسترس نیست»** شود. با فعال کردن این گزینه، پخش ویدیو درست میشود اما تعداد اجراهای Apps Script بیشتر و تأخیر اندکی بالاتر میرود. |
|
||||
| `exit_node.provider` | `valtown` | backend انتخابشده برای exit node: `valtown`، `cloudflare`، `deno` یا `custom`. |
|
||||
| `exit_node.provider` | `cloudflare` | backend انتخابشده برای exit node: `cloudflare`، `deno`، `vps` یا `custom`. |
|
||||
| `exit_node.url` | `""` | آدرس ساده و اصلی برای provider انتخابشده. |
|
||||
|
||||
### وابستگیهای اختیاری
|
||||
@@ -411,7 +410,6 @@ MasterHttpRelayVPN/
|
||||
├── requirements.txt # وابستگیهای اختیاری پایتون
|
||||
├── apps_script/
|
||||
│ ├── Code.gs # اسکریپت رله روی Google Apps Script
|
||||
│ ├── valtown.ts # template نود خروجی برای val.town
|
||||
│ ├── cloudflare_worker.js # template نود خروجی برای Cloudflare Workers
|
||||
│ └── deno_deploy.ts # template نود خروجی برای Deno Deploy
|
||||
├── ca/ # گواهی MITM (هرگز به اشتراک نگذارید)
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
const PSK = "CHANGE_ME_TO_A_STRONG_SECRET";
|
||||
|
||||
const STRIP_HEADERS = new Set([
|
||||
"host",
|
||||
"connection",
|
||||
"content-length",
|
||||
"transfer-encoding",
|
||||
"proxy-connection",
|
||||
"proxy-authorization",
|
||||
"x-forwarded-for",
|
||||
"x-forwarded-host",
|
||||
"x-forwarded-proto",
|
||||
"x-forwarded-port",
|
||||
"x-real-ip",
|
||||
"forwarded",
|
||||
"via",
|
||||
]);
|
||||
|
||||
function decodeBase64ToBytes(input: string): Uint8Array {
|
||||
const bin = atob(input);
|
||||
const out = new Uint8Array(bin.length);
|
||||
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
||||
return out;
|
||||
}
|
||||
|
||||
function encodeBytesToBase64(bytes: Uint8Array): string {
|
||||
let bin = "";
|
||||
for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
|
||||
return btoa(bin);
|
||||
}
|
||||
|
||||
function sanitizeHeaders(h: unknown): Record<string, string> {
|
||||
const out: Record<string, string> = {};
|
||||
if (!h || typeof h !== "object") return out;
|
||||
for (const [k, v] of Object.entries(h as Record<string, unknown>)) {
|
||||
if (!k) continue;
|
||||
if (STRIP_HEADERS.has(k.toLowerCase())) continue;
|
||||
out[k] = String(v ?? "");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export default async function(req: Request): Promise<Response> {
|
||||
try {
|
||||
if (req.method !== "POST") {
|
||||
return Response.json({ e: "method_not_allowed" }, { status: 405 });
|
||||
}
|
||||
|
||||
const body = await req.json();
|
||||
if (!body || typeof body !== "object") {
|
||||
return Response.json({ e: "bad_json" }, { status: 400 });
|
||||
}
|
||||
|
||||
const k = String((body as any).k ?? "");
|
||||
const u = String((body as any).u ?? "");
|
||||
const m = String((body as any).m ?? "GET").toUpperCase();
|
||||
const h = sanitizeHeaders((body as any).h);
|
||||
const b64 = (body as any).b;
|
||||
|
||||
if (k !== PSK) return Response.json({ e: "unauthorized" }, { status: 401 });
|
||||
if (!/^https?:\/\//i.test(u)) return Response.json({ e: "bad url" }, { status: 400 });
|
||||
|
||||
let payload: Uint8Array | undefined;
|
||||
if (typeof b64 === "string" && b64.length > 0) payload = decodeBase64ToBytes(b64);
|
||||
|
||||
const resp = await fetch(u, {
|
||||
method: m,
|
||||
headers: h,
|
||||
body: payload,
|
||||
redirect: "manual",
|
||||
});
|
||||
|
||||
const data = new Uint8Array(await resp.arrayBuffer());
|
||||
const respHeaders: Record<string, string> = {};
|
||||
resp.headers.forEach((value, key) => {
|
||||
respHeaders[key] = value;
|
||||
});
|
||||
|
||||
return Response.json({
|
||||
s: resp.status,
|
||||
h: respHeaders,
|
||||
b: encodeBytesToBase64(data),
|
||||
});
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
return Response.json({ e: message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
# Exit Node Deployment Guide (Val Town / Cloudflare / Deno / VPS)
|
||||
# Exit Node Deployment Guide (Cloudflare / Deno / VPS)
|
||||
|
||||
This guide explains how to deploy an exit node for MasterHttpRelayVPN on free platforms or your own VPS server.
|
||||
|
||||
@@ -10,7 +10,6 @@ Use this when destinations block Google datacenter egress.
|
||||
|
||||
## 1) Choose One Provider
|
||||
|
||||
- Val Town (free, no server required)
|
||||
- Cloudflare Workers (free tier available)
|
||||
- Deno Deploy (free, not fully tested)
|
||||
- **Your Own VPS** (full control, Linux server — automated installer included)
|
||||
@@ -29,19 +28,7 @@ Important:
|
||||
- Use the same PSK in your local config under exit_node.psk.
|
||||
- Never share your deployed URL together with a valid PSK.
|
||||
|
||||
## 3) Deploy On Val Town
|
||||
|
||||
Source file: apps_script/valtown.ts
|
||||
|
||||
Steps:
|
||||
1. Sign in at https://www.val.town
|
||||
2. Create a new Val (TypeScript HTTP endpoint).
|
||||
3. Paste content from apps_script/valtown.ts.
|
||||
4. Set the PSK constant in the code.
|
||||
5. Save and Add HTTP trigger.
|
||||
6. Copy your public URL, usually like https://YOUR-NAME.web.val.run
|
||||
|
||||
## 4) Deploy On Cloudflare Workers
|
||||
## 3) Deploy On Cloudflare Workers
|
||||
|
||||
Source file: apps_script/cloudflare_worker.js
|
||||
|
||||
@@ -54,7 +41,7 @@ Steps:
|
||||
6. Deploy.
|
||||
7. Copy URL, usually like https://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev
|
||||
|
||||
## 5) Deploy On Deno Deploy (It's not tested Yet)
|
||||
## 4) Deploy On Deno Deploy (It's not tested Yet)
|
||||
|
||||
Source file: apps_script/deno_deploy.ts
|
||||
|
||||
@@ -66,7 +53,7 @@ Steps:
|
||||
5. Deploy.
|
||||
6. Copy URL, usually like https://YOUR-PROJECT.deno.net
|
||||
|
||||
## 6) Deploy On Your Own VPS (Linux only)
|
||||
## 5) Deploy On Your Own VPS (Linux only)
|
||||
|
||||
Source files:
|
||||
- `apps_script/vps_exit_node.py` — the relay server
|
||||
@@ -94,16 +81,16 @@ The script automatically downloads `vps_exit_node.py` from GitHub, so no `git cl
|
||||
Note:
|
||||
- To rotate the PSK, edit `/etc/exit-node.env` and restart: `systemctl restart exit-node`.
|
||||
|
||||
## 7) Configure MasterHttpRelayVPN
|
||||
## 6) Configure MasterHttpRelayVPN
|
||||
|
||||
Update `config.json`:
|
||||
|
||||
For Val Town / Cloudflare / Deno:
|
||||
For Cloudflare / Deno:
|
||||
```json
|
||||
"exit_node": {
|
||||
"enabled": true,
|
||||
"provider": "valtown",
|
||||
"url": "https://YOUR-NAME.web.val.run",
|
||||
"provider": "cloudflare",
|
||||
"url": "https://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev",
|
||||
"psk": "CHANGE_ME_TO_A_STRONG_SECRET",
|
||||
"mode": "full",
|
||||
"hosts": [
|
||||
@@ -133,7 +120,6 @@ For your own VPS:
|
||||
```
|
||||
|
||||
Provider values:
|
||||
- `valtown`
|
||||
- `cloudflare`
|
||||
- `deno`
|
||||
- `vps`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# راهنمای نصب نود خروجی (Val Town / Cloudflare / Deno)
|
||||
# راهنمای نصب نود خروجی (Cloudflare / Deno / VPS)
|
||||
|
||||
این راهنما توضیح میدهد چطور یک نود خروجی رایگان برای MasterHttpRelayVPN راهاندازی کنید.
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
|
||||
## ۱) یک Provider انتخاب کنید
|
||||
|
||||
- Val Town
|
||||
- Cloudflare Workers
|
||||
- Deno Deploy
|
||||
- VPS شخصی
|
||||
|
||||
فقط به یکی از اینها نیاز دارید.
|
||||
|
||||
@@ -32,19 +32,7 @@ const PSK = "CHANGE_ME_TO_A_STRONG_SECRET";
|
||||
- همین PSK را در `config.json` زیر `exit_node.psk` وارد کنید.
|
||||
- URL عمومی را هرگز همراه با PSK معتبر به اشتراک نگذارید.
|
||||
|
||||
## ۳) نصب روی Val Town
|
||||
|
||||
فایل: `apps_script/valtown.ts`
|
||||
|
||||
مراحل:
|
||||
1. در [https://www.val.town](https://www.val.town) ثبتنام کنید.
|
||||
2. یک Val جدید بسازید (TypeScript HTTP endpoint).
|
||||
3. محتوای `apps_script/valtown.ts` را paste کنید.
|
||||
4. مقدار ثابت PSK را در کد تنظیم کنید.
|
||||
5. ذخیره و deploy کنید. (Add HTTP trigger را فراموش نکنید)
|
||||
6. URL عمومی خود را کپی کنید؛ معمولاً به شکل `https://YOUR-NAME.web.val.run`
|
||||
|
||||
## ۴) نصب روی Cloudflare Workers
|
||||
## ۳) نصب روی Cloudflare Workers
|
||||
|
||||
فایل: `apps_script/cloudflare_worker.js`
|
||||
|
||||
@@ -57,7 +45,7 @@ const PSK = "CHANGE_ME_TO_A_STRONG_SECRET";
|
||||
6. Deploy کنید.
|
||||
7. URL را کپی کنید؛ معمولاً به شکل `https://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev`
|
||||
|
||||
## ۵) نصب روی Deno Deploy (هنوز تست نشده)
|
||||
## ۴) نصب روی Deno Deploy (هنوز تست نشده)
|
||||
|
||||
فایل: `apps_script/deno_deploy.ts`
|
||||
|
||||
@@ -70,6 +58,28 @@ const PSK = "CHANGE_ME_TO_A_STRONG_SECRET";
|
||||
6. Deploy کنید.
|
||||
7. URL را کپی کنید؛ معمولاً به شکل `https://YOUR-PROJECT.deno.dev`
|
||||
|
||||
## ۵) نصب روی VPS شخصی (فقط Linux)
|
||||
|
||||
فایلها:
|
||||
- `apps_script/vps_exit_node.py` (سرور نود خروجی)
|
||||
- `apps_script/setup_vps_exit_node.sh` (نصب خودکار - پیشنهادی)
|
||||
|
||||
نیازمندیها:
|
||||
- یک VPS لینوکسی با دسترسی root/sudo
|
||||
- Python 3.10+
|
||||
|
||||
دستور نصب سریع:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/masterking32/MasterHttpRelayVPN/python_testing/apps_script/setup_vps_exit_node.sh | sudo bash
|
||||
```
|
||||
|
||||
یا:
|
||||
|
||||
```bash
|
||||
wget -qO- https://raw.githubusercontent.com/masterking32/MasterHttpRelayVPN/python_testing/apps_script/setup_vps_exit_node.sh | sudo bash
|
||||
```
|
||||
|
||||
## ۶) تنظیم MasterHttpRelayVPN
|
||||
|
||||
فایل `config.json` را ویرایش کنید:
|
||||
@@ -77,8 +87,8 @@ const PSK = "CHANGE_ME_TO_A_STRONG_SECRET";
|
||||
```json
|
||||
"exit_node": {
|
||||
"enabled": true,
|
||||
"provider": "valtown",
|
||||
"url": "https://YOUR-NAME.web.val.run",
|
||||
"provider": "cloudflare",
|
||||
"url": "https://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev",
|
||||
"psk": "CHANGE_ME_TO_A_STRONG_SECRET",
|
||||
"mode": "full",
|
||||
"hosts": [
|
||||
@@ -91,9 +101,9 @@ const PSK = "CHANGE_ME_TO_A_STRONG_SECRET";
|
||||
```
|
||||
|
||||
مقادیر provider:
|
||||
- `valtown`
|
||||
- `cloudflare`
|
||||
- `deno`
|
||||
- `vps`
|
||||
|
||||
اگر `mode` برابر `selective` باشد، فقط دامنههای داخل `hosts` از نود خروجی عبور میکنند.
|
||||
اگر `mode` برابر `full` باشد، تمام ترافیک relayشده از نود خروجی عبور میکند.
|
||||
|
||||
@@ -1116,8 +1116,6 @@ class DomainFronter:
|
||||
def _normalize_exit_node_provider(raw: object) -> str:
|
||||
provider = str(raw or "custom").strip().lower()
|
||||
aliases = {
|
||||
"val": "valtown",
|
||||
"val-town": "valtown",
|
||||
"cloudflare_worker": "cloudflare",
|
||||
"worker": "cloudflare",
|
||||
"cf": "cloudflare",
|
||||
@@ -1150,11 +1148,7 @@ class DomainFronter:
|
||||
if direct:
|
||||
return direct
|
||||
|
||||
if provider == "valtown":
|
||||
selected = _pick_from(en_cfg, "valtown_url", "val_url") or _pick_from(
|
||||
providers, "valtown", "val_town", "val",
|
||||
)
|
||||
elif provider == "cloudflare":
|
||||
if provider == "cloudflare":
|
||||
selected = _pick_from(
|
||||
en_cfg, "cloudflare_url", "worker_url", "cf_url",
|
||||
) or _pick_from(
|
||||
|
||||
Reference in New Issue
Block a user