
Tunneling data over webrtc to bypass censorship
Tunnels internet traffic through video calling platforms (VK Call, Yandex Telemost, WB Stream) to bypass government whitelist censorship.
Step-by-step setup guide (in Russian): docs/SETUP.md
Two tunnel modes are available: DC (DataChannel) and Video (VP8 data encoding). The recommended setup is headless on both ends - pure Go (Pion) talks to the platform's SFU directly, no browser. ChaCha20 obfuscation, configurable VP8 pacing, and the LiveKit/WB Stream backend are headless-only features.
A legacy browser path (Android WebView joiner against an Electron desktop creator with JS hooks) still works for VK DC, but it's slower, can't obfuscate, and is being phased out. New deployments should use headless.
Pion opens a SCTP DataChannel on the publisher PC and tunnels TCP/UDP through it. Frames pass through the platform's SFU like any other DataChannel payload.
Joiner (censored, Android/iOS/Linux) Creator (free internet)
All apps
|
VpnService (captures all traffic)
|
tun2socks (IP -> TCP)
|
SOCKS5 proxy (Go, :1080)
|
Headless joiner (Pion) Headless creator (Pion)
| |
DataChannel <------- SFU -------> DataChannel
|
Relay bridge
|
Internet
Same pipeline as DC mode, but the tunnel rides on a published VP8 video track instead of a SCTP DataChannel. Useful when the SFU rate-limits DataChannels but lets RTP through (e.g. Telemost), and platform-mandatory in some cases (WB Stream's publisher track is always video). Tunnel framing and the multiplex layer above it are the same as DC mode.
Traffic goes through the platform's SFU, which is on the government whitelist. To DPI it looks like a normal video call.
relay/ - Go relay shared by both ends: SOCKS5 proxy, tun2socks plumbing, DC/VP8 tunnel, ChaCha20 obfuscator, connection multiplexer, gomobile/iOS bindingsheadless/vk/ - Headless VK creator: creates or joins a call via the VK HTTP API, Pion DC/VP8 tunnel, no browserheadless/telemost/ - Headless Telemost (Yandex) creator with the same modelheadless/wbstream/ - Headless WB Stream creator (LiveKit-backed, anonymous guest tokens)headless/dion/ - Headless DION creator with the same modelheadless/bitrix/ - Headless Bitrix creator (adaptive DC/VP8, guest join)headless/wbstream-joiner/ - Desktop WB Stream joiner (counterpart to the creator, used for tests and Linux clients)headless/telemost-joiner/ - Desktop Telemost joiner (counterpart to the creator, used for tests and Linux clients)headless/dion-joiner/ - Desktop DION joiner (counterpart to the creator, used for tests and Linux clients)headless/bitrix-joiner/ - Desktop Bitrix joiner (counterpart to the creator, used for tests and Linux clients)headless/vk-bot/ - Standalone VK Long Poll bot that spawns headless creators on demand and replies with the join link (server-side alternative to the Electron bot)headless/tests/ - Live end-to-end tests (creator + joiners over a real SFU); run same-host or in a Dockerized netns stand, see headless/tests/README.mdandroid-app/ - Android joiner: VpnService + tun2socks + headless Pion (primary path); also retains a WebView fallback for the legacy browser flowios-proxy-app/ - iOS joiner: SOCKS5 + headless Pion via the gomobile xcframeworkcreator-app/ - Electron desktop creator app: GUI front-end that can run either the legacy browser path or spawn the headless Go binaries; suitable for both interactive use and deploymentshooks/ - JavaScript hooks for the legacy browser path (DC and Video modes, VK and Telemost). Headless does not use JS hooks.Prebuilt binaries are available on GitHub Releases.
Download and run the Electron app from GitHub Releases. It bundles the Go relay automatically.
Important: The call must be created from within the Creator app. Joining an existing call from the app will not work - the JS hooks must be present from the moment the call starts.
Three forms are available; pick whichever fits the device:
whitelist-bypass.apk from Releases. Allow the VPN prompt on first launch. Paste the join link and tap GO; system-wide traffic flows through the call.whitelist-bypass-proxy.ipa from Releases (sideload via AltStore / Sideloadly / your dev account). Exposes a local SOCKS5 proxy only - no system VPN. To proxy the whole device, point any SOCKS5-capable VPN app (Shadowrocket, Streisand, ...) at the SOCKS5 endpoint the app shows; or set the proxy per app (Telegram has built-in support).--socks-user / --socks-pass enable SOCKS5 username/password auth.
headless-wbstream-joiner --room <link> --socks-port 1080 [--socks-user u --socks-pass p]headless-telemost-joiner --tm-link <link> --socks-port 1080 [--socks-user u --socks-pass p]headless-dion-joiner --room <link> --socks-port 1080 [--socks-user u --socks-pass p]headless-bitrix-joiner --link <link> --socks-port 1080 [--socks-user u --socks-pass p]The full step-by-step (Russian) covers each platform in detail: see docs/SETUP.md.
go install golang.org/x/mobile/cmd/gomobile@latest)go install golang.org/x/mobile/cmd/gobind@latest)# Full release build (Android APK + Creator app + Headless creators + Linux joiners + VK bot + iOS IPA on macOS)
./make-release.sh
# Individual builds
./build-go.sh # Go .aar, relay binary, headless creators
./copy-hooks.sh # Copy JS hooks to android assets
./build-app.sh # Android APK
./build-headless.sh # Headless binaries only (current platform)
./build-cli.sh # Per-arch zips of headless creators + joiners + vk-bot
./build-creator.sh # Creator Electron app (all platforms)
./build-ios.sh proxy # iOS proxy app, xcframework + unsigned IPA
./build-ios.sh vpn # iOS VPN app, xcframework + unsigned IPA
Requires Xcode and macOS. build-ios.sh takes one argument, proxy or vpn.
./build-ios.sh proxy # ios-proxy-app -> prebuilts/whitelist-bypass-proxy.ipa
./build-ios.sh vpn # ios-vpn-app -> prebuilts/whitelist-bypass-vpn.ipa
The script builds Mobile.xcframework into the app directory, runs the app's strip-signing.sh to clear the developer team from the project, builds the app unsigned, and writes an unsigned IPA to prebuilts/.
To run on a device, open the matching .xcodeproj in Xcode, set your team and unique bundle identifiers in Signing & Capabilities, and build. The vpn variant requires the Network Extension capability on its bundle identifiers.
Output in prebuilts/: