Commit graph

10 commits

Author SHA1 Message Date
okhsunrog
c059c64582 fix(zygisk): cover libc socket-interface binds 2026-07-13 21:57:05 +03:00
okhsunrog
bca81b80e7 fix: block socket binds to hidden VPN interfaces 2026-07-13 20:22:51 +03:00
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
okhsunrog
3c7853d2d5 chore: bump internal crates (activator, protocol) to 1.0.0
Don't leave the shared vpnhide_activator / vpnhide_protocol crates on the
old version while the release is 1.0.0. release.py now bumps them too.
2026-07-01 22:48:01 +03:00
Danila Gornushko
c5d89c3dd9
Block the whole loopback range; warn on native-target overflow (#208)
* fix(ports): block the whole loopback range; warn on native-target overflow

Two activator findings from the codebase audit.

The localhost port blocker only rejected 127.0.0.1, so a proxy/VPN daemon bound
to the wildcard 0.0.0.0 (the common allow-lan / TUN setup for Clash, sing-box,
V2Ray) stayed reachable on any other 127.x.x.x alias — an observer could
connect(127.0.0.2:port) and get a handshake a clean device would refuse, a
positive fingerprint. Reject the whole 127.0.0.0/8 block instead (::1 already is
the entire IPv6 loopback).

The native-target cap (64) was restated as a bare literal in three places (the
activator and both C backends) and projection truncated the overflow with a
silent .take(), dropping the highest-UID apps from protection with no diagnostic.
Export the cap once from the shared protocol crate, alias it in the activator,
cross-reference it from the C #defines, and warn on stderr when the target set
exceeds it.

* style: rustfmt activator loopback comment

* docs(changelog): note the native-target overflow warning
2026-06-30 11:31:18 +03:00
Danila Gornushko
5cbdc54e4f
Drop dead proc diagnostics, fix misaligned reads, align parser parity (#206)
* fix(native): drop dead proc diagnostics, fix misaligned reads, parser parity

Three native-correctness fixes from the codebase audit.

Diagnostics: /proc/net/{tcp,tcp6,udp,udp6,fib_trie} expose the VPN only as a
hex local address, never as an interface name, so the name-matching probe could
only ever report a green "no VPN entries" regardless of an actual leak — and
from inside the targeted (self-hidden) process there is no reference tunnel
address to decode and compare. Remove those five checks rather than keep a
meaningless always-pass; the address-leak vector on these files is covered by
zygisk's socket-table filters. /proc/net/{route,ipv6_route,if_inet6,dev}, which
do carry interface names, are unchanged.

UB: SIOCGIFCONF and the netlink dumps reinterpret the kernel's bytes as ifreq /
nlmsghdr / rtattr over plain [u8; N] buffers (align 1), so forming those refs is
undefined behaviour. Back the three buffers with an 8-byte-aligned wrapper so
every such reference is well-formed.

Protocol parity: the Rust parse_header skipped a non-ASCII first significant
line and searched on, while C (kmod/KPM) and Kotlin (LSPosed) reject the whole
payload — same wire bytes, different accept decision across the mutually
exclusive backends. Distinguish "blank/comment" (skip) from "significant but
non-ASCII" (reject) so all three agree. Clarify the §4.2 corner in the spec and
add header-position golden vectors (cfg + kind) that all three parsers now pass.

* style: rustfmt protocol parse_header
2026-06-30 11:30:11 +03:00
okhsunrog
52b137b78e Add backend-specific native hook selection 2026-06-29 19:24:03 +03:00
okhsunrog
552762a246 Add LSPosed interception stats 2026-06-29 02:43:23 +03:00
okhsunrog
dd2a8038e9 feat(storage): add native config activators 2026-06-28 17:47:45 +03:00