Russia reachability test rig

One IP (135.125.239.97), one document root, four arms. Mobile data only — Wi-Fi off, no VPN. Tap each link and note whether it completes, hangs, or errors instantly.

Arm A — sslip.io hostname (Let’s Encrypt)

135-125-239-97.sslip.io

Arm B — OVH hostname (Let’s Encrypt)

vps-85c8a526.vps.ovh.net

Arm C — plain HTTP to the IP (no TLS, no SNI)

http://135.125.239.97

Arm D — HTTPS to the IP (TLS, no meaningful SNI)

https://135.125.239.97 — self-signed. The browser will warn; tap through it once, then the rest load normally.

Arm G — real domain, straight to the OVH box (no CDN)

direct.bravoapp.cc — the control arm. Same server and same files as arms A and B, but a real registered domain. If this works where arm A stalls, the hostname was the problem.

Arm F — same box, behind the Cloudflare edge

cf.bravoapp.cc — identical origin and files, proxied by Cloudflare. If arm G stalls and this works, a CDN in front is mandatory.

A second tap on the same file may be served from Cloudflare’s cache rather than the origin. Use the buttons below for a guaranteed cold fetch.

Arm H — Cloudflare R2 object storage

r2.bravoapp.cc — decides whether map tiles and user photos can live in R2.

Arm I — dedicated AWS IP, real domain, no CDN

aws.bravoapp.cc — AWS Lightsail, eu-west-1, static IP 54.216.199.119 (range 54.216.0.0/15). The direct counterpart to arm G, which failed on OVH: same domain, same TLD, no CDN either side — only the network underneath differs. The 10 MB file is the one that matters; small files completing proves nothing about throughput.

Arm J (the ec2-….compute.amazonaws.com hostname) is not available: Let’s Encrypt refuses to issue certificates for AWS-owned names, and serving a self-signed one would make a broken arm look like a working one.

Arm E — WebSocket, held open (tap and wait)

A file download finishing tells you nothing about whether a long-lived connection survives. Supabase Realtime holds one of these. Tap a button and leave the screen on — it runs for 120 s and counts keepalive frames.

Upload — 256 KB POST

The app’s critical path is an upload: a GPS track is 252 KB at p95, photos are bigger. Uploads cross DPI differently from downloads.

Reference

What to watch for. A block on Russian mobile looks like a stall, not an error: the download starts, reaches some byte count, and then sits there forever. If that happens, note roughly how far the progress bar got — that number is the whole point of the exercise. An instant “can’t reach” error means something different from a freeze.