Brings the useful work from the old master/pre-release lineage (5c2b5a0)
onto the clean rebuild, since that lineage never had the multi-server/WSS/
Reality removal or any of the 0.4.0 stability work. This is a manual port,
not a cherry-pick — this file's Args/ClientConfig shape had already
diverged too much for the patch to apply mechanically.
- ostp/src/main.rs: flat Args -> clap subcommands (setup, init, generate-key,
links, check, connect, uninstall, update, import, proxy-env,
proxy-env-clear), bridged onto the existing ~500 lines of flag-driven
dispatch via a LegacyArgs struct so none of that logic had to change.
- Fixed a real bug found while porting: GenerateKey's `count` used
short='c', colliding with the global `--config` short (also 'c'), which
clap validates across the whole command tree on first parse() -- a
duplicate short flag there could break every subcommand's parsing, not
just generate-key's.
- `update` now takes `-b/--branch` and `-v/--version` explicitly (was a
bare flag with no way to target a channel or exact version).
- Added the UAC elevation step for TUN mode that this lineage's CLI was
completely missing (`run_client_directly` went straight to creating the
TUN adapter unelevated). Also fixed the elevation check itself: it only
tested `ret <= 32`, but ShellExecuteW returns ERROR_CANCELLED (1223) when
the user clicks "No" on the UAC prompt -- > 32, so a denied prompt was
read as success and the process exited silently without starting the
tunnel. Now ret==1223 is reported explicitly, and a genuine failure logs
GetLastError() so the real Win32 cause is visible next time.
- scripts/install.sh: added -b/--branch alongside the existing -v/--version,
and channel-aware release resolution (nightly/pre-release use their own
rolling tag; stable resolves via the GitHub API's "latest").
- release.yml: added nightly/pre-release branch-push triggers for rolling
prereleases. Fixed the tag_name logic from 5c2b5a0, which mapped
`master` pushes to a release tagged "nightly" -- backwards from master
being the most stable channel. github.ref_name already equals the
branch or tag name that triggered the run, so no per-branch remapping is
needed at all; master is intentionally left off the branch-push list --
it only ever gets real version tags.
Verified: `cargo build -p ostp` succeeds, and `ostp update --help` /
`ostp generate-key --help` / `ostp --help` show the expected flags with no
clap panic.
Co-Authored-By: Claude <noreply@anthropic.com>
security / protocol:
- Derive a PER-KEY junk marker (obfuscation.rs, info byte 0x04) instead of the
global constant [0x88,0x1A,0x93,0x5D]. A fixed marker was a universal DPI
signature identifying ALL OSTP users at once — exactly what the HKDF version
gate avoids for the handshake. Server drops junk via a new DispatchOutcome::Junk
inside the existing key-trial loop (secrets already derived → zero extra cost);
client stamps its own key's marker.
- §E: configurable junk/fragmentation params (junk_pc / junk_ps / frag_chunk / frag_sleep).
GUI (desktop):
- Light theme + toggle, GUI version footer in Settings.
- Fix mouse-wheel scroll on Settings (flex child needed min-height: 0).
- Drop the false "process exclusions unsupported in TUN mode" warning — they DO
work (native_handler maps port->process via GetExtendedTcpTable).
release / infra:
- build.ps1: add -PreRelease (tag CURRENT version as v<ver>-beta.N, no bump, no
master commit); guard the panel build when ostp-control ships no source; bump
the real ostp-gui/package.json instead of the nonexistent ostp-control one.
- release.yml: mark hyphenated tags as GitHub pre-releases; don't hard-fail the
web-panel step when there is no source (use committed dist/).
- Versions aligned to 0.4.1; README license badge BSL 1.1 -> AGPL v3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Anti-DPI obfuscation the project wants to keep, ported from 0.3.x with the
harmful UDP behaviour designed out from the start.
- Junk: before the handshake on a UoT/TCP connection, send 2-5 random
length-prefixed frames (100-1000 B). The server reads each as a frame,
fails to authenticate it, drops it and keeps reading (drop-and-continue),
so junk perturbs DPI flow analysis without breaking the connection. Junk
is NEVER sent over UDP — there each junk would be a lone datagram
indistinguishable from a port scan (probe-flood / wasted CPU / the very
"self-ban" risk the plan calls out). Verified the server has no
probe-based ban, and the unauthorized-probe log is already rate-limited
(§B), so junk-over-UoT produces one debug line, not a flood.
- TCP fragmentation: new `transport.tcp_fragmentation` flag (default off).
When set, the writer splits the first real frame (the handshake) — length
header byte-by-byte then payload in 2-byte chunks with short gaps — so DPI
can't classify the handshake from a single read.
- Ranges are hardcoded for now; §E fine-tuning (configurable Jc/Jmin/Jmax,
S1/S2, H1..H4) is deferred.
Verified by loopback E2E: a UoT client with tcp_fragmentation=true connects
(junk logged as one rate-limited probe, then real handshake accepted) and
curl via SOCKS5 tunnels HTTPS successfully.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ported only the fixes that actually apply to the pre-refactor base
(the handshake fixes 6eb7b36/d65af35 fix bugs the 0.3.1 multi-server
refactor introduced into the new outbounds/ostp.rs; the base bridge.rs
already waits for the handshake response with retransmit + NAT64
fallback, so they are intentionally skipped).
- EMFILE (922cf0b): rlimit::increase_nofile_limit at CLI startup.
- Logs (1151726): UoT connect/disconnect → debug; rate-limit the
unauthorized-probe log to one line / ~30s so a junk/probe flood can't
spam the log (and a client running junk-over-UDP can't self-ban).
- Helper lifecycle + bypass routes (b6e78c1):
* ostp-tun-helper forces std::process::exit(0) after run_server so the
WinTun adapter and its metric-0 default route are reclaimed instead
of lingering as a zombie that breaks the next connect.
* windows_route: delete_routes_for_dest() purges stale /32s, dedupe
bypass IPs, and log add failures at warn!.
* windows: retry tun::create through the transient ERROR_INVALID_
PARAMETER window and widen the adapter-index lookup to ~15s.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Clean-rebuild on the stably-working v0.2.98 base. The project's stealth
path is zapret-like (packet obfuscation / junk / fragmentation), NOT
TLS-mimicry, so WSS and Reality are dropped entirely.
- Delete dead orphan files: ostp-client/src/transport/xhttp.rs and
ostp-core/src/crypto/reality.rs (never declared as modules → not even
compiled), plus ostp-core/src/framing/wss.rs.
- Scrub the `wss` transport field from client config/bridge, the unified
CLI (ostp/src/main.rs), the Tauri GUI backend, the GUI frontend
(index.html/main.js), and the Flutter UI; also drop the Reality
pbk/sid plumbing and XTLS auto-search modes from both frontends.
- Drop now-unused client deps (x25519-dalek, chacha20poly1305, hex).
- Bump workspace to version 0.4.0 and license AGPL-3.0; make ostp's
ostp-core dep path-only so the version bump resolves.
- gitignore ostp-control/ (panel assets built separately; a dummy dist
is created for the rust-embed build).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Boxed HandshakeState in NoiseSession to reduce enum variant sizes
- Used is_ok() instead of let Ok(_) pattern
- Applied automatic clippy fixes for minor warnings
- Unified log prefix to [ostp] across all modules (was [OSTP Core],
[ostp-server], [ostp-client], [client], [bridge])
- Removed informal/casual phrasing from all user-visible messages
- Startup messages are clean and concise (mode, server, status)
- Error messages are actionable without being alarming
- Essential server logs (client connect/disconnect) always visible
- Essential client logs (connection status, errors) always visible
- TUN tunnel messages consistent across Windows and Linux
- Removed noisy eprintln from UDP reader hot path
- Status format: [ostp] Status: Connected (rtt=12.3ms)