Files
therealaleph c12ffd4dd4 chore: redact val.town from code and docs, rename exit-node script
The val.town founder asked us not to promote using their service. This
commit removes every val.town reference from the codebase and rewrites
the exit-node guides to be platform-agnostic.

Changes:
- Renamed assets/exit_node/valtown.ts → assets/exit_node/exit_node.ts.
  TypeScript itself is unchanged — same web-standard Request/Response/
  fetch API that runs on any serverless runtime.
- Rewrote assets/exit_node/README.md and README.fa.md to recommend
  Deno Deploy as the primary host for users who want a free serverless
  TS endpoint, with fly.io and your-own-VPS as alternatives. CF Workers
  is explicitly called out as not-helpful (CF outbound is still on
  CF's flagged IP space).
- Updated all val.town mentions in source comments (src/config.rs,
  src/domain_fronter.rs, src/bin/ui.rs) to neutral wording.
- Updated config.exit-node.example.json `_comment` strings and the
  example URL.
- Updated main README.md FAQ entries (Persian + English) and
  docs/guide.md / docs/guide.fa.md.
- Old changelog files (v1.9.4 / v1.9.5 / v1.9.9) had val.town mentions
  retroactively replaced too — same redaction principle.
- Bumped to v1.9.10 with a changelog noting the rename + Telegram
  channel brief format from earlier today.

Users who already have an exit node deployed (on whichever host they
picked) don't need to change anything — the wire protocol is identical
and the renamed script is byte-identical to the old one.

Tests: 179 lib + 35 tunnel-node green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 19:11:56 +03:00

6.3 KiB

• exit node اختیاری برای دور زدن CF anti-bot روی ChatGPT / Claude / Grok / X (port از upstream masterking32/MasterHttpRelayVPN@464a6e1d, با hardening): سایت‌های پشت Cloudflare مانند chatgpt.com، claude.ai، grok.com، x.com، openai.com traffic از Google datacenter IPs (Apps Script's outbound IP space) رو به‌عنوان bot flag می‌کنن + Turnstile / CAPTCHA / 502 challenge برمی‌گردونن. تا v1.9.3 این "Relay error: json: key must be a string at line 2 column 1" یا 502 generic می‌داد + هیچ workaround در apps_script mode نبود. حالا یک endpoint TypeScript کوچک (assets/exit_node/exit_node.ts) روی Deno Deploy / fly.io deploy می‌شه + بین Apps Script + destination قرار می‌گیره. مسیر traffic: client → SNI rewrite → Apps Script (Google IP) → the exit node (non-Google IP) → destination. destination IP exit node رو می‌بینه، نه Google datacenter — heuristic anti-bot CF نمی‌سوزه + صفحه واقعی برمی‌گرده. leg user-side (Iran ISP → Apps Script) بدون تغییر — second hop کاملاً درون outbound Apps Script اجرا می‌شه، invisible از شبکه‌ی کاربر. config جدید:

"exit_node": {
  "enabled": true,
  "relay_url": "https://your-deployed-exit-node.example.com",
  "psk": "<openssl rand -hex 32>",
  "mode": "selective",
  "hosts": ["chatgpt.com", "claude.ai", "x.com", "grok.com", "openai.com"]
}

• Optional exit node to bypass CF anti-bot on ChatGPT / Claude / Grok / X (ported from upstream masterking32/MasterHttpRelayVPN@464a6e1d, with hardening): Cloudflare-fronted services like chatgpt.com, claude.ai, grok.com, x.com, openai.com flag traffic from Google datacenter IPs (Apps Script's outbound IP space) as bots and return Turnstile / CAPTCHA / 502 challenges. Through v1.9.3 this surfaced as "Relay error: json: key must be a string at line 2 column 1" or generic 502 with no apps_script-mode workaround. Now a small TypeScript HTTP endpoint (assets/exit_node/exit_node.ts) deployed on Deno Deploy / fly.io sits between Apps Script and the destination. Traffic chain: client → SNI rewrite → Apps Script (Google IP) → the exit node (non-Google IP) → destination. The destination sees the exit node's IP, not Google datacenter — CF's anti-bot heuristic doesn't fire and the real page comes back. The user-side leg (Iran ISP → Apps Script) is unchanged — the second hop happens entirely inside Apps Script's outbound, invisible from the user's network, so the DPI evasion property mhrv-rs is built around stays intact. New config:

"exit_node": {
  "enabled": true,
  "relay_url": "https://your-deployed-exit-node.example.com",
  "psk": "<openssl rand -hex 32>",
  "mode": "selective",
  "hosts": ["chatgpt.com", "claude.ai", "x.com", "grok.com", "openai.com"]
}

Two modes: selective (default, only listed hosts route via exit node, recommended) or full (everything via exit node, slower). On exit-node failure, mhrv-rs falls back to direct Apps Script automatically — CF-affected sites fail in that case but everything else keeps working, so a down exit node doesn't take you fully offline. Hardening over upstream: PSK fail-closed if still the placeholder (fresh exit-node deploy can't accidentally serve as open relay until the user replaces the placeholder), loop guard (refuses to fetch its own host), explicit 503 on misconfigured deploys. Setup walkthrough in assets/exit_node/README.md (English) and README.fa.md (Persian). Complete example config at config.exit-node.example.json. • Removed the legacy telegram job from release.yml. Previously, with the TELEGRAM_NOTIFY_ENABLED repo variable flipped to true (which it had been), every release produced two duplicate APK posts on the main Telegram channel: the old release.yml job (universal APK + bundled changelog) and the newer telegram-publish-files.yml workflow (per-platform per-file posts to the files channel + a single cross-link to the main channel). Only the cross-link was wanted. The legacy job and its helper script .github/scripts/telegram_release_notify.py are gone. telegram-publish-files.yml is now the only Telegram path. The legacy bundled-on-main pattern is recoverable from git log if anyone ever wants it back.