FlareProx can now fall back to a relay that you host on Google Cloud whenever a Cloudflare Worker cannot reach a Cloudflare-managed destination. The relay reuses the same WebSocket handshake as the worker, so no application changes are required—just deploy the relay, note its URL and credentials, then enable it in flareprox.json under client.relay.
"client": {
"relay": {
"enabled": true,
"url": "ws://YOUR_RELAY_HOSTNAME:8080",
"auth_token": "Bearer YOUR_SHARED_TOKEN",
"socks_password": "same-password-used-by-worker"
}
}
Tips:
- Set the relay
socks_passwordto match the worker password so the same credential works everywhere.- Use
ws://for plaintext listeners (e.g., a VM without TLS) andwss://when you terminate TLS in front of the relay (Cloud Run, HTTPS load balancer, etc.).
-
Provision the VM
- Choose a lightweight image (e.g.,
debian-12orubuntu-22.04). - Expose TCP port
8080(or any port you plan to bind) in the firewall.
- Choose a lightweight image (e.g.,
-
Install dependencies
sudo apt-get update sudo apt-get install -y python3 python3-venv git python3 -m venv ~/relay-env source ~/relay-env/bin/activate pip install --upgrade pip pip install websockets
-
Deploy the relay
- Copy
gcp_relay.pyto the VM (e.g., viagit cloneof this repository orscp). - Run the relay with your chosen password and optional auth token:
source ~/relay-env/bin/activate python3 gcp_relay.py --host 0.0.0.0 --port 8080 \ --password "YOUR_SHARED_PASSWORD" \ --auth-token "Bearer YOUR_SHARED_TOKEN"
- Keep the process running with
tmux,screen, or a systemd service.
- Copy
-
Record the URL
- Point a DNS record to the VM or note its external IP:
ws://YOUR_HOST:8080(usewss://only if you terminate TLS in front of the relay).
- Point a DNS record to the VM or note its external IP:
- Access your authorized Google Cloud Shell
- Pick/create a project and save its ID for the commands below.
- Configure defaults (replace
PROJECT_IDandREGION, e.g.,us-central1):gcloud config set project PROJECT_ID gcloud config set run/region REGION
- Enable the required services (one-time per project):
gcloud services enable run.googleapis.com cloudbuild.googleapis.com artifactregistry.googleapis.com
From your development machine (where this repo lives):
mkdir -p cloud-run-relay && cd cloud-run-relay
cp /path/to/repo/gcp_relay.py .
cat <<'EOF' > Dockerfile
FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
COPY gcp_relay.py ./
RUN pip install --no-cache-dir websockets
CMD ["python", "gcp_relay.py"]
EOFCloud Run now prefers Artifact Registry repositories. Create one (once per project), then build:
gcloud artifacts repositories create flareprox-relay-repo \
--repository-format docker \
--location REGION \
--description "Relay images"
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/flareprox-relay-repo/flareprox-relay:latestgcloud run deploy flareprox-relay \
--image REGION-docker.pkg.dev/PROJECT_ID/flareprox-relay-repo/flareprox-relay:latest \
--platform managed \
--allow-unauthenticated \
--set-env-vars FLAREPROX_RELAY_PASSWORD=YOUR_SHARED_PASSWORD,FLAREPROX_RELAY_TOKEN="Bearer YOUR_SHARED_TOKEN"- Cloud Run injects the port via
$PORT;gcp_relay.pyreads it automatically. - The deploy command prints a service URL (e.g.,
https://relay-xyz.a.run.app). Use thewss://form of that URL insideflareprox.json. - You can re-run the deploy command whenever you push a new image tag.
- Fetch the URL anytime:
gcloud run services describe flareprox-relay --format='value(status.url)' - (Optional) Restrict ingress via:
Pair this with Cloud Armor or Identity-Aware Proxy if you need more control.
gcloud run services update-traffic flareprox-relay --ingress internal-and-cloud-load-balancing
Remember to keep FLAREPROX_RELAY_PASSWORD/TOKEN strong—Cloud Run treats them like environment variables, and you can rotate them with gcloud run services update.
- Open
flareprox.json(or your chosen config file). - In the
clientsection, set:"relay": { "enabled": true, "url": "ws://relay.example.com:8080", "auth_token": "Bearer super-secret-token", "socks_password": "generated-socks-password" }
- Optionally adjust
client.handshake_timeout(default 5 seconds) if your relay sits behind high-latency networks. - Restart any running local SOCKS listeners. FlareProx will now fall back to the relay whenever the worker reports
cloudflare-blocked.
- Run
python3 flareprox.py socks --bind 127.0.0.1. - Access a Cloudflare-hosted site through the SOCKS proxy.
- When the worker declines the target, the CLI will log a message similar to:
flareprox-123: fallback to relay for target.example.com:443 (Target served by Cloudflare IP range) - Confirm the connection succeeds and packets egress from your GCP relay IP (use
https://ifconfig.me/ip).
If the relay isn’t reachable, FlareProx will return a SOCKS failure to the client—double-check firewall rules, TLS certificates, and credentials.