mhr-cfw README

The project's README from github.com/denuitt1/mhr-cfw. As one markdown file: README.md.

MHR-CFW

MITM Domain-Fronted HTTP Relay + Cloudflare Worker Exit

GitHub

English Persian

How It Works

1 - GAS + Cloudflare Worker Exit

Client -> Local Relay -> Google/CDN Front -> GAS (Google Apps Script) Relay -> Cloudflare Worker -> Exit
            |
            +-> Shows www.google.com to network DPI filter

2 - GAS + Cloudflare Worker Middle + Self-Hosted Upstream Forwarder Relay Exit

Client -> Local Relay -> Google/CDN Front -> GAS (Google Apps Script) Relay -> Cloudflare Worker -> Self-Hosted Upstream Forwarder -> Exit
            |
            +-> Shows www.google.com to network DPI filter

In normal use, the browser sends traffic to the proxy running on your computer. The proxy sends that traffic through Google-facing infrastructure so the network only sees an allowed domain such as www.google.com. Your deployed relay then fetches the real website through cloudflare worker and sends the response back through the same path.

This means the filter sees normal-looking Google traffic, while the actual destination stays hidden inside the relay request.


How to Use

1 - Download project and extract

git clone https://github.com/denuitt1/mhr-cfw.git
cd mhr-cfw
pip install -r requirements.txt

Can't reach PyPI directly? Use this mirror instead:

pip install -r requirements.txt -i https://mirror-pypi.runflare.com/simple/ --trusted-host mirror-pypi.runflare.com

2 - Set Up the Cloudflare Worker (worker.js)

  1. Open Cloudflare Dashboard and sign in with your Cloudflare account.
  2. From the sidebar, navigate to Compute > Workers & Pages
  3. Click Create Application, Choose Start with Hello World and click on Deploy
  4. Click on Edit code and Delete all the default code in the editor.
  5. Open the worker.js file from this project (under deploy/), copy everything, and paste it into the Apps Script editor.
  6. Important: Change the worker on this line to the worker you created:
    const WORKER_URL = "myworker.workers.dev";
    
  7. Click Deploy.

3 - Set Up the Google Relay (Code.gs)

  1. Open Google Apps Script and sign in with your Google account.
  2. Click New project.
  3. Delete all the default code in the editor.
  4. Open the Code.gs file from this project (under deploy/), copy everything, and paste it into the Apps Script editor.
  5. Important: Change the password on this line to something only you know, also replace the worker url with your cloudflare worker:
    const AUTH_KEY = "your-secret-password-here";
    const WORKER_URL = "https://myworker.workers.dev";
    
  6. Click Deploy → New deployment.
  7. Choose Web app as the type.
  8. Set:
    • Execute as: Me
    • Who has access: Anyone
  9. Click Deploy.
  10. Copy the Deployment ID (it looks like a long random string). You'll need it in the next step.

⚠️ Remember the password you set in step 3. You'll use the same password in the config file below.

4 - Run

Click on the run.bat file (on windows) or run.sh file (on linux) to start the relay.

If you're running for the first time it will prompt a setup wizard where you have to enter the AUTH_KEY and Google Apps Script Deployment ID. You should see a message saying the HTTP proxy is running on 127.0.0.1:8085

5 - Usage

We recommend using v2rayN client and configuring a socks5 proxy.

You can also use FoxyProxy's Chrome extension or Firefox extension to use this proxy in your browser.

6 - Test your connection

Open ipleak.net in your browser, you should see your ip address set as cloudflare's.

image

7 - Additional Usage Guides

Using the Proxy Inside a Virtual Machine

When you run a virtual machine (VM), it operates in an isolated network environment separate from the host. By default, the VM cannot directly access services running on localhost of the host machine — including this proxy.

To fix this, you need to find the gateway IP that your hypervisor assigns to the host, then use it instead of localhost when configuring the proxy inside the VM.

Example: VirtualBox (NAT mode)

The host is always reachable from inside the VM at 10.0.2.2. Set the proxy:

export http_proxy="http://10.0.2.2:8085"
export https_proxy="http://10.0.2.2:8085"
export all_proxy="socks5://10.0.2.2:8085"

To make this permanent, add the lines above to ~/.bashrc and run source ~/.bashrc.

Since this proxy performs SSL inspection, you may see certificate errors. Install the included ca.crt to fix them:

sudo cp ca.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates

Sharing the Proxy Over a Local Network (e.g. Mobile Devices)

You can use this proxy on your phone or any other device on the same network — no extra software needed.

1. Find your host IP

# Windows
ipconfig
 
# Linux / macOS
ip addr

Look for the IP of the adapter connected to your router (e.g. 192.168.1.8).

2. Forward the port (Windows only, if the service is bound to localhost)

Run CMD as Administrator:

netsh interface portproxy add v4tov4 listenaddress=192.168.1.8 listenport=8085 connectaddress=127.0.0.1 connectport=8085
netsh advfirewall firewall add rule name="Proxy 8085" dir=in action=allow protocol=TCP localport=8085

3. Configure proxy on your phone

Connect your phone to the same Wi-Fi, then set the proxy manually:

On Android: Settings → Wi-Fi → Modify → Proxy → Manual
On iPhone: Settings → Wi-Fi → (network) → HTTP Proxy → Manual

4. Install the CA certificate

Transfer ca.crt to your phone, then:


Optional: Stable Exit IP via Upstream Forwarder

CAPTCHAs (Cloudflare Turnstile/bot challenge, reCAPTCHA, hCaptcha) bind tokens to the IP that solved the challenge. Cloudflare Workers exit through different edge IPs per request, so verification on the target site fails even when you solve the challenge. This optional add-on lets the Worker forward all fetch() calls through a small Node server you run on a VPS with a stable IP — giving the target site one consistent exit address.

When you need this

If you don't hit these, leave it unconfigured — the Worker behaves exactly as before.

Why a separate server is required

Cloudflare Workers don't expose a stable outbound IP — fetch() exits through a rotating pool of Cloudflare edge IPs, which is exactly what breaks IP-bound CAPTCHA tokens. Cloudflare's static-egress options (BYOIP, Egress Workers) are Enterprise-tier, so a small VPS with a static IP is the practical workaround. The forwarder is just a thin proxy that re-issues the fetch() from a stable address.

1. Deploy the forwarder on a VPS

The reference implementation is deploy/upstream-forwarder/upstream_forwarder.js. It needs Node 18+ and no dependencies. Run it behind Caddy or nginx with TLS — the Worker rejects non-HTTPS forwarder URLs.

# On your VPS (Ubuntu/Debian example):
sudo apt install -y nodejs   # must be 18+
export AUTH_KEY="some-long-random-string-at-least-32-chars"
export PORT=8787
node deploy/upstream-forwarder/upstream_forwarder.js

Front it with Caddy for auto-TLS:

forwarder.example.com {
    reverse_proxy 127.0.0.1:8787
}

Quick smoke test:

curl -X POST https://forwarder.example.com/fwd \
  -H "x-upstream-auth: $AUTH_KEY" \
  -H "content-type: application/json" \
  -d '{"u":"https://httpbin.org/ip","m":"GET","h":{}}'

The decoded response body should show the VPS's IP.

2. Wire the Worker to the forwarder

In the Cloudflare dashboard → your Worker → Settings → Variables and Secrets:

Name Type Value
UPSTREAM_FORWARDER_URL Secret https://forwarder.example.com/fwd
UPSTREAM_AUTH_KEY Secret the same AUTH_KEY you set on the VPS
UPSTREAM_FAIL_MODE Variable closed (default) — return 502 on forwarder failure. Use open to fall back to direct fetch.
UPSTREAM_TIMEOUT_MS Variable (optional) default 25000

Save and redeploy the Worker.

3. Verify

Browse https://httpbin.org/ip through the proxy — you should see the VPS's IP, not Cloudflare's. Then revisit a CAPTCHA-protected site that wasn't working — the challenge should now validate.

The forwarder must require auth. Without AUTH_KEY it refuses to start. Anyone with the URL and key can use it as a relay, so keep both secret.

4. Scope the forwarder to specific hosts (optional)

By default every request the Worker handles routes through the forwarder, so unrelated traffic also burns VPS bandwidth. To send only the sites that need a stable exit IP through the VPS, list them in forwarder_hosts in config.json — same syntax as bypass_hosts (exact hostname or .suffix). Anything not matched falls back to direct fetch() on the Worker.

{
   ...
   "forwarder_hosts": [
       "example.com",
       ".cf-protected-suffix"
   ]
   ...
}

Leave the list empty (or remove the key) to keep the historical "forward everything" behavior.


Disclaimer

MHR-CFW is provided for educational, testing, and research purposes only.


Contributors


Sources


License

MIT

mhr-cfw (denuitt1/mhr-cfw)

Searching Database…

4.4K ·GitHub
这是什么?MHR-CFW 是一个域前置中继,它把你的流量伪装成对 Google 等被允许域名的请求,经由 Google Apps Script 和 Cloudflare Worker 转发后再去抓取真正的目标网站。它被设计用来绕过基于 DPI(深度包检测)的网络过滤。
这是浏览器扩展,还是我自己运行的本地代理?它是你在自己电脑上用 run.bat 或 run.sh 运行的本地代理,会在 127.0.0.1:8085 上提供一个 HTTP/SOCKS5 代理,你把浏览器或操作系统的网络设置指向它即可。
怎么把它跑起来?把 worker.js 部署为 Cloudflare Worker、把 Code.gs 部署为 Google Apps Script 网页应用以拿到部署 ID,然后运行 run.bat(Windows)或 run.sh(Linux);首次运行会出现设置向导,要求输入你的 AUTHKEY 和该部署 ID。
用这个需要 Cloudflare 和 Google 账号吗?需要——既需要一个免费的 Cloudflare 账号来部署 Worker,也需要一个 Google 账号来部署 Apps Script 中继;本地客户端本身是通过提供的批处理/shell 脚本运行的 Python 脚本。
在有验证码保护的网站上能用吗?默认情况下不太可靠——Cloudflare Worker 的出口是轮换的边缘 IP,这会破坏与 IP 绑定的验证码令牌(Turnstile、reCAPTCHA、hCaptcha),导致验证循环。在有静态 IP 的 VPS 上部署一个可选的上游转发器可以解决这个问题。
它会检查我的加密流量吗?会——该代理执行 SSL 检查(本地 MITM),所以你需要在电脑或手机上安装它自带的 CA 证书(ca.crt),以避免证书错误。
手机或其他设备上也能用这个代理吗?可以——把同一 Wi-Fi 网络下的设备指向你主机的 IP 的 8085 端口,并在这些设备上安装同一个 ca.crt 证书以避免 SSL 错误。
这个代理应该搭配什么客户端?README 推荐使用配置了 SOCKS5 代理的 v2rayN,或者 Chrome 和 Firefox 上的 FoxyProxy 之类浏览器扩展。
使用它合法吗?它仅以教育、测试和研究目的分发;遵守当地法律和 Google 的 Apps Script 服务条款由你自己负责。
怎么确认中继确实藏住了我的真实目标地址?连接后在浏览器里打开 ipleak.net——显示的 IP 应该是 Cloudflare 的,而不是你的真实 IP。
Creator
denuitt1
Size
0.2 MB
Stars
4.4K
Age
5mo
Commits · 90 Days