Welcome aboard cocode.dk Airways

Parvaz پرواز PVZ 001 · CPH→THR

A flight over the filter

Android browser tunnel · Google Apps Script · domain fronting · Farsi-first

cocode.dk · departures local time · LIVE
FLT
STAGE
GATE
STATUS
PVZ 001
paste · the parvaz:// link
A1
boarding
PVZ 002
install · the user CA
B12
on time
PVZ 003
open · chrome (no setup)
C7
cleared
PVZ 004
https · all routes open
D24
final call
§1

Abstract

Mission brief

Parvaz is a Farsi-first Android browser tunnel for Iranian users with no technical background. A helper deploys the upstream MasterHttpRelayVPN Code.gs on their own Google account; the user receives a parvaz:// link over a secure messenger (Signal or Telegram — not WhatsApp), scans a QR or taps Paste, installs a MITM certificate via Android Settings once, taps Connect, and browses normally in Chrome (or any Chromium browser).

Chrome traffic routes through Apps Script — TLS SNI www.google.com, HTTP Host script.google.com. Chrome trusts the on-device Parvaz CA out of the box; no flags, no about:config, no root. Architecturally aligned with the proven MasterHttpRelayVPN-RUST port; Parvaz's edge is the NOTAM visual identity, Farsi-by-default UI, and tighter onboarding for non-technical passengers.

§2

Flight path

5 hops · DPI sees the front
Chromeno flags
browser
PARVAZVPN + tun2socks + sidecar
this APK
Google edgeSNI www.google.com
DPI sees
script.google.comHTTP Host (real route)
internal
Code.gsyour deployment
UrlFetch → target
What DPI seesTLS to Google · SNI www.google.com · indistinguishable from Search.
What Google seesHTTP Host script.google.com → routes to your Web App.
What Code.gs doesUrlFetchApp.fetch(target) · returns {s,h,b} envelope.
§3

Notice to airmen

Restricted airspace
Caution · Restricted airspace NOTAM A0001/26
Google Apps Script's terms forbid this use. Deploy the Code.gs to your own Google account only — do not centralize deployments, do not commercialise, do not distribute a shared one. Personal, research, and educational use only. If you do not understand the legal implications, do not deploy.
§4

Airframe specifications

Features
01Domain frontingSNI www.google.com · Host script.google.com. DPI sees the front; Google's edge routes by Host.
02Farsi-first onboardingPaste a parvaz:// URL or scan QR → install MITM cert once → tap Connect. Persian default.
03Chrome out of the boxChrome (and other Chromium: Brave, Edge, Vivaldi) trust the user-installed Parvaz CA on Android with no flags. Native apps still reject user CAs by Android default.
04SNI-rewrite fast pathGoogle-owned hosts skip Apps Script entirely · direct tunnel · no quota.
05Open source APKKotlin + Compose UI · embedded Go SOCKS5 sidecar · MIT · F-Droid & sideload only.
06Zero telemetryNo analytics · no crash reporting · access key in EncryptedSharedPreferences.
§5

Honest disclosure

What the app won't do · what it must do · the limits
Won't do No
  • No analytics, telemetry, or remote logs (yet).
  • No central relay — every passenger runs their own Code.gs.
  • No location, contacts, SMS, microphone, or camera (camera is opt-in for QR only).
  • No auto-update pings · no ads · no crash reporting service.
  • No servers operated by us · no accounts · no sign-in.
Verify in source · MIT · grep the manifest.
Must do Yes
  • VpnService — to capture and route browser packets.
  • INTERNET + FOREGROUND_SERVICE — talk to Apps Script, stay alive.
  • POST_NOTIFICATIONS (Android 13+) — show the connected pill.
  • Device screen-lock — Android refuses CA install otherwise.
  • A Chromium browser — Chrome (or Brave / Edge / Vivaldi). No browser flags needed.
Optional · CAMERA — only if you scan a QR.
Limits · if we hand out the boarding card
Trustrelay sees URL · headers · cookies · body in plaintext ~20kUrlFetch / day · Apps Script free quota ~30sper fetch ~6 minper script execution 1 relayper Google account · TOS Throughputcapped by UrlFetch
§6

Who flies, who's grounded

Honest scope
Heads-up Not every site opens — and WebSockets are not supported in this version.
Cleared for take-off Tunnels
  • Chrome on Android — no flags, no about:config, no root.
  • Other Chromium browsers — Brave, Edge, Vivaldi — same path, same trust.
  • Google-owned hosts (google.com, youtube.com, fonts.googleapis.com) via direct SNI rewrite, in any browser.
  • Web apps inside Chrome — Gmail, GitHub, Wikipedia, news sites, search.
No Apps Script quota for Google fast-path. Throughput ~5 KB/s · WebSockets do not work yet.
Grounded Won't tunnel
  • Firefox Stable / Beta / Focus — no about:config, can't set the trust flag.
  • Firefox Nightly — flag exists but resets to false on every restart (fenix#18990, open since 2021).
  • DuckDuckGo browser — Chromium-based but rejects the user CA. Confirmed broken.
  • Native apps — Instagram, Telegram, WhatsApp, banking, streaming. Reject user CAs by Android 7+ default.
General Android MITM constraint · pair with xray + VPS for native apps.
§7

Boarding sequence

~3 minutes · once
1

Receive the parvaz:// link

Signal or Telegram from your helper · not WhatsApp

Auto
2

Install Parvaz · tap the link

APK from GitHub releases · sideload

Auto
3

Install the certificate

Android Settings · ~30 seconds · see §8

Manual
4

Tap Connect · open Chrome

no browser flags · see §9

Manual
§8

Install the certificate · in Settings

Step 1 of 2 · once · ~30 seconds

In Parvaz, tap Open Settings. Parvaz drops parvaz-ca.crt into Downloads and opens Android Settings. Then follow the path for your phone.

proc · cert.001 · samsungOne UI 6 / Android 14
# SAMSUNG (Galaxy): Settings → Security and privacyMore security settingsInstall from device storageCA certificate → pick parvaz-ca.crt from Downloads → enter your PIN / fingerprint → tap Install anyway on the warning
proc · cert.001 · pixel / aospAndroid 14 / 15
# PIXEL / stock Android: Settings → Security & privacyMore security & privacyEncryption & credentialsInstall a certificateCA certificate → pick parvaz-ca.crt from Downloads → enter your PIN / fingerprint → tap Install anyway on the warning

Pre-requisite: screen lock (PIN, pattern, password) · Android refuses install otherwise. Can't find the menu? Search CA certificate in Settings. Warning is fine to dismiss — the CA was generated on your phone; the private key never leaves the app's private storage.

§9

Tap Connect · open Chrome

Step 2 of 2 · once · ~10 seconds

Tap the rubber-stamp button on Parvaz's main screen. When it flips to در پرواز (in flight), open Chrome and browse normally — HTTPS pages route through Parvaz with no further configuration. Brave, Edge, and Vivaldi work the same way; the Parvaz CA you just installed is the only piece they need.

proc · browser.001 · chromiumone-time · ~10 sec
# 1. In Parvaz, tap the rubber stamp. → "پرواز" (outline) flips to "در پرواز" (filled · olive) # 2. Open Chrome (or Brave / Edge / Vivaldi). → just browse · no flags, no about:config, no root # 3. (Optional) sanity-check the route: open wikipedia.org # non-Google site → goes through MITM open google.com # Google site → SNI-rewrite fast path

Why Chrome works: Chrome on Android trusts user-installed CAs from the system store, and Chrome's Certificate Transparency enforcement has an explicit carve-out for chains rooted in a user CA — so the Parvaz leaf is accepted with no setup. Browsers that won't work, plus the throughput and WebSocket limits, are covered in §6.

§10

Airframe schematic

Monorepo topology · Kotlin + Go
Sheet 10 · Monorepo topology MIT · Android 7.0+
parvaz/
├── app/             kotlin + compose UI · VpnService · tun2socks
│                 · sidecar launcher · MITM CA install · NOTAM
├── core/            go SOCKS5 sidecar
│   ├── fronter/     TLS-with-custom-SNI dialer + HTTP client
│   ├── protocol/    Apps Script JSON envelope encode/decode
│   ├── codec/       gzip / br / zstd decoders
│   ├── relay/       envelope + fronted client glue
│   ├── mitm/        (next) CA + leaf certs + TLS server
│   ├── dispatcher/  (next) SNI-rewrite vs MITM+relay decision
│   ├── socks5/      local SOCKS5 listener on :1080
│   └── cmd/parvazd/ sidecar main → libparvaz.so (per ABI)
├── reference/      MasterHttpRelayVPN · upstream python (read-only)
└── website/        bilingual GitHub Pages

· core is called from app via ProcessBuilder, not JNI
· one apk + one Code.gs drop-in + one release tag
drawn by · parvaz.doc§10
§11

Helper · deploy the relay

~5 min · once · technical helper only

If you are the technical helper setting Parvaz up for someone else, here is the one-time Apps Script deployment. The end user never opens script.google.com.

proc · relay.deploy.001script.google.com · ~5 min
# 1. Open Apps Script and create a new project open script.google.com # click "New project" # 2. Paste the relay code into Code.gs (replace the default contents) view github.com/cocodedk/parvaz/blob/main/apps_script/Code.gs copy → paste into the Code.gs tab in the editor # 3. Generate a strong random AUTH_KEY (do not reuse passwords) openssl rand -base64 32 # or any password manager · 32+ chars → in Code.gs, set: var AUTH_KEY = "<paste-here>"; → File → Save (Ctrl/Cmd+S) # 4. Deploy as a Web App Deploy → New deployment → ⚙ Web app Execute as: Me (your-email@gmail.com) Who has access: Anyone → click Deploy → Google asks for OAuth consent the first time → Allow # 5. Find the URL that goes into the Parvaz app Apps Script gives you a Web app URL that looks like: https://script.google.com/macros/s/AKfycbyLONGRANDOMTOKEN/exec └────────────┬────────────┘ deployment-id # the only piece you need You can re-open it any time: Deploy → Manage deployments → copy the Web app URL # 6. Build the parvaz:// access link by combining the two pieces above parvaz://<deployment-id>/<AUTH_KEY>#<display-name> # concrete example: parvaz://AKfycbyLONGRANDOMTOKEN/7dF9KmY...eY=#رلهٔ‌من # 7. Share via SECURE messenger ONLY — this URL contains the key ✓ Signal · end-to-end · recommended ✓ Telegram · Secret Chat preferred ✗ WhatsApp · Meta-readable cloud backup → NEVER ✗ SMS · carrier-readable → NEVER ✗ Email · server-readable → NEVER

Quota: ~20k UrlFetch / day · 30 s per fetch · 6 min per execution. One relay per Google account (Apps Script TOS). Test it: open the Web app URL in a browser — you should see {"e":"unauthorized"} (proof the deployment is live and rejecting unauthenticated calls). Source: apps_script/Code.gs · Apps Script · Web Apps.

§12

Ground support · departure

Final call · MIT · 2026
FormPVZ-001
Issued2026.04.26
OriginCocode · DK
CallsignParvaz / پرواز
StatusPre-alpha
MIT · © 2026 Cocode · Babak Bandpey

Cleared for take-off.

Parvaz replaces only the client half of MasterHttpRelayVPN. The Apps Script server is the upstream Code.gs, unchanged — deploy it to your own Google account.

If you don't need the Farsi-first NOTAM UX touches, the mature MasterHttpRelayVPN-RUST port ships today with prebuilt APKs and an English + Persian walkthrough.