GitHub release License: MIT Rust Docker Platforms
A DPI-resistant SOCKS5 / HTTP-CONNECT tunnel that wraps your traffic in TLS + WebSocket and ships it through a single VPS. The inner wire uses the Biba v3 shared-PSK layer (opaque HELLO/ACK, ChaCha20-Poly1305, per-frame random decoy), plus per-frame random padding, browser-ordered upgrade headers, and HTTP camouflage on the same TLS port.
Pure Rust server and client; Android app (Jetpack Compose) and a Tauri desktop wrapper live in the same workspace.
Status: experimental. Protocol is not frozen — treat any deployment as a
personal lab, not a production service. See Security.
Quick start
git clone https://github.com/Eljaja/BibaVPN
cd BibaVPN
bash start.sh
#Download app from releases(Releases — Android & desktop. bash start.sh prints a labeled Invite URI (biba://…) and Passphrase; paste both into the app.)
- Docs
- docs/manual/ — English user manual (how it works, download, server & client setup) for websites
- PROTOCOL.md — wire formats, session flow, invite URI, BibaV4 roadmap + v3 + implementation status
- AGENTS.md — architecture, CLI flags, deploy notes, scripts, stealth vs BibaV4
- CHANGELOG.md — v1.2.0 / BibaV4 release notes
- DESIGN.md — brand / UI design system for ports
- What it does
- Features
- Quick start
- Using the tunnel
- Build from source
- Configuration
- v1.2.0 — BibaV4 breaking changes
- Comparison (at a glance)
- Android and desktop
- Security
- License
┌─────────┐ SOCKS5 / ┌───────────────┐ TLS + WSS ┌───────────────┐ TCP/UDP ┌────────┐
│ apps │ ─HTTP CONNECT─►│ bibavpn-client│ ─────────────► │ bibavpn-server│ ──────────► │ target │
└─────────┘ (plaintext) └───────────────┘ one socket └───────────────┘ └────────┘
(mux)
- Client runs on your machine and exposes a local SOCKS5 (and optional HTTP CONNECT) endpoint.
- Server runs on a VPS, terminates TLS + WebSocket, and dials the target TCP / UDP destination.
- Many logical streams are multiplexed over one to four outer WebSocket
sessions (client
--ws-parallel, round-robin stream placement) or one whenws_parallel=1— trading extra handshakes for more natural parallelism.
For the full wire format, frame layout and session setup see PROTOCOL.md.
- SOCKS5 (TCP CONNECT + UDP ASSOCIATE) and HTTP CONNECT on the client.
- TLS + WebSocket transport; the server serves plain HTTP on the same port
as camouflage (
--camouflage-dirfor a static site,--camouflage-urlfor a reverse origin). - Biba shared-PSK wire: variable-length opaque HELLO/ACK (no fixed
33/48-byte signatures), domain-separated key derivation (
--proto-domain), and sealed control frames (AUTH, OPEN, MUX / UDP_MUX, OPEN_OK / OPEN_ERR). UDP datagrams use v3 single-byte opcodes (0x05/0x06for REQ/REP) inside the AEAD plaintext, not legacy ASCII magics. - Biba shaping knobs: adaptive / random / HTTP-bucket padding, WS
Ping with jitter, binary size cap, per-frame WS jitter (min–max ms),
configurable upgrade headers per TLS client profile (default Chrome
132+ when nothing else is selected), early-session noise, TLS via rustls
(default) or BoringSSL (
--features boring-tls, client--tls-stack boring—**--pin-cert+ Boring** is not supported yet), TLS leaf pinning on rustls (--pin-cert). - TCP mux over 1–4 outer WSS sessions (round-robin when
--ws-parallelis 2–4) + a separate single WSS for UDP mux. - Biba extras: optional
--stealth-profile,fingerprint/tls_profilemerge rules (client_policy), parallel decoys plus idle decoys, server delayed ACK + ACK profile and RTT mask — see AGENTS.md. - Packet desync / TCP “fooling” flags in the client are mostly advisory in the default build; real DPI-oriented split/disorder usually means an external helper (e.g. zapret-class tools) documented in PROTOCOL.md (external desync section).
- Encrypted invite URIs (
biba://…) so you can ship one line of config instead of a wall of flags. - Android app (Jetpack Compose, JNI core) and Tauri desktop wrapper.
You will need Docker (for the image-based paths) or Rust 1.78+ (the
repo pins a toolchain in rust-toolchain.toml) if you want to build from
source. For anything beyond a local lab you also need a spare VPS or LAN
host to act as the server.
The snippet at the top of this file is enough for a local Docker lab; you need
Docker (e.g. Docker Desktop or WSL2 + Docker on Windows). First run:
bash start.sh --build. For a public server, set BIBA_INVITE_PUBLIC and
BIBA_INVITE_SNI before bash start.sh. Full invite / flag details:
E. Encrypted biba:// invite. Landing page:
GitHub Pages (source: docs/index.html).
Prebuilt multi-arch (linux/amd64, linux/arm64) images live on Docker Hub:
The repo ships a ready-made compose file that pulls both images, wires them
on one Docker network, and exposes the client's SOCKS5 on localhost:11080
and HTTP CONNECT on localhost:11880:
# pull + run (no build step)
curl -fsSL https://raw.githubusercontent.com/Eljaja/BibaVPN/main/docker-compose.hub.yml \
-o docker-compose.hub.yml
# pick your own secrets (both sides must agree)
export BIBA_VPN_TOKEN="$(openssl rand -hex 16)"
export BIBA_VPN_PSK="$(openssl rand -hex 32)"
docker compose -f docker-compose.hub.yml up -d
# SOCKS5: 127.0.0.1:11080
# HTTP: 127.0.0.1:11880Or, if you've already cloned the repo:
BIBA_VPN_TOKEN=$(openssl rand -hex 16) \
BIBA_VPN_PSK=$(openssl rand -hex 32) \
docker compose -f docker-compose.hub.yml up -dSmoke test:
curl --socks5-hostname 127.0.0.1:11080 https://ifconfig.io
curl -x http://127.0.0.1:11880 https://ifconfig.ioThis variant uses a self-signed cert inside the Docker network and the client runs with
--insecure. That is fine for a localhost lab, not for a real VPN. For that, see C.
Image tags:
| Tag | Meaning |
|---|---|
:latest |
HEAD of main (CI publishes on every push). |
:vX.Y.Z |
Pinned release. Prefer this for anything long-lived. |
:sha-abc1234 |
Exact commit. Useful for rollback. |
To build the server image from this checkout and run it with the same
defaults as the quick path (including invite + 262144 WS cap), use:
bash start.sh --build(start.sh writes .biba-start.env and runs docker compose --env-file … up -d.
Plain docker compose up without those variables will fail — see
[docker-compose.yml](docker-compose.yml).)
For a client + server lab that pulls prebuilt Hub images instead, use A. For an automated build + curl smoke test
- teardown:
./scripts/docker-smoke.sh- Build both binaries locally (Linux or WSL):
cargo build --release -p bibavpn --bin bibavpn-server
cargo build --release -p bibavpn --bin bibavpn-client- Pick your secrets and put them in your shell (do not commit):
export BIBA_VPN_TOKEN="$(openssl rand -hex 16)"
export BIBA_VPN_PSK="$(openssl rand -hex 32)"
export BIBA_HOST="vpn.example.com" # or IP- Start the server on the VPS (here: self-signed TLS for a quick lab — for production use real certs, see Security):
- Start the client locally, pointing at the VPS:
./target/release/bibavpn-client \
--server "$BIBA_HOST:8443" --sni "$BIBA_HOST" \
--token "$BIBA_VPN_TOKEN" --psk "$BIBA_VPN_PSK" \
--decoy-max 32 --max-pad 64 \
--max-ws-binary 262144 --ws-ping-secs 25 \
--insecure \
--socks5 127.0.0.1:1080--insecure disables cert verification and is lab-only. Remove it
together with --self-signed-san once you have a real certificate or
switch to --pin-cert <leaf.pem>.
If somebody else is already running a BibaVPN server and shared host,
token, psk (and optionally a TLS pin) with you out of band:
./target/release/bibavpn-client \
--server "$HOST:8443" --sni "$HOST" \
--token "$TOKEN" --psk "$PSK" \
--pin-cert server-leaf.pem \
--socks5 127.0.0.1:1080Instead of juggling flags, the server can emit a one-line encrypted config and the client can consume it:
# server (prints exactly one biba://… line to stdout after bind)
./target/release/bibavpn-server … \
--print-invite-uri \
--invite-passphrase "$BIBA_INVITE_PASSPHRASE" \
--invite-public "$BIBA_HOST:8443" \
--invite-sni "$BIBA_HOST"
# client (mutually exclusive with --server / --token)
./target/release/bibavpn-client \
--from-invite 'biba://…' \
--invite-passphrase "$BIBA_INVITE_PASSPHRASE" \
--socks5 127.0.0.1:1080Share the passphrase out-of-band, never in the same channel as the URI. See PROTOCOL.md#encrypted-invite-biba.
Once the client is up, point your apps at the local SOCKS5 / HTTP CONNECT:
- Browser (Firefox): Settings → Network → Manual proxy,
SOCKS5 host
127.0.0.1, port1080, "Proxy DNS when using SOCKS v5" on. - Browser (Chrome / Chromium):
--proxy-server="socks5://127.0.0.1:1080". - curl:
curl --socks5-hostname 127.0.0.1:1080 https://…. - System-wide on Linux: use
proxychainsor setALL_PROXY=socks5h://127.0.0.1:1080.
Workspace layout (cargo workspace):
| Crate | Role |
|---|---|
bibavpn |
lib + binaries bibavpn-server, bibavpn-client, bibavpn-mint-invite |
biba |
uTLS-like TLS fingerprint helpers |
apps/bibavpn-jni |
Android JNI glue around bibavpn (crate name bibavpn-jni) |
apps/bibavpn-desktop/src-tauri |
Tauri desktop wrapper (systray, platform proxy setup) |
Common commands:
cargo build --release -p bibavpn --bin bibavpn-server
cargo build --release -p bibavpn --bin bibavpn-client
cargo test --workspaceA rust-toolchain.toml pins the compiler version so CI and local builds stay
reproducible. Docker images use the same or a newer toolchain.
The 1.2.x line ships Biba v3 on the wire today and implements many BibaV1.2 anti-DPI behaviors as optional layers. The long-term BibaV4 product spec in PROTOCOL.md may still replace inner opcodes or KDF/invite fields — that would be a true breaking wire change. Until such a cutover, treat releases as “v3 + stealth” and keep client, server, and app builds on the same version line.
PROTOCOL — Implementation status lists what is already in code versus what remains roadmap relative to the BibaV4 bullet list. Always follow SECURITY.md and local law.
Rough positioning only; details depend on version and network path. Stealth features land incrementally on top of v3; check the crate version and CHANGELOG.md.
| BibaVPN (1.2.x, v3 wire) | wstunnel | Hysteria2 | REALITY (e.g. Xray) | |
|---|---|---|---|---|
| Primary transport | TLS + WSS, PSK inner | TLS + WSS, generic | QUIC | TLS fronting / proxy protocol |
| DPI focus | Explicit (fingerprints, timing, padding, decoys) | General tunneling | Brutal throughput / quic | Site mimicry |
| Typical role | Single small VPS, SOCKS/CONNECT | Port forwarding / WSS | High perf | Domain fronting style |
| Ecosystem | Rust + mobile/desktop in-repo | many | Go server | V2Ray / Xray family |
BibaVPN does not claim a security or anonymity property beyond “harder to classify on the wire” — see Security.
Every CLI flag is documented in AGENTS.md. The short story:
- Required for an encrypted tunnel:
--server,--sni,--token,--psk. The client wire is Biba v3 only (--protodefaults to**3**). Server--proto-domain(defaultdefault) must match the client’s--proto-domain, or the SNI when the client leaves--proto-domainempty. - Shape / anti-DPI:
--decoy-max,--max-pad,--pad-mode,--dummy-interval-secs,--ws-ping-secs,--junk-frames,--stealth-profile,--fingerprint/ effective TLS client profile,--ws-jitter-min-ms/--ws-jitter-max-ms,--ws-parallel,--decoy-gets*,--idle-decoy-secs(client),--tls-stack(withboring-tlsbuild if needed),--tls-fragment. - Server timing:
--ack-profile,--server-ack-delay-*-ms,--rtt-mask-jitter-ms(see AGENTS.md for when profiles apply). - Camouflage on the TLS port (server):
--camouflage-dir <path>or--camouflage-url http://…. - TLS trust (client): real CA by default,
--pin-cert <pem>to pin the leaf,--insecurelab only.
Never put secrets in the URL: the token is carried in the v3 sealed AUTH
opcode after HELLO/ACK, and the WebSocket path (--ws-path, default /ws) does
not contain credentials.
Invites: JSON includes **proto** (default **3**) and optional
**proto_domain** (see PROTOCOL.md). **--print-invite-uri**
and **bibavpn-mint-invite** both target v3 by default.
WSL smoke: after cargo build --release -p bibavpn, you can run
scripts/wsl-proto-v3-smoke.sh for a quick local SOCKS + curl check (see
AGENTS.md).
- Android + desktop (Tauri):
apps/bibavpn-desktop/(Vite UI + Tauri shell). Android VPN glue lives undersrc-tauri/android-bibavpn-extras/and is merged into Tauri's generated Android project byapps/scripts/integrate-bibavpn-into-tauri-android.sh. Prebuilt binaries are emitted by the GitHub Actions workflows in.github/workflows/.
See DESIGN.md for the shared visual language if you want to port the UI elsewhere.
BibaVPN is an experimental tunnel, not a hardened product. Known caveats:
- Secrets in the repo:
PSK,tokenand anyinvite-passphrasemust stay out of git. The repo ships an.gitignorethat coversserver.txt,.env*,*.pem,*.keyand related local files. Do not commit real credentials. Rotate anything that ever leaked. **--insecureis lab-only.** For anything you actually care about, use a real certificate (e.g. Let's Encrypt via a reverse proxy) or pin the leaf with--pin-cert.- Threat model: BibaVPN aims to make the outer flow look like a long-lived HTTPS WebSocket to a reasonable camouflage site. It is not anonymity software; the server operator sees every byte you send, and active probing with the right keys recovers the inner protocol.
- Token path:
--legacy-path-authaccepts an old/b/{token}URL form without the sealed AUTH step. It is only there for old clients and is strictly weaker than the default. - Report security issues privately — see SECURITY.md.
MIT — see LICENSE. Third-party crates retain their own licenses
(cargo tree --duplicates, cargo about if you want a full inventory).