Commit graph

20 commits

Author SHA1 Message Date
okhsunrog
e6723861bf chore: release v1.1.1 2026-07-05 15:11:38 +03:00
okhsunrog
6b6ed490ed chore: release v1.1.0 2026-07-04 23:32:51 +03:00
Danila Gornushko
5902c0f86c
Upgrade diagnostic captures (#227)
Some checks are pending
CI / kmod-activator (push) Blocked by required conditions
CI / kmod (android12-5.10) (push) Blocked by required conditions
CI / kmod (android13-5.10) (push) Blocked by required conditions
CI / kmod (android13-5.15) (push) Blocked by required conditions
CI / kmod (android14-5.15) (push) Blocked by required conditions
CI / kmod (android14-6.1) (push) Blocked by required conditions
CI / kmod (android15-6.6) (push) Blocked by required conditions
CI / kmod (android16-6.12) (push) Blocked by required conditions
CI / kmod-qemu (android12-5.10) (push) Blocked by required conditions
CI / kmod-qemu (android13-5.10) (push) Blocked by required conditions
CI / kmod-qemu (android13-5.15) (push) Blocked by required conditions
CI / kmod-qemu (android14-5.15) (push) Blocked by required conditions
CI / kmod-qemu (android14-6.1) (push) Blocked by required conditions
CI / kmod-qemu (android15-6.6) (push) Blocked by required conditions
CI / kmod-qemu (android16-6.12) (push) Blocked by required conditions
CI / kpm-qemu (android12-5.10) (push) Blocked by required conditions
CI / kpm-qemu (android13-5.10) (push) Blocked by required conditions
CI / kpm-qemu (android13-5.15) (push) Blocked by required conditions
CI / kpm-qemu (android14-5.15) (push) Blocked by required conditions
CI / kpm-qemu (android14-6.1) (push) Blocked by required conditions
CI / kpm-qemu (android15-6.6) (push) Blocked by required conditions
CI / kpm-qemu (android16-6.12) (push) Blocked by required conditions
CI / kpm-qemu-legacy (4.14) (push) Blocked by required conditions
CI / kpm-qemu-legacy (4.19) (push) Blocked by required conditions
CI / kpm-qemu-legacy (5.4) (push) Blocked by required conditions
CI / kpm (push) Blocked by required conditions
CI / zygisk (push) Blocked by required conditions
CI / lsposed (push) Blocked by required conditions
CI / portshide (push) Blocked by required conditions
CI / release (push) Blocked by required conditions
* feat: upgrade diagnostic captures

Collect richer debug and full-logcat bundles with device, backend, hook, portshide, and kernel partition evidence.

Add an explicit kernel image export for maintainer-requested kernel analysis.

* fix: harden diagnostic capture sessions

* fix(lsposed): harden diagnostic export error paths from review

Address correctness findings from a review of the diagnostic-capture upgrade,
all validated on a Pixel 4a via the agent bridge (kernel/debug/logcat exports).

- Kernel image export: wrap exportKernelImagesZip so a zip/IO failure returns
  null (and cleans the parts dir) instead of escaping and stranding the export
  button disabled; add try/finally at the DiagnosticsScreen call site. Cap the
  per-partition dd (skip unknown/oversized partitions, bound with count=) so a
  mislabelled or huge partition can't fill /data.
- HookDiagnostics: drive counter deltas off an explicit "baseline captured"
  flag instead of baselineCounters.isEmpty(), so a fresh boot with an empty
  baseline no longer reports every delta as n/a. Add HookDiagnosticsTest.
- DebugShellSnapshot: raise the 20s snapshot timeout to 60s and preserve+flag a
  timeout-truncated section instead of silently dropping it and every later one.
- LogcatRecorder: delete the intermediate raw logcat file after zipping and on
  failed start, so repeated captures stop leaking multi-MB files into cache.
- DebugExport: rethrow CancellationException before the generic catch so
  navigating away mid-capture cancels cleanly instead of logging a false error.
- DebugCaptureLogging: when the on-disk canonical config is present but
  unparseable, refuse the targets-snapshot rebuild (which would reset settings
  and clear autoHiddenPackages); fall back to an app-process-only toggle.
- Dashboard: don't warn "ports rules not active" for a module the user disabled
  via their manager (new ports_disabled probe, mirrors the activator's guard).
- activator write_atomic: per-process temp name so a boot-time and app-triggered
  activation can't corrupt each other's load_status.
- Drop the wasted multi-user pm enumeration from the counter baseline command.
2026-07-02 16:25:53 +03:00
Danila Gornushko
1582efa067
docs: refresh installation/backend docs + 1.0.0 screenshots (#224)
* docs: refresh installation and backend docs

* docs: fix review findings and add KPM to update-json

Cross-checked the docs refresh against the code and corrected:
- protocol.md: config parser is vpnhide_parse_config (not the legacy
  vpnhide_parse_target_uids); path is kmod/shared/vpnhide_logic.h; drop the
  unverified 0x2026 KPatch-Next marker (activator drives it via the CLI).
- zygisk/README: module declares Zygisk API v2 (not v5); add the recv hook
  row and the if<N> renamed-netdev match.
- README (en/ru): live-check counts are 13 native / 12 Java; Diagnostics is
  under Settings, not a tab; mention the Statistics tab; note KPM beta parity.
- detection-vectors: KPM host-route helper is kpm_is_public_host_route{4,6};
  restore CONFIG_KPROBES and the Zygisk qualifiers; codegen renders four targets.
- storage.md: legacy files are no longer user-managed (migration inputs), not
  'gone'. CLAUDE.md: activator has four bins (kmod/kpm/zygisk/ports).
- development/ROADMAP/kmod/lsposed/portshide READMEs + AGENTS.md: assorted
  accuracy fixes (KPM needs a KernelPatch runtime, per-KMI kmod zip name, etc.).
- CONTRIBUTING.md: clang-format uses scripts/clang-format-c.sh (covers KPM src).
- portshide customize.sh: 'Hiding -> Ports' (renamed tab).
- update-json.sh: emit update-kpm.json so KPM gets Magisk/KSU update checks.

* docs: correct diagnostics check count (25, not 26 vectors)

* docs: refresh README screenshots for the 1.0.0 UI

Replace the v0.5.3-era screenshots (old per-tab Protection UI) with a
new 1.0.0 set: VPN-hidden dashboard, the unified Hiding list with
J/N/A/P, the Statistics tab + per-hook breakdown, per-app hook selection,
diagnostics, settings, and the community screen. Extra shots
(statistics-apps, settings-advanced, diagnostics-java, settings-developer)
are included for the release notes.

* docs: fix the how-it-works layer breakdown

The old 'Layer 3 — additional app-level controls' bucket was wrong:
interface hiding is what Layers 1+2 already do, app-hiding is done by the
LSPosed/Java layer (system_server PackageManager hooks), and ports is a
separate module. Fold app-hiding into Layer 1 (LSPosed) and make Layer 3
the standalone portshide module.

* docs: conceptual-coherence pass on the 5 core docs

Second review pass, this time for architectural coherence rather than
code-facts. Fixes:
- README (en/ru): 'What vpnhide hides' stopped reifying interface hiding
  as a standalone 'layer'/'role' and now ties the three hiding goals to
  the four J/N/A/P roles (interface = Java + Native, toggled independently)
- README (ru): add the KPM-beta hook-parity caveat (parity with the EN side)
- protocol.md: app-hiding is a normal lsposed mask bit, not a separate
  'package/observer records' entry in the §6 profile table
- detection-vectors.md: a complete install is two components (native + lsposed),
  not 'two roles'; name both lsposed jobs
- storage.md: scope the text protocol to the config wire (LSPosed reuses the
  format for its state file); 'by function' not 'by role'; note the Apps role
  shares the same resolver; heading no longer files ports under 'Native layer'
2026-07-02 00:03:17 +03:00
okhsunrog
1bbfed6e70 chore: release v1.0.0 2026-07-01 22:30:34 +03:00
okhsunrog
69f0a92716 feat(storage): apply ports through activator 2026-06-28 19:01:44 +03:00
okhsunrog
c6cf8607d7 fix(storage): clean up legacy config leftovers 2026-06-28 18:51:47 +03:00
okhsunrog
b5790766e7 feat(storage): migrate app to canonical config 2026-06-28 18:27:51 +03:00
okhsunrog
68da0be38e portshide: TODO for per-app port-range rules
Note the path to per-UID port-range blocking (iptables --dports) so observers
stop being all-localhost-blocked — keeps the backend-independent netfilter
approach instead of a kernel connect-hook. No behaviour change.
2026-06-28 13:59:39 +03:00
okhsunrog
3fb956eb74 fix(portshide): re-apply iptables 30s after boot in case netd flushes
service.sh waits for netd's bw_OUTPUT chain to appear, then applies our
rules once. On slow boots netd has been observed to flush/rebuild its
own chains AFTER bw_OUTPUT first appears — wiping the rules we just
installed. The rules then stay missing until the user opens the app
and Save runs apply again.

Add a backgrounded second pass 30 seconds after the first apply. The
apply script is already idempotent (chains created with
`-N ... 2>/dev/null || true`, atomically rebuilt via
`iptables-restore --noflush`), so the extra pass is harmless when
nothing was wiped and self-healing when it was. Cost is one shell
process and one iptables-restore per boot.

shellcheck clean (no new lint).
2026-04-27 02:45:51 +03:00
okhsunrog
7f22875e6b chore: release v0.7.1 2026-04-21 16:45:04 +03:00
okhsunrog
4cf512c6ae chore: release v0.7.0 2026-04-20 02:54:26 +03:00
okhsunrog
16578a15d2 feat: target apps across all user profiles (work profile, etc.)
Android user profiles (work profile, MIUI Second Space, Private Space,
secondary users) each give the same package its own UID in the
namespace `<user>*100000 + <app_id>`. Previously every pkg→UID
resolver used plain `pm list packages -U`, which only emits UIDs for
the primary user, so the work-profile copy of Telegram kept seeing
the VPN even though the user had marked Telegram as a target.

Switch every resolver to `pm list packages -U --user all`. The pm
output format for multi-profile apps is comma-separated on one line:

    package:com.android.chrome uid:10187,1010187

Each call site now splits on `,` and emits one UID per line so every
profile's copy is individually matched by the hooks. No UI changes —
"mark Telegram as a target" just now means "in every profile it's
installed in".

Resolvers touched (all places found by an audit, no duplicates left):

  Shell (boot-time):
    kmod/module/service.sh
    zygisk/module/service.sh
    portshide/module/vpnhide_ports_apply.sh

  Kotlin (save-time via suExec):
    AppPickerScreen.kt       — buildUidResolver
    AppHidingScreen.kt       — buildHidingUidResolver
    ShellUtils.kt            — ensureSelfInTargets
    TargetsCache.kt          — PM_LIST batch script + parser

Verified on a Pixel 4a with a managed profile (user 10):
  - Chrome toggled in LZ on primary → both 10187 and 1010187 land in
    /data/system/vpnhide_uids.txt.
  - Primary-only apps (Ozon, etc.) still resolve to a single UID.
  - ensureSelfInTargets correctly adds both UIDs when vpnhide is
    installed across profiles.
2026-04-20 01:27:11 +03:00
okhsunrog
b85673c81c chore: release v0.6.2 2026-04-17 16:24:53 +03:00
okhsunrog
53aacaa870 chore: release v0.6.1 2026-04-16 00:24:58 +03:00
okhsunrog
a37b1b7cd8 fix(modules): add META-INF for Magisk versions before v28
Magisk before v28 requires META-INF/com/google/android/update-binary
+ updater-script in module zips to extract them; without these the
manager fails with an unpack error (issue #23). Magisk v28+ removed
this requirement, which is why the bug only shows up on older managers.

Added the standard Magisk template (same one already used by the
zygisk module) to portshide and kmod. CI's `(cd module && zip -qr)`
step picks up the new files automatically.
2026-04-16 00:23:05 +03:00
okhsunrog
a5c21f262c chore: release v0.6.0 2026-04-15 18:42:08 +03:00
okhsunrog
529be11adf Fix pkg regex-injection + log pm-never-ready in apply.sh
Address second-pass review of PR #19:

apply.sh was feeding package names to grep as a regex. Package names
contain dots, which regex treats as "any char" — so resolving e.g.
\"com.x.y\" could land on a neighbouring \"comXxXy\" package and
silently block the wrong UID. Switch to awk with literal field
comparison, eliminating the class entirely.

While there, log explicitly when the boot-time pm readiness loop times
out after 30s, so apply.sh's \"0 observer(s)\" message is no longer
ambiguous between "user selected nothing" and "pm never came up".

Minor polish: drop the empty-body null-branch comment in PortsHidingScreen
and simplify body-string construction with joinToString(postfix).
2026-04-15 17:04:44 +03:00
okhsunrog
b2510e3526 Address PR #19 review: pkg-name config + robustness fixes
Move UID resolution from Save-time to apply-time so app reinstalls
(which rotate UIDs) get picked up automatically without manual Save.
observers.txt now stores one package name per line — vpnhide_ports_apply.sh
reads it, queries \`pm list packages -U\`, and resolves to UIDs inline
when building the iptables ruleset. Same pattern kmod's service.sh
already uses for its targets.

Other review points:
- uninstall.sh loops \`-D OUTPUT -j …\` so duplicate jumps are fully
  cleaned up, and redirects all probes to /dev/null
- PortsHidingScreen detects the module via \`cat module.prop\` rather
  than \`[ -d \$dir ]\` — a KSU-Next remove-pending dir stays on disk
  until reboot, so bare dir-check misreports install state
- Dashboard observer count now uses the existing countTargets helper,
  consistent with kmod/zygisk line counting
- Dropped the awkward \`when (moduleInstalled) { null, true -> Unit;
  false -> … return }\` in a Composable — plain if/else reads cleaner
- Comment on apply.sh explaining v4/v6 restores are per-family, not
  transactional — if v6 fails, v4 rules are already live
- Simplified buildPortsSaveCommand: no more per-package UID resolver
  shell-script construction, just a base64-encoded newline list
2026-04-15 16:57:33 +03:00
okhsunrog
2b2b144cd7 Add portshide module for localhost port blocking
New standalone Magisk / KernelSU-Next module that rejects TCP/UDP
connections from selected UIDs to 127.0.0.1 / ::1 via iptables
owner-match rules. Covers the VPN/proxy detection vector where an app
probes well-known localhost ports (7890, 1080, etc.) via
connect() — the observer gets ECONNREFUSED, indistinguishable from
a real closed port.

Rules live in a dedicated chain `vpnhide_out` / `vpnhide_out6` with a
jump from OUTPUT, applied atomically via iptables-restore. Configured
by /data/adb/vpnhide_ports/observers.txt (one UID per line, UID < 10000
filtered out for safety). service.sh re-applies at boot after netd
finishes its own chain setup. uninstall.sh flushes on module removal.

No C code, no per-kernel builds, no Rust FFI — just a shell script
leveraging the iptables binary that ships with every Android ≥ 4.
Verified on Pixel 8 Pro (Android 16) with iptables 1.8.11 legacy:
observer UID gets REJECT, non-observer UIDs are unaffected.
2026-04-15 16:17:00 +03:00