بسیاری از سرویسهای پشت Cloudflare، traffic از رنج IP datacenter
گوگل را بهعنوان bot flag میکنن + بهجای صفحه واقعی یک Turnstile /
CAPTCHA / 502 challenge میفرستن. UrlFetchApp.fetch() در Apps
Script از همان رنج IP datacenter Google خروج میکنه، پس برای سایتهایی مانند:
- chatgpt.com / openai.com
- claude.ai
- grok.com / x.com
…مسیر apps_script-mode عادی mhrv-rs ارورهایی مثل
Relay error: json: key must be a string at line 2 column 1 یا
502 Relay error میده چون Code.gs در حال wrap کردن صفحهی HTML
challenge CF است که کلاینت نمیتونه parse کنه.
Exit node یک handler کوچک HTTP به زبان TypeScript است که روی یک پلتفرم serverless TypeScript که خودت تأییدش میکنی deploy میشه و بین Apps Script و destination قرار میگیره. مسیر traffic این میشه:
Browser ─┐ ┌─→ Destination
│ │ (chatgpt.com)
▼ │
mhrv-rs │
│ │
│ TLS به Google IP، SNI=www.google.com (DPI cover)│
▼ │
Apps Script (Google datacenter) │
│ │
│ UrlFetchApp.fetch(EXIT_NODE_URL) │
▼ │
exit node خودت (IP غیر گوگل) │
│ │
│ fetch(real_url) │
└──────────────────────────────────────────────────┘
Destination IP خروجی exit node رو میبینه، نه IP datacenter گوگل. Heuristic anti-bot CF نمیسوزه + صفحه واقعی برمیگرده.
نکته مهم: leg user-side (Iran ISP → Apps Script) بدون تغییر است. ISP فقط TLS به Google IP میبینه — second hop کاملاً درون outbound Apps Script اجرا میشه، invisible از شبکهی کاربر. پس DPI evasion property که mhrv-rs براش ساخته شده، دست نمیخوره.
handler در exit_node.ts plain TypeScript است که از
APIهای web-standard (Request، Response، fetch) استفاده میکنه و
روی هر پلتفرمی که serverless-fetch runtime داره اجرا میشه.
۱. فایل exit_node.ts رو باز کنید و PSK پیشفرض رو در
ابتدا عوض کنید:
const PSK = "<your-strong-secret>";Strong secret تولید کنید با openssl rand -hex 32 از terminal.
placeholder رو در production نگذارید — کد عمداً fail-closed است
(در هر request 503 برمیگردونه) تا placeholder replace نشده، تا
جلوی serve شدن بهعنوان open relay accidentally گرفته بشه.
۲. فایل رو روی host انتخابی deploy کنید (گزینهها در ادامه).
۳. URL public deployment رو copy کنید.
۴. در config.json mhrv-rs، block exit_node اضافه کنید:
"exit_node": {
"enabled": true,
"relay_url": "https://your-deployed-exit-node.example.com",
"psk": "<همان PSK که در گام ۱ گذاشتید>",
"mode": "selective",
"hosts": ["chatgpt.com", "claude.ai", "x.com", "grok.com", "openai.com"]
}۵. mhrv-rs رو restart کنید (Disconnect + Connect، یا kill +
restart binary).
۶. تست کنید — chatgpt.com یا grok.com رو از browser pointed به
mhrv-rs proxy باز کنید. صفحه login واقعی رو میبینید، نه CF
challenge.
config مثال کامل در
config.exit-node.example.json
در root repo.
اسکریپت یک فایل self-contained است. هر host که میتوانید signup کنید + بهاش اعتماد دارید رو انتخاب کنید:
| Host | توضیحات |
|---|---|
| Deno Deploy (deno.com/deploy) | free tier برای personal use کافی است. با deployctl deploy --prod exit_node.ts یا GitHub Actions deploy کنید. همان web-standard API. |
| fly.io | free tier با محدودیت. handler رو در یک server thin بستهبندی کنید (Deno.serve(handler) برای Deno یا یک Express wrapper برای Node) + Dockerfile اضافه کنید. IP دائم، region جغرافیایی قابل انتخاب. |
| VPS شخصی خودت | deno run --allow-net wrapper.ts که wrapper.ts کارش Deno.serve({ port: 8443 }, handler) است. حداکثر کنترل، ~۳-۵ دلار در ماه. |
| Cloudflare Workers | کمک نمیکنه. CF Workers از IP space خود CF خروج میکنن، که CF anti-bot هنوز بهعنوان worker-internal flag میکنه. |
برای اکثر کاربرانی که مسیر local رو اجرا میکنن، Deno Deploy سریعترین setup است. برای deployment طولانیمدت تحت کنترل کامل خودت، VPS کوچک شخصی ایدهآل است.
| Mode | چی میکنه | کی استفاده کنید |
|---|---|---|
selective (default) |
فقط hosts در hosts از طریق exit node میرن؛ بقیه از مسیر Apps Script عادی |
توصیه میشه. exit-node hop ~۲۰۰-۵۰۰ms به هر request اضافه میکنه — برای سایتهایی reserve کنید که نیاز به non-Google IP دارن. |
full |
همهی requestها از طریق exit node میرن | فقط زمانی که کل workload شما CF-anti-bot affected است، یا exit node خود سریعتر روی مسیر شبکه شما (rare). budget runtime host رو برای سایتهایی که نیاز ندارن میسوزونه. |
اگر exit node در دسترس نباشه، 5xx برمیگردونه، یا response malformed
بفرسته، mhrv-rs بهطور خودکار به Apps Script relay عادی fallback
میکنه. در log یک خط warn: exit node failed for ... — falling back to direct Apps Script میبینید. سایتهایی که نیاز به exit node دارن در آن
case fail میگیرن (CF challenge)، ولی سایر سایتها کار میکنن — یک
exit node down شما رو fully offline نمیکنه.
PSK تنها چیز است که مانع میشه endpoint deployed یک public open proxy بشه. مثل password برخورد کنید:
- commit نکنید PSK رو به source control. اکثر hostها بهطور default کد deployed رو private نگه میدارن؛ همانطور نگه دارید.
- publicly share نکنید PSK رو. هر کسی که هم URL هم PSK رو داره میتونه quota host شما رو بهعنوان proxy خود استفاده کنه.
- rotate اگر leak مشکوک هست. PSK رو در source deployed تغییر بدید،
redeploy کنید، سپس
pskدرconfig.jsonmhrv-rs رو update + restart.
اسکریپت همچنین شامل loop guard هست (refuse میکنه fetch host خود)
- placeholder check (در صورت
PSK === "CHANGE_ME_TO_A_STRONG_SECRET"return 503 میکنه) تا یک fresh deploy بدون setup نتونه بهطور accidentally بهعنوان open relay سرو بشه.
- ۲۰۰-۵۰۰ms به هر request اضافه میکنه (hop اضافی)
- budget bandwidth free-tier host رو میسوزونه
- برای سایتهایی که CF anti-bot ندارن benefit نداره
- Setup یک account جداگانه روی پلتفرم third-party میخواد
پس enabled: false default است. کاربرانی که خصوصاً به ChatGPT / Claude /
Grok اهمیت میدن opt in؛ همهی دیگران lighter اجرا میکنن.
exit node refused or errored: unauthorized — PSK mismatch.
بررسی کنید psk در config.json دقیقاً با PSK constant در source
deployed match هست. whitespace + quoting مهم است.
exit node refused or errored: exit_node misconfigured: PSK is still the placeholder — فراموش کردید CHANGE_ME_TO_A_STRONG_SECRET رو
در source جایگزین کنید. فایل deployed رو edit + save + redeploy کنید.
exit node failed for ...: connection refused — URL اشتباه است
یا deployment live نیست. با hit کردن URL مستقیم از browser verify
کنید — باید {"e":"method_not_allowed"} برگردونه (handler expects
POST).
exit node failed for ...: timeout — outbound host slow است
یا destination slow. region متفاوت رو امتحان کنید، یا latency
trade-off رو accept کنید.
سایت همچنان CF challenge نشون میده بعد از enable exit node — CF
IP host شما رو هم flag کرده. بعضی hosting providerها outbound IP
spaceشون روی CF bot blocklist است. workarounds: host دیگه امتحان
کنید (VPS شخصی شما clean IP میده)، یا سایت رو به passthrough_hosts
اضافه کنید (MITM رو bypass میکنه؛ از real IP ISP شما استفاده
میکنه).
- English version of this doc
exit_node.ts— منبع handler (با hardening)config.exit-node.example.json— config مثال کامل- Issue #382 — thread tracking canonical Cloudflare anti-bot
- Issue #309 — roadmap CF WARP integration (approach جایگزین، longer-horizon)