refactor: remove Val Town references and update exit node documentation

This commit is contained in:
Abolfazl
2026-05-04 22:46:37 +03:30
parent 2afdf3c7bb
commit b3df1d3828
6 changed files with 56 additions and 158 deletions
+10 -12
View File
@@ -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
View File
@@ -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 (هرگز به اشتراک نگذارید)
-88
View File
@@ -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 });
}
}
+8 -22
View File
@@ -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`
+29 -19
View File
@@ -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‌شده از نود خروجی عبور می‌کند.
+1 -7
View File
@@ -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(