Commit graph

163 commits

Author SHA1 Message Date
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
4b0a597860 chore(scripts): rewrite update-version in python, add changelog-add
Replace the bash update-version.sh with a python equivalent that also
rotates the changelog (previous top-level → history[0], new empty
top-level for the new VERSION) and regenerates update-json/changelog.md
from the JSON source of truth.

Add changelog-add.py for appending a bilingual entry (EN + RU) to the
upcoming version's section.

Both scripts are uv inline scripts; shared helpers live in _changelog.py.
2026-04-16 00:18:25 +03:00
okhsunrog
b7adc38813 feat: detect gb.sweetlifecl as Russian app 2026-04-15 23:26:45 +03:00
okhsunrog
820afa7a55 docs: refresh README screenshots and install docs 2026-04-15 20:21:00 +03:00
okhsunrog
e1d4859e7f docs: update README for protection modes 2026-04-15 20:09:36 +03:00
okhsunrog
54267d87d8 chore: update-json for v0.6.0
Some checks are pending
CI / lint (push) Waiting to run
CI / kmod (android12-5.10) (push) Waiting to run
CI / kmod (android13-5.10) (push) Waiting to run
CI / kmod (android13-5.15) (push) Waiting to run
CI / kmod (android14-5.15) (push) Waiting to run
CI / kmod (android14-6.1) (push) Waiting to run
CI / kmod (android15-6.6) (push) Waiting to run
CI / kmod (android16-6.12) (push) Waiting to run
CI / zygisk (push) Waiting to run
CI / lsposed (push) Waiting to run
CI / portshide (push) Waiting to run
CI / release (push) Blocked by required conditions
2026-04-15 18:54:31 +03:00
okhsunrog
a5c21f262c chore: release v0.6.0 2026-04-15 18:42:08 +03:00
Danila Gornushko
c62a5d5613
Merge pull request #20 from okhsunrog/fix/rknhardering-linkproperties-routes
Fix LinkProperties route filtering for app-visible snapshots
2026-04-15 18:40:16 +03:00
okhsunrog
2ed0ce7241 Fix LinkProperties route filtering for target apps 2026-04-15 18:34:37 +03:00
Danila Gornushko
0b0c9818c3
Merge pull request #19 from okhsunrog/feat/ports-hiding
Add portshide module for localhost port blocking
2026-04-15 17:30:58 +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
5341c07781 Wire portshide into release + update-json pipeline
Mirror the kmod/zygisk plumbing so KernelSU-Next / Magisk pick up
portshide updates automatically:

- scripts/update-version.sh bumps portshide/module/module.prop along
  with the other modules when VERSION changes
- scripts/update-json.sh writes update-json/update-ports.json pointing
  at the current release zip
- CI appends updateJson=.../update-ports.json to the portshide
  module.prop before zipping, matching kmod/zygisk
- Dashboard reports portshide version mismatches as issues, with the
  same up/down/different wording the other modules use
2026-04-15 16:45:58 +03:00
okhsunrog
7faeb5ce9a CI: build vpnhide-ports.zip
Adds a portshide job mirroring the simple kmod zip packaging (no build
needed, just zip the module directory). Artifact lands next to the
other release zips so the gh-release step picks it up for tagged
builds.
2026-04-15 16:41:38 +03:00
okhsunrog
d8ffc24712 Show portshide module in Dashboard
Add a fourth module card under Modules showing ports module install
state, iptables chain active-ness, and configured observer count.
Detected via /data/adb/modules/vpnhide_ports presence plus a quick
`iptables -L vpnhide_out` probe to confirm service.sh has applied the
chain.

Add an issue card when the module is installed but observers.txt is
empty, pointing the user to Protection → Ports.
2026-04-15 16:40:42 +03:00
okhsunrog
c967040660 Add Ports mode UI for managing observers
Replaces the ComingSoonPlaceholder in Protection → Ports with a real
picker. Lists installed apps with a single P chip per row — tapping it
toggles the app as a localhost-proxy-hide observer. On Save, resolves
package names to UIDs, writes /data/adb/vpnhide_ports/observers.txt,
then invokes the portshide module's apply script via su so iptables
rules update immediately (no reboot needed).

If the portshide module isn't installed, shows a hint card explaining
how to install vpnhide-ports.zip via KernelSU-Next or Magisk.

Help dialog becomes mode-aware for Ports too: explains the P role,
what connect() behavior observers see (ECONNREFUSED), and which app
categories are safe to mark as observers (banks / госуслуги /
marketplaces yes; Chromium-based browsers no).
2026-04-15 16:26:51 +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
Danila Gornushko
60213cf237
Merge pull request #17 from okhsunrog/feat/package-visibility
Add app-to-app package visibility hooks
2026-04-15 16:03:48 +03:00
Danila Gornushko
92e7eac07e
Merge pull request #18 from okhsunrog/fix/ifconf-sock-do-ioctl
Hook sock_ioctl instead of dev_ifconf for SIOCGIFCONF
2026-04-15 16:03:37 +03:00
okhsunrog
c882586032 Hook sock_ioctl instead of dev_ifconf for SIOCGIFCONF filtering
On GKI 5.10 kernels built with Clang LTO, dev_ifconf() gets inlined
into sock_do_ioctl(). The symbol remains in kallsyms as a dead stub,
so kretprobe registration succeeds but the probe never fires.
Confirmed by disassembly on Xiaomi 13 Lite (5.10.136) and Lenovo
Legion 2 Pro (5.10.101).

On 6.1+, SIOCGIFCONF was moved from sock_do_ioctl() into sock_ioctl()
directly, so hooking sock_do_ioctl would miss it on newer kernels.

sock_ioctl is the file_operations->unlocked_ioctl callback — used as
a function pointer, so LTO cannot inline it. SIOCGIFCONF passes through
it on every kernel version. After it returns, ifconf data is already in
userspace, so we filter uniformly via copy_from_user/copy_to_user with
no version-specific code paths.
2026-04-15 15:54:37 +03:00
okhsunrog
692c8dcd33 Add Protection tab UI with VPN / Apps / Ports modes
Rename the Apps tab to Protection and put a segmented button on top
that selects between three sub-modes: Tun (existing VPN target picker),
Apps (new package-visibility picker with H/O chips per app), and Ports
(placeholder — coming soon).

App Hiding reads/writes vpnhide_hidden_pkgs.txt and vpnhide_observer_uids.txt,
resolves observer package names to UIDs at save time. Self-package is always
added to the hidden list both at app startup (ensureSelfInTargets) and on
Save — managed invisibly, not shown in the app list.

Help dialog is mode-aware: Tun shows the existing L/K/Z hints, Apps shows
the new H/O hints with Russian labels spelling out Hidden / Observer
explicitly, Ports has no help.
2026-04-15 15:30:15 +03:00
okhsunrog
23e2ca292b Add package visibility hooks in system_server
Hides selected packages from selected caller UIDs at the PackageManagerService
Binder stub. Filters getInstalled{Packages,Applications}, queryIntent*,
resolve{Intent,Service}, get{Package,Application}Info, getPackageUid,
getPackagesForUid, getInstaller{PackageName,SourceInfo}. Hooks
IPackageManagerBase with PackageManagerService fallback.

Config via /data/system/vpnhide_hidden_pkgs.txt and
/data/system/vpnhide_observer_uids.txt with inotify live-reload. Callers
with UID < 10000 are exempt to avoid breaking installd / LauncherApps.
2026-04-15 14:55:26 +03:00
okhsunrog
cffb52776b Fix logcat collection — read directly without su
logcat via su runs as root and can't see app's own log entries on some
devices. Use Runtime.exec("logcat") directly instead, which reads the
app's own log buffer without needing READ_LOGS permission.
2026-04-15 14:17:32 +03:00
okhsunrog
3d138f914c chore: update-json for v0.5.3 2026-04-15 00:56:23 +03:00
okhsunrog
00a40db04c chore: bump version to v0.5.3 2026-04-15 00:49:37 +03:00
okhsunrog
1a1b69a3e3 Fix clang-format violations in kmod 2026-04-15 00:40:45 +03:00
okhsunrog
f67cb40925 Add debug logging toggle and diagnostic export
kmod: add /proc/vpnhide_debug toggle — writing "1" enables detailed
pr_info logging in all 6 kretprobe hooks (uid, target, interface name,
filter decisions). Disabled by default, zero overhead when off.

app: add "Collect debug log" button on Diagnostics screen. Enables
kmod debug, clears dmesg, runs all checks, captures dmesg, collects
device info, module status, targets, interfaces, /proc/net, kallsyms,
LSPosed config, root manager version, and logcat into a zip. Save to
disk or share via share sheet.

Also: remove unused kmod/symvers/, add kmod/*.lds to .gitignore.
2026-04-15 00:35:29 +03:00
okhsunrog
832b78c087 Split update-version.sh into two scripts
- scripts/update-version.sh — updates source files (module.prop, Cargo.toml, etc.)
- scripts/update-json.sh — generates Magisk/KSU update-json files

update-json must be committed AFTER the release is published to avoid
a race where Magisk sees a new version but the zip doesn't exist yet.
2026-04-14 17:36:26 +03:00
okhsunrog
8420965cd9 chore: bump version to v0.5.2 2026-04-14 17:03:50 +03:00
Danila Gornushko
a04d3748f3
Merge pull request #14 from okhsunrog/fix/ifconf-5.10
Fix SIOCGIFCONF filtering on kernel 5.10
2026-04-14 17:02:04 +03:00
okhsunrog
ca9773d14f Fix hardcoded v0.1.0 in customize.sh — read version from module.prop 2026-04-14 16:56:57 +03:00
okhsunrog
c1a1e37b73 Fix unsafe block in netlink_recv for Rust 2024 edition 2026-04-14 16:45:43 +03:00
okhsunrog
aa2d6c098c Fix SIOCGIFCONF filtering on kernel 5.10
dev_ifconf() changed its signature between 5.10 and 5.15:

  5.10:  dev_ifconf(struct net *, struct ifconf *ifc, int size)
         x1 = kernel pointer (caller did copy_from_user)
  5.15+: dev_ifconf(struct net *, struct ifconf __user *uifc)
         x1 = userspace pointer

The kretprobe handler assumed 5.15+ (copy_from_user on x1), which
silently failed on 5.10 because copy_from_user on a kernel pointer
returns EFAULT. This left SIOCGIFCONF unfiltered — tun0 visible.

Use LINUX_VERSION_CODE to select the right access method at compile
time. Each kmod build already targets a specific GKI generation, so
this is safe.

Reported by users on Android 12 (5.10) and Android 14 (non-GKI 5.10).
2026-04-14 16:14:14 +03:00
okhsunrog
14bdfd9650 Hook recv for netlink filtering on Android 10 (no SELinux block)
On Android 10 and devices with permissive SELinux, netlink RTM_GETLINK
is not blocked by sepolicy. The existing recvmsg hook covers most
callers (bionic getifaddrs, Java NetworkInterface), but code using
recv() goes through recvfrom via a bare branch — a different syscall
path. Hooking recvfrom directly breaks recv (shadowhook overwrites the
branch target), so we hook recv instead (12 bytes, safe for island mode).

Also switch diagnostic checks from recv to recvmsg so they go through
the hooked path, and add a separate recv-based check for full coverage.
2026-04-14 16:00:59 +03:00
okhsunrog
6590c8344f Fix zygisk first-launch race: dashboard waited on stale selfNeedsRestart
ensureSelfInTargets() and loadDashboardState() ran as independent
coroutines, so the dashboard could read selfNeedsRestart=false before
the init completed. On slower devices (Pixel 4a) this caused "Installed,
inactive" instead of the restart prompt.

- Make selfNeedsRestart nullable; show spinner until resolved
- Sync zygisk targets to module dir so next app fork picks them up
- Show "restart app to activate" instead of misleading "inactive"
- Add scripts/clean-device.sh for testing fresh installs via adb
2026-04-14 15:24:20 +03:00
okhsunrog
7f410432d4 Fix license badge: use static MIT badge 2026-04-14 03:48:08 +03:00
okhsunrog
ac597680dc Add Star History chart to README 2026-04-14 03:47:31 +03:00
okhsunrog
56c83f0fc3 Add badges to README 2026-04-14 03:44:58 +03:00
okhsunrog
8030c2b7c7 Fix module changelog: use raw markdown instead of HTML release page
KernelSU-Next and Magisk fetch the changelog URL and display it as text.
Pointing to the GitHub releases HTML page showed raw HTML tags.
Now points to a raw markdown file that renders correctly.
2026-04-14 03:30:04 +03:00
okhsunrog
b68fc25b2c Fix ktlint indentation in DashboardData 2026-04-14 03:07:02 +03:00
okhsunrog
64cc4be1f0 Add pre-commit hook for ktlint 2026-04-14 03:04:57 +03:00
okhsunrog
20bcbc3b3e Fix ktlint formatting in DashboardData 2026-04-14 03:03:32 +03:00
okhsunrog
5aadb0165b Rename APK artifact from vpnhide-lsposed to vpnhide 2026-04-14 03:00:10 +03:00
okhsunrog
0073ef7030 Fix false LSPosed warnings and improve target detection
- Detect LSPosed in all known module paths (zygisk_vector, zygisk_lsposed, lsposed)
- Skip LSPosed config warnings when hooks are already active at runtime
- Check all modules for empty targets, not just LSPosed
- Bump version to v0.5.1
2026-04-14 02:57:37 +03:00
okhsunrog
7e9c1def9c Add screenshots to README and rename branding to assets 2026-04-14 00:46:02 +03:00
okhsunrog
e5a85c5b7d chore: bump version to v0.5.0 2026-04-14 00:39:21 +03:00
Danila Gornushko
f6678868e5
Merge pull request #13 from okhsunrog/fix/hook-race-condition
Fix system_server crash: copy-on-write for writeToParcel hooks
2026-04-14 00:14:48 +03:00
okhsunrog
0d41f15ae6 Fix system_server crash: use copy-on-write instead of mutating shared objects
The writeToParcel hooks were mutating the real NetworkCapabilities,
NetworkInfo, and LinkProperties objects in beforeHookedMethod and
restoring them in afterHookedMethod. Between before and after, other
ConnectivityService threads could read the mutated object, causing
IllegalStateException in checkNrisConsistency ("This NRI is already
registered") and crashing system_server.

Fix: create a copy of each object, modify the copy, write the copy
to the Parcel, and skip the original writeToParcel via setResult(null).
The original object is never mutated. ThreadLocal re-entrancy guard
prevents infinite recursion when the copy's writeToParcel triggers
the same hook.
2026-04-14 00:09:48 +03:00
Danila Gornushko
4c859b21e8
Merge pull request #12 from okhsunrog/fix/zygisk-api-v2
Lower zygisk API from v5 to v2 for Magisk v27 compatibility
2026-04-14 00:04:14 +03:00