Commit Graph

61 Commits

Author SHA1 Message Date
ospab ebfc751471 fix(android): treat a blank signing secret as absent, not as the password
The Android jobs failed with "Get Key failed: Given final block not properly
padded" once the store password was corrected - the keystore opened, but the
KEY could not be decrypted.

Cause: GitHub Actions substitutes an empty string, not an unset variable, for
a secret that does not exist. ANDROID_KEY_PASSWORD is deliberately not set (our
keystore is PKCS12, where the key password cannot differ from the store
password), so OSTP_KEY_PASSWORD arrived as "". Kotlin's elvis operator only
falls back on null, so `getenv(...) ?: storePassword` kept the empty string and
used it as the literal key password.

signingSetting() now maps blank to null, so the documented fallback actually
happens. Applies to every signing field, not just the key password - the same
trap would have hit any of them.
2026-07-30 20:56:33 +03:00
ospab 77a45d7642 chore: release v0.4.2 on master 2026-07-30 20:31:26 +03:00
ospab 6abae68f35 fix(android): default the signing key password to the store password
Our upload keystore is PKCS12 (verified from its DER header, 0x30 0x82 —
JKS would start 0xFEEDFEED). That format has nowhere to store a key password
distinct from the store password, and keytool enforces the two being equal,
so requiring a separate OSTP_KEY_PASSWORD meant configuring a secret whose
only possible correct value was a copy of another one.

Falls back to the store password when unset; an explicit value still takes
precedence for the legacy JKS format, where the two can genuinely differ.
2026-07-30 20:28:07 +03:00
ospab 32c36afc3b fix(android): sign releases with a stable upload key, not the debug keystore
Published APKs could never be updated over - users hit "App not installed" or
"unable to parse the package" and had to uninstall first. The cause was not the
version code (verified: local.properties carries flutter.versionCode=23 and
gha.ps1 bumps pubspec's build number every release, so it increments correctly).
It was the signing key: app/build.gradle.kts still had the stock Flutter
template TODO and pointed the release build type at signingConfigs["debug"].
Android identifies an app by applicationId + signing key and refuses to update
across a key change, and the debug keystore is generated per machine - on
ephemeral CI runners that means every single published build was signed with a
different random key.

Release builds now take their key from android/key.properties or the
OSTP_KEYSTORE_* environment variables, falling back to debug (with a loud
warning) only so local `flutter build apk --release` keeps working. CI
materialises the keystore from repository secrets, refuses to build at all if
the secret is absent, and re-verifies the finished APK is not debug-signed
rather than ever shipping an un-updatable build again.

NOTE: existing installs are signed with a now-unreproducible random key, so
users must uninstall once more for THIS release. Every update after it works.
2026-07-30 19:54:31 +03:00
ospab 2ede607027 chore: release v0.4.2-beta.5 on beta 2026-07-30 19:02:48 +03:00
ospab 7473278cc2 fix(client): bound the UoT connect; green aura + self-updating ping on mobile
UoT took 20-30s (sometimes 1-2 min) to come up on mobile. The TCP connect
had no timeout, so it inherited the kernel's SYN retry budget. Callers
resolve every address for the server and deliberately try IPv6 first
(perform_handshake_with_id sorts is_ipv6 to the front); a mobile network
that advertises IPv6 without a working route blackholes the SYN instead of
rejecting it, so the client sat through that entire budget before reaching
the IPv4 address that would have connected immediately. UDP never showed
this because connect() on a UDP socket just sets the default peer and
returns.

Capped at 4s per address, so a blackholed candidate costs seconds and the
next one is tried. Left the IPv6-first ordering alone: it is what makes
IPv6-only and NAT64 networks work, and with the cap its worst case is now
bounded. (A further win would be remembering which family last succeeded
and trying that first, removing even those 4s — not done here.)

Also, per the earlier UI requests:
- The connected state drew its aura, ring, icon and status dot from the
  theme's `secondary`, which is #AAAAAA and reads as plain white, giving no
  confirmation the tunnel was actually up. Now green, reusing the green
  already used for a healthy ping so "green = good" stays consistent.
  Applied at the call sites rather than to the theme, since `secondary`
  also paints routing toggles, the download metric and settings switches.
- Ping now updates itself from the metrics stream that was already
  arriving, instead of needing the "Test Ping" button, and is rendered as a
  compact icon + value.
2026-07-29 20:06:07 +03:00
ospab cdfd2babc0 chore: release v0.4.2-beta.4 on beta 2026-07-21 18:18:01 +03:00
ospab 5278f58903 chore: release v0.4.2-beta.3 on beta 2026-07-21 18:12:30 +03:00
ospab cd12b01bc3 chore: release v0.4.2-beta.2 on beta 2026-07-18 17:10:47 +03:00
ospab 66a1e97840 chore: release v0.4.2-beta.1 on beta 2026-07-12 02:18:47 +03:00
ospab 108ab8468b fix(flutter): show Junk/TCP-Frag controls only when transport is UoT
Junk packets and TCP fragmentation only take effect on the UoT (TCP)
transport — the UDP path applies neither — so showing them (with an
implicit "UoT only" caveat) while UDP is selected was misleading. The
whole DPI OBFUSCATION section is now gated on transportMode == 'uot' and
appears/disappears reactively when the Transport dropdown changes
(setDialogState already rebuilds the dialog).
2026-07-12 02:04:09 +03:00
ospab 271a39c664 fix(icons): forcefully overwrite all android legacy and adaptive icons with logo_new.png 2026-07-11 20:59:45 +03:00
ospab 44f9067222 feat(icons): apply logo_new.png to all apps and watermarks 2026-07-11 00:58:44 +03:00
ospab 10ec253fa0 chore: release v0.4.1-.0 on master 2026-07-10 03:17:41 +03:00
ospab 2092f6c716 fix(flutter/android): surface getMetrics failures into the in-app log
Traced the whole traffic-counter pipeline (Dart -> MethodChannel ->
Kotlin -> JNI -> Bridge) end to end; it's architecturally identical to
the working desktop implementation, so no code-level bug was found.
Previously a getMetrics exception was only reported as a PlatformException
that Dart swallows with a bare debugPrint, invisible in the in-app log
viewer users actually have access to. Now it's also written to the
native log buffer via OstpClientSdk.addLog, so if the counter breaks
again the actual cause (exception vs. genuinely-zero atomics) shows up
in View Logs instead of requiring adb.
2026-07-10 01:23:28 +03:00
ospab 223f02287a feat(flutter): add optional live speed/RTT display, matching desktop GUI
Mirrors ostp-gui's "Show Speed" / "Show RTT" client settings toggles
(both default on): the home screen now shows live download/upload
throughput (computed from byte deltas between 1s polls, same as
desktop's poll()) as a subtitle under the existing cumulative
Download/Upload totals, and the RTT box is now hideable. Also fixed
"Test Ping" to actually query getMetrics instead of just faking a
500ms spinner with no real measurement.
2026-07-10 01:18:07 +03:00
ospab 1d1a1ea5af refactor: remove dead stealth_sni config field across the whole stack
stealth_sni was never actually consumed to construct any wire bytes —
verified dead in bridge.rs (only stored, never read). It implied
TLS/HTTP SNI mimicry that this project deliberately does not do
(zapret-like: packet-level DPI obfuscation only, no protocol
mimicry). Removed from the runtime schema (config.rs, bridge.rs),
both CLI/GUI local config shapes and their JSON templates, the
Flutter profile model/UI/share-link logic, and README feature docs.
migrate.rs now drops the field from legacy configs with a note
instead of carrying it forward.
2026-07-10 01:04:56 +03:00
ospab 1b3390a3cf fix(flutter): declutter profile editor, fix contrast bugs, unblock app list
- Profile edit dialog: moved junk packets + TCP fragmentation into their own
  modals (tap-to-configure), replacing 5 inline field rows with a compact
  2-button row. These are occasional/advanced settings, not something every
  profile edit needs to see up front.
- Profile card: subtitle repeated the server address verbatim whenever a
  profile had no custom name (name falls back to serverAddr) — showing
  "1.2.3.4:50000" as both title AND subtitle, with transport mode tacked on
  the end of the second copy. Now only shown once; added maxLines/ellipsis
  so long addresses truncate instead of wrapping awkwardly.
- Mobile: removed the "Bypass Processes" field entirely (editor UI, prefs
  key, config JSON). Android per-app selection (Configure Split Tunneling)
  is the real, correct control here — a process-name text field doesn't map
  to anything meaningful on Android the way it does on desktop.
- Share icon changed from a QR icon (redundant — the modal already shows a
  QR code) to the standard Material share glyph. Share modal title no
  longer interpolates the profile's name, which — same root cause as
  above — can silently BE the raw server address; title is now generic
  ("Share Profile") so a screenshot/recording can't leak host:port through it.
- Contrast: the monochrome theme's colorScheme.primary is pure white
  (0xFFFFFFFF); several buttons hardcoded white text/icons on top of it
  (Bypass/Proxy mode toggles, Copy Link), making them invisible when active.
  Added an _onColor() helper (luminance-based black/white pick) and applied
  it everywhere a button's foreground sits on a theme color.
- "Configure Split Tunneling" appeared to hang for 10-15s before doing
  anything: MainActivity.kt's getInstalledApps handler enumerated every
  installed package AND decoded+re-encoded each one's icon synchronously
  inside the MethodChannel callback, which runs on the main/UI thread by
  default — blocking it for the whole duration meant Flutter couldn't
  render ANY frame, not even the loading spinner, until it finished. Moved
  the work onto a background Thread; only the final result.success() hops
  back via runOnUiThread(). Navigation + spinner now show immediately.
2026-07-10 00:45:30 +03:00
ospab 7d9e5faeec fix(flutter): eagle watermark rendered as a flat gray square
assets/logo.png had NO real alpha transparency — both the background and
the eagle shape were fully opaque (A=255 everywhere), just baked in as
near-black (3,3,3) vs near-white (253,253,253) RGB. Applying `color:
Colors.white` to tint it painted the WHOLE bounding square white (alpha
being 255 across the entire image gives BlendMode nothing to mask against),
which at low Opacity looked like a flat gray square instead of a silhouette.

Converted the asset in place: since it was already grayscale (R=G=B), each
pixel's luminance became its new alpha channel, RGB set to pure white. The
background (near-black, low luminance) is now near-transparent; the eagle
(near-white, high luminance) is now near-opaque. This is the same effect the
desktop GUI gets for free from its logo.svg (a vector eagle path with no
background element at all — inherently transparent), just reproduced for a
raster asset without adding flutter_svg as a new dependency.

The `color: Colors.white` tint in both watermark call sites is now
redundant (the asset is already a pure-white silhouette) and removed.
2026-07-10 00:24:28 +03:00
ospab eda2a0eba7 fix(flutter): increase watermark opacity and apply to settings 2026-07-10 00:09:55 +03:00
ospab 22c2d5edd8 feat(flutter): update UI theme to monochrome with eagle watermark 2026-07-09 23:57:58 +03:00
ospab fa7ec2cd9a feat(flutter): update launcher icons to new eagle design with round support 2026-07-09 23:52:37 +03:00
ospab c6d506e6c0 feat(flutter): profiles + per-profile junk/frag, drop WSS
Merges the best of both lineages instead of a blind revert to v0.3.21:
kept from v0.3.21: multi-profile management (add via QR scan/link/manual,
single-select active profile, auto-mode transport/MTU probing). Kept from
current: Share Config (QR generation), Check for Updates, curated stealth-SNI
domain list, and actually-rendered exclusions fields (v0.3.21 loaded/saved
them but never showed them in the UI — dead code).

New: junk packets (pc/ps min/max) and TCP fragmentation (chunk/sleep) are now
per-profile fields in the profile editor, mirroring the desktop GUI's profile
object shape 1:1 (ostp-gui/src/main.js) so behavior matches across platforms.

WSS is gone — removed from the model, the UI, and the config builder. The
core dropped TLS-mimicry transports entirely (see §A of the rebuild), so
there was nothing left for it to configure.

Config building now targets the flat single-server schema
(ostp_client::config::ClientConfig) built from ONE active profile, not the
old modular inbounds/outbounds/urltest-failover config — the core no longer
supports connecting to multiple servers at once, matching how the desktop
GUI already works (single activeId). Also dropped a dead nested "tun": {...}
object that neither version's JSON producer nor the real ClientConfig struct
ever actually used — serde silently ignored it.
2026-07-09 23:42:10 +03:00
ospab 61091b6d56 chore(release): 0.4.7 + fix resolve-channel prerelease labelling
resolve-channel treated EVERY v* tag as stable, so v0.4.6-beta got published
as a non-prerelease "Latest" release, sitting on top of the release line. Now
a pushed tag is used as-is and its suffix decides the channel: v*-alpha / v*-beta
are prereleases, only a bare vX.Y.Z is stable. (A tag is never recomputed from
Cargo.toml, so the release can't upload to a different tag than the one pushed.)

Version bumped 0.4.5 -> 0.4.7 (0.4.6 is already taken by the mislabelled beta).
This commit's tip is what gets tagged v0.4.7-beta to cut the beta build.
2026-07-09 14:58:40 +03:00
ospab e21acc2ee1 docs: update references from nightly to alpha 2026-07-09 02:49:33 +03:00
ospab d065f6ceca chore: release 0.4.4-nightly on nightly 2026-07-08 19:13:55 +03:00
ospab ec947ec9d1 chore: release 0.4.3-nightly on nightly 2026-07-08 18:13:37 +03:00
ospab f81610f939 chore: bump version to 0.4.2 2026-07-08 17:28:14 +03:00
ospab c330a0abe3 Fix UAC diagnostics parity, gk alias, flutter version, and versioned CI channels
- GUI launch_as_admin now matches the CLI's UAC diagnosis: detects
  ERROR_CANCELLED (1223, user declined the prompt) instead of silently
  treating it as success, and reports GetLastError()+exe path for any other
  ShellExecuteW failure, replacing the old single opaque "denied or missing"
  message that made GUI/TUI failures impossible to tell apart.
- generate-key subcommand renamed to `gk` (kept `generate-key` as an alias).
- Fixed a real short-flag collision: GenerateKey's --count used short='c',
  which collides with the global --config short (propagated into every
  subcommand); clap validates the whole command tree on first parse(), so
  this could break parsing for the entire CLI, not just generate-key/gk.
  --count is now short='n'.
- ostp-flutter/pubspec.yaml version was stuck at 0.2.97+12; bumped to 0.4.1+13.
- release.yml: added a resolve-channel job that computes one release tag per
  run instead of repeating the logic in five upload steps. Rolling channel
  pushes now carry the actual Cargo.toml version instead of a bare channel
  name: `{version}-nightly` for the nightly branch, `{version}-beta` for
  pre-release. workflow_dispatch gained a `channel` input restricted to
  nightly/beta only — a manual run can never accidentally publish a "stable"
  release; that still requires an explicit vX.Y.Z tag push.
2026-07-08 02:52:23 +03:00
ospab 7704e0bdb1 §A.3: remove dead tun2socks code (native OSTP TUN is the only path)
The "system" TUN stack that shelled out to a bundled tun2socks binary is
long-dead — Flutter already hardcodes the native OSTP stack — and only
bloats the build.

- ostp-jni: drop the tun2socks spawn branch and the tun_child handle;
  the native TUN (run_native_tunnel_from_fd) is now unconditional. The
  JNI signature is kept ABI-stable (t2sBinPath/localProxy retained but
  ignored) to avoid breaking the Kotlin linkage without an Android build.
- Delete the committed 10 MB tun2socks-arm64 asset; drop the tun2socks
  download steps from the Android build scripts.
- Remove the dead tun2socks.exe entry from the desktop build_dist.js
  (it required a file nothing downloads, breaking the GUI dist build).
- Reword stale tun2socks references in proxy.rs, the GUI config comment,
  install.ps1, the release workflow matrix, and CONTRIBUTING.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 16:29:55 +03:00
ospab 92d6b06d75 §A: remove WSS + Reality (TLS-mimicry); bump to 0.4.0 / AGPL-3.0
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>
2026-06-27 16:29:42 +03:00
ospab 04761fb6a3 Fix memory leaks, hang issues, gui helper token vulns, and log spam 2026-06-16 14:11:37 +03:00
ospab b841053628 fix(jni): add exclusions_rx param to run_native_tunnel_from_fd stub to fix non-Android builds 2026-06-14 01:49:06 +03:00
ospab c7bca41616 chore: fix JNI UoT handler args, center Flutter home screen metrics, update READMEs 2026-06-14 01:04:50 +03:00
ospab 486d745d47 feat(tun): implement process bypass for TCP/UDP and IP bypass for UDP using existing Extended tables 2026-06-14 00:02:08 +03:00
ospab 83ba39e59a feat(gui): split tunneling — tag-chip UI, process picker with live process list 2026-06-13 02:55:28 +03:00
ospab 55215567dd Fix all compilation errors and suppress all warnings across workspace 2026-06-13 02:30:57 +03:00
ospab 2a24ac34d0 Remove Reality/XTLS from all UI components and TSX pages (Dashboard, Settings, Tools) 2026-06-13 02:19:53 +03:00
ospab 3c54aba63f Remove Reality/XTLS UI from ostp-gui, ostp-flutter, ostp-control 2026-06-13 01:57:20 +03:00
ospab a9e4511190 Fix CLI setup permissions, enforce global debug tracing, and fix GUI silent startup crash 2026-06-13 01:25:54 +03:00
ospab 9f35caf4ca Remove built-in DNS server and owndns features 2026-06-10 22:52:35 +03:00
ospab 7bb7d211fa Remove stealth_port entirely and integrate fallback into UoT HTTP handler 2026-06-10 02:26:13 +03:00
ospab 730eab8553 feat: implement built-in DNS server, adblock and dns leak prevention 2026-06-07 19:55:42 +03:00
ospab 29e9ef739c Refactor: Phase 1 and 2 - Async architecture, JNI fixes, SmolTCP data races, and Tunnel optimizations 2026-06-03 02:06:06 +03:00
ospab ca9dd9ec06 fix(gui): remove tun stack selection, default to ostp; fix(flutter): add missing ic_launcher_background.xml for icon build 2026-06-02 23:27:04 +03:00
ospab f9e272d6bf chore: apply icon variant 2 (infinity tunnel) to tauri and flutter 2026-06-02 23:12:47 +03:00
ospab eb0a193fee fix(flutter): enforce MTU 1280 for Android TUN while passing 1140 to Rust core for TCP MSS clamping 2026-05-30 22:40:03 +03:00
ospab 95e72f6136 fix: remove IPv6 from Android TUN to allow MTU < 1280 and prevent crashes 2026-05-30 22:31:24 +03:00
ospab 472fb8dc11 feat: user configured MTU automatically subtracts 48 for overhead compensation 2026-05-30 22:24:08 +03:00
ospab 8825cf0838 fix: resolve deadlock, multiplexing backpressure, and LTE fragmentation issues 2026-05-30 22:21:12 +03:00