GooseRelayVPN
- title
- GooseRelayVPN
- type
- toolbox
- summary
- SOCKS5 VPN tunneling raw TCP through a Google Apps Script relay to a small VPS exit, with end-to-end AES-256-GCM so Google never sees plaintext
- tags
- go, proxy, vpn, censorship-circumvention, serverless-relay-transport, google-apps-script, domain-fronting, iran
- language
- Go
- license
- MIT
- created
- 2026-04-30
- updated
- 2026-04-30
GooseRelayVPN is the third entry in the small but interesting "Apps-Script-as-a-circumvention-relay" cluster, after masterhttprelayvpn (Python original) and masterhttprelayvpn-rust (Rust port). The author Kianmhz cites the original explicitly: "This project was inspired by the idea in the main repository: MasterHttpRelayVPN."
What's different here is the architecture. Where the MasterHttpRelay tools front HTTPS request-response traffic through Apps Script with a local MITM CA, GooseRelay tunnels raw TCP end-to-end with AES-256-GCM, requiring a small VPS exit server. Google sees only opaque encrypted bytes; the AES key never touches Google. This trades the "no infrastructure required" property of MasterHttpRelay for being able to carry SSH, IMAP, custom binary protocols, anything SOCKS5 can wrap.
Architecture
Browser/App
-> SOCKS5 (127.0.0.1:1080)
-> AES-256-GCM raw-TCP frames
-> HTTPS to Google edge IP (SNI=www.google.com, Host=script.google.com)
-> Apps Script doPost() (~30-line dumb forwarder, never sees plaintext)
-> Your VPS :8443/tunnel (decrypts, demuxes by session_id, dials target)
<- Same path in reverse via long-polling
Five moving parts:
- Local SOCKS5 listener (
goose-client) on the user's machine, port 1080 - AES-256-GCM frame encoder that wraps every TCP byte before it leaves
- Domain-fronted HTTPS connection to a Google edge IP (default 216.239.38.120) with
SNI=www.google.com,Host=script.google.comโ see domain-fronting - Google Apps Script web app (
Code.gs, ~30 lines) โ a dumb forwarder that POSTs the encrypted batch to the VPS - VPS exit server (
goose-server) on a $4/month Linux box โ decrypts, multiplexes by session ID, runs the actualnet.Dial
Two Go binaries: goose-client (run daily) and goose-server (run once on the VPS, systemd or NSSM). Apps Script is "Deploy as web app, anyone can access," with the deployment ID pasted into the client config.
Wire format
- Frame:
session_id (16) || seq (u64 BE) || flags (u8) || target_len (u8) || target || payload_len (u32 BE) || payload - Batch seal:
nonce (12) || AES-GCM(u16 frame_count || [u32 frame_len || frame_bytes]โฆ)โ one nonce + tag per HTTP body, not per frame - HTTP body:
base64(nonce || ciphertext+tag)(base64 so it survives Apps Script'sContentServicetext round-trip)
Authentication is the AES-GCM tag itself โ no shared password, no certificates. Frames that fail Open() are dropped silently. The 64-character hex tunnel_key is the entire trust anchor and must match byte-for-byte between client and server.
Multi-deployment scaling
Each Apps Script deployment is rate-limited to ~20,000 calls/day. The client supports an array of deployment IDs:
"script_keys": ["FIRST_ID", "SECOND_ID", "THIRD_ID"]
Round-robin across deployments. Health-aware blacklist with exponential backoff (3s, 6s, 12s, โฆ up to ~48s) on failures. Same-poll failover so one transient quota error doesn't drop traffic. README warns against more than 3-4 deployment IDs โ each adds 3 concurrent poll workers and going higher creates load without speed gains.
Setup cost
- One-time: $4/month Linux VPS, 64-char AES key from
scripts/gen-key.sh, two Go binaries, one Apps Script project + Deploy New Deployment with type "Web app" / access "Anyone" - Daily: run
./goose-clientand point browser at SOCKS5127.0.0.1:1080
The Apps Script step has the usual Google-deployment gotcha: every Code.gs edit requires a new deployment (Deploy โ New deployment, not just save), with the new deployment ID pasted back into the client config.
Tradeoffs
| GooseRelay | MasterHttpRelay (Python/Rust) | VLESS via xray-tutorial | |
|---|---|---|---|
| Server cost | $4/mo VPS required | Free (Google only) | $5/mo VPS minimum |
| Protocol | Any TCP via SOCKS5 | HTTPS only (MITM CA on local) | Any TCP via VLESS |
| Setup | VPS + Apps Script + AES key | Apps Script + auth key | VPS + domain + TLS + Xray config |
| Throughput | Apps Script quota * # deployments | Apps Script quota * # deployments | VPS bandwidth |
| Observability | Apps Script never sees plaintext | Apps Script sees the full HTTP request | Direct |
| Iran DPI fit | TLS-to-Google + raw TCP โ strong | TLS-to-Google + HTTP โ fingerprint risk | Direct VPS = fingerprint risk |
The end-to-end AES is the meaningful security improvement over MasterHttpRelay โ Google's request logs are obvious and Google ToS / Iran-sanctions exposure for the original maintainers is real. With GooseRelay, Google's logs are AES ciphertext; the only thing leaking is request count, body sizes, and timing. Still recoverable by a sufficiently motivated adversary, but qualitatively different from logging plaintext destinations.
The VPS requirement is the meaningful cost. The whole appeal of MasterHttpRelay was "free, no servers." GooseRelay drops that because the project's stated value is tunneling raw TCP โ SSH, IMAP, anything โ which fundamentally requires a real net.Dial somewhere.
Watchlist
This goes on watchlist โ single author (kianmhz), recent repo, single Persian-speaking-market target. Re-check 2026-07-29 for: independent contributors, Android/iOS clients (currently CLI-only), audit of the AES wrapper, evidence the threat model holds against Iran's TSPU-equivalent (see tspu for the Russian analogue).
Related
- masterhttprelayvpn โ original Python project; cited as inspiration
- masterhttprelayvpn-rust โ Rust port with egui UI and Android VpnService
- serverless-relay-transport โ the broader pattern this slots into
- domain-fronting โ the underlying censorship technique
- xray-tutorial, 3x-ui, mihomo, xkeen โ VLESS-based circumvention cluster (the alternative if you have a domain and don't need to hide behind Google)