A fast, custom encrypted transport protocol written in Rust.
Go to file
ospab 8b5c0a3a8c feat(gui): register the helper task from an installer, not from the app
Elevation belongs to install time. Registering a task that runs elevated is
itself privileged, so an unprivileged GUI can only obtain one by raising the
very prompt we are trying to remove. There was nowhere to put it: the Windows
GUI ships as a portable zip built with --no-bundle, so the project had no
installer at all. Adds an NSIS one, whose POSTINSTALL hook registers the task
while already elevated. Connecting then prompts zero times.

NSIS over WiX because installerHooks is an NSIS feature; the MSI equivalent
needs a custom action, which is more bespoke machinery, not less. installMode
is perMachine — the default, currentUser, does not run elevated, and the hook
would fail exactly as the in-app attempt did.

The task's principal is the SID S-1-5-32-545 (BUILTIN\Users) with
InteractiveToken rather than the installing user, so a machine-wide install
serves every account instead of only whoever ran the installer; the name is
localized and would not resolve. %LOCALAPPDATA% in the arguments is left
unexpanded for the same reason — Task Scheduler expands it per running user.

Also fixes the in-app fallback, which the portable zip still needs and which
had never once worked. It trusted the exit code of an elevated schtasks, but
-Verb RunAs launches through ShellExecute and a non-elevated parent generally
cannot read the child's exit code: $p.ExitCode yields $null, and `exit $null`
leaves PowerShell reporting 0 (measured, not assumed). Failure was arriving
disguised as success. -Wait does not reliably block either, so deleting the
task XML afterwards raced schtasks reading it. It now waits for the task to
actually appear before deleting anything, and treats the exit code as advisory
except for 1223, a declined prompt, which is worth failing fast on.

Corrects one comment that asserted the opposite of the truth: schtasks writes
UTF-16 to a console but UTF-8 with no BOM into a redirected pipe, which is the
case that matters here. Only the fallback made the path check work at all.

wintun.dll rides along as a bundled resource and the hook copies it beside the
executables, since the helper loads it with a plain LoadLibrary. The uninstall
hook removes both it and the task, so no stale registration is left pointing at
a deleted binary.
2026-08-11 16:43:49 +03:00
.github/workflows feat(gui): register the helper task from an installer, not from the app 2026-08-11 16:43:49 +03:00
docs fix(relay): explain the 404 — the API lives under the panel's secret webpath 2026-07-31 20:00:29 +03:00
icons docs: update CLI arguments to subcommands 2026-07-10 03:05:30 +03:00
ostp refactor(relay)!: forward transparently instead of re-authenticating clients 2026-08-03 18:49:57 +03:00
ostp-client fix: post-suspend reconnect no longer strands the machine without internet 2026-08-04 00:34:12 +03:00
ostp-core feat(congestion): actually pace sends instead of releasing whole windows 2026-07-31 19:18:42 +03:00
ostp-flutter chore: release v0.4.4 on master 2026-08-08 21:37:55 +03:00
ostp-gui feat(gui): register the helper task from an installer, not from the app 2026-08-11 16:43:49 +03:00
ostp-jni fix: restore LICENSE file to actual AGPL-3.0 text (was stuck on old BSL 1.1) 2026-07-10 01:36:41 +03:00
ostp-server refactor(relay)!: forward transparently instead of re-authenticating clients 2026-08-03 18:49:57 +03:00
ostp-tun §B: port stability fixes from 0.3.x onto the clean base 2026-06-27 16:30:42 +03:00
ostp-tun-helper feat(gui): one UAC prompt per machine instead of one per connect 2026-08-07 17:19:36 +03:00
ostp.wiki@2a22b520b2 docs: update architecture diagram to be more understandable 2026-07-12 00:34:32 +03:00
scripts fix(install): alpha/beta self-update actually finds a real release now 2026-07-21 18:39:48 +03:00
.gitattributes chore: enforce LF line endings on bash scripts via gitattributes to fix 'bad interpreter' on Linux 2026-05-15 19:08:03 +03:00
.gitignore feat(gui): register the helper task from an installer, not from the app 2026-08-11 16:43:49 +03:00
.release-state.json chore: release v0.4.4 on master 2026-08-08 21:37:55 +03:00
CONTRIBUTING.md fix(release): the second branch is 'beta', not 'pre-release' — was never checkoutable 2026-07-12 02:12:57 +03:00
CONTRIBUTING.ru.md fix(release): the second branch is 'beta', not 'pre-release' — was never checkoutable 2026-07-12 02:12:57 +03:00
Cargo.lock chore: release v0.4.4 on master 2026-08-08 21:37:55 +03:00
Cargo.toml chore: release v0.4.4 on master 2026-08-08 21:37:55 +03:00
Cross.toml CI/CD: Resolve MIPS Tier-3 compilation by instructing Cross to dynamically build-std library from source 2026-05-14 23:57:19 +03:00
LICENSE fix: restore LICENSE file to actual AGPL-3.0 text (was stuck on old BSL 1.1) 2026-07-10 01:36:41 +03:00
README.md fix(release): the second branch is 'beta', not 'pre-release' — was never checkoutable 2026-07-12 02:12:57 +03:00
README.ru.md fix(release): the second branch is 'beta', not 'pre-release' — was never checkoutable 2026-07-12 02:12:57 +03:00
REBUILD_PLAN.md §A: remove WSS + Reality (TLS-mimicry); bump to 0.4.0 / AGPL-3.0 2026-06-27 16:29:42 +03:00
app-icon.svg Refactor: Phase 1 and 2 - Async architecture, JNI fixes, SmolTCP data races, and Tunnel optimizations 2026-06-03 02:06:06 +03:00

README.md

OSTP - Ospab Stealth Transport Protocol

Русский язык · Wiki · Contributing · Releases

GitHub Release License: AGPL v3 Platform: Windows | Linux | macOS | Android Crypto Transport

A fast, custom encrypted transport protocol written in Rust.

OSTP (Ospab Stealth Transport Protocol) is a high-performance transport protocol. It implements a custom ARQ transport over UDP, as well as a UoT (UDP-over-TCP) mode. Every byte on the wire - including packet headers - is cryptographically indistinguishable from random noise, making it highly resistant to Deep Packet Inspection (DPI).


Quick Install

Linux

bash <(curl -Ls https://raw.githubusercontent.com/ospab/ostp/master/scripts/install.sh)

Windows (PowerShell, run as Administrator)

irm https://raw.githubusercontent.com/ospab/ostp/master/scripts/install.ps1 | iex

Manual Download

Download pre-built binaries for your platform from GitHub Releases.


Key Features

Feature Description
Full Traffic Obfuscation Every packet - including headers - is indistinguishable from random noise. Session IDs and nonces are masked with per-packet HMAC-derived keys.
Noise Protocol Handshake Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s - PSK-authenticated, forward-secret key exchange with no static identity exposure.
Reliable UDP (ARQ) Selective ACK/NACK with rate-limited retransmission, configurable reorder buffer, and exponential backoff.
Multiplexed Streams Multiple logical TCP streams over a single encrypted UDP session with per-stream flow control.
Seamless Roaming Clients can switch networks (WiFi ↔ LTE) without session interruption - tracked by session-ID, not IP.
Management API Built-in REST API for third-party panels (3x-ui, custom dashboards). Per-user stats, traffic limits, key CRUD.
Fallback Server TCP fallback proxy to a web server - makes OSTP indistinguishable from nginx during active probing.
Multi-Listener Bind to multiple addresses simultaneously (dual-stack IPv4/IPv6, multi-port).
TUN Mode Full-system VPN via native smoltcp network stack without external dependencies. All traffic transparently routed through the tunnel.
UoT (UDP-over-TCP) Bare UDP-over-TCP tunnel, no protocol mimicry. Since all data is fully encrypted and length-prefixed, it bypasses DPI filters that block unknown UDP traffic by riding over a plain TCP connection.
Mobile & Web Apps Beautiful cross-platform mobile client (Flutter) and a modern Web Control Panel (React/Vite) for effortless server and client management.
TURN Relay RFC 5766 TURN support for environments where direct UDP is blocked.
Hot-Reload Runtime config reload without restart (access keys, exclusions, mux settings).
Structured Logging tracing-based logging with RUST_LOG filtering. JSON/file/syslog output support.
Cross-Platform Windows, Linux, macOS, Android, FreeBSD, MIPS, RISC-V. Single binary, no runtime dependencies.

Architecture

flowchart LR
    %% Styles
    classDef userApp fill:#e1f5fe,stroke:#01579b,stroke-width:2px,color:#01579b
    classDef ostpCore fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#2e7d32
    classDef network fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#e65100,stroke-dasharray: 5 5
    classDef external fill:#f3e5f5,stroke:#4a148c,stroke-width:2px,color:#4a148c
    classDef fallback fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#c62828

    subgraph Local["💻 Client Device"]
        Apps["Web Browser / Apps"]:::userApp
        Socks["SOCKS5 / HTTP Proxy"]:::ostpCore
        Tun["Global TUN (VPN)"]:::ostpCore
        Client["OSTP Client Protocol Engine\n(Noise + ChaCha20 + ARQ)"]:::ostpCore

        Apps -->|TCP/UDP| Socks
        Apps -->|IP Packets| Tun
        Socks --> Client
        Tun --> Client
    end

    subgraph Internet["🌐 Hostile Network (DPI/Firewall)"]
        Tunnel{"Fully Obfuscated\nEncrypted UDP\n(Looks like noise)"}:::network
    end

    subgraph Remote["🖥️ Remote VPS (Server)"]
        Server["OSTP Server Protocol Engine\n(Authentication & Decryption)"]:::ostpCore
        Relay["Connection Multiplexer"]:::ostpCore
        Fallback["Fake Website\n(Nginx/Caddy)"]:::fallback
        Target["Open Internet\n(YouTube, Google, etc)"]:::external

        Server -->|Decrypted Traffic| Relay
        Server -->|Active Probe / Scanner| Fallback
        Relay -->|Clear Traffic| Target
    end

    Client <==> Tunnel <==> Server

Quick Start

1. Generate config

# On your VPS (server):
./ostp init server

# On your machine (client):
./ostp init client

2. Edit config

Server - set your access keys:

{
  "mode": "server",
  "listen": "0.0.0.0:50000",
  "access_keys": ["YOUR_SECRET_KEY"],
  "api": { "enabled": true, "bind": "127.0.0.1:9090", "token": "admin-token" },
  "fallback": { "enabled": false, "listen": "0.0.0.0:443", "target": "127.0.0.1:8080" }
}

Client - point to your server:

{
  "mode": "client",
  "server": "YOUR_SERVER_IP:50000",
  "access_key": "YOUR_SECRET_KEY",
  "socks5_bind": "127.0.0.1:1088",
  "transport": { "mode": "udp" },
  "tun": { "enable": false, "dns": "1.1.1.1" }
}

3. Run

./ostp                         # Uses config.json in current directory
./ostp --config /path/to.json  # Custom config path
./ostp check                   # Validate config without running
./ostp gk                      # Generate a new access key
./ostp links                   # Print client share links
./ostp connect "ostp://ACCESS_KEY@server.com:50000?..."

[!WARNING] Always wrap the ostp://... link in quotes (") so your terminal doesn't misinterpret special characters like & or ?.


Management API

Built-in REST API for building panels and dashboards.

# Server status
curl -H "Authorization: Bearer mytoken" http://127.0.0.1:9090/api/server/status

# List all users with traffic stats  
curl -H "Authorization: Bearer mytoken" http://127.0.0.1:9090/api/users

# Create a user with 10GB traffic limit
curl -X POST -H "Authorization: Bearer mytoken" \
  -H "Content-Type: application/json" \
  -d '{"limit_bytes": 10737418240}' \
  http://127.0.0.1:9090/api/users

Full API reference: Management API


CLI Reference

ostp [--config <PATH>] [COMMAND]

Commands:
  run                    Run the daemon using the config file (default when no command is given)
  connect <URL>          Connect once using a share link: ostp://KEY@HOST:PORT
  setup                  Interactive setup wizard
  init <MODE>            Generate a template config (server/client/relay)
  check                  Validate the configuration file and exit
  gk                     Generate a secure access key (alias: generate-key)
    --format <FMT>         Key format: hex, base64 (default: hex)
    -n, --count <N>        Number of keys to generate (default: 1)
  links                  Print client share links from the server config
  import <URL>           Import a share link into the config file
  update                 Update OSTP to the latest release
    -b, --branch <NAME>    Release channel: stable, beta, alpha (default: stable)
    -v, --version <VER>    Update to an exact version instead of the channel's latest
  migrate                Force-migrate the configuration file to the current format
  proxy-env              Print shell export commands for the local SOCKS proxy
  proxy-env-clear        Print shell export commands to unset it
  uninstall              Stop the service and remove the binary and config

Global options:
  --config <PATH>        Config file path (default: config.json)

Every subcommand also accepts -h/--help for its own option list.


Protocol Summary

Layer Mechanism
Key Exchange Noise NNpsk0 (X25519 + ChaChaPoly + BLAKE2s) zero-RTT
Encryption ChaCha20-Poly1305 AEAD per-packet
Header Obfuscation HMAC-SHA256 derived per-packet mask
Reliability Selective ACK with cumulative + SACK ranges
Retransmission Rate-limited NACK + exponential backoff RTO
Keepalive Ping/Pong with RTT measurement every 5s

Building from Source

# Prerequisites: Rust 1.75+
cargo build --release

# Cross-compile for Linux
cross build --release --target x86_64-unknown-linux-gnu

# Run tests
cargo test -p ostp-core -p ostp-server

Documentation


License

GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE for the full text.


Contact