You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"Exclude from TrackerControl" currently means "leave the VPN" (apply = false → addDisallowedApplication, ServiceSinkhole.java:1778). That is a kernel-level
bypass, and it is not what the toggle is supposed to mean.
Consequences:
It is incompatible with always-on VPN + "block connections without VPN":
under lockdown an excluded app gets no network, not the raw network.
Toggling it requires rebuilding the tun, so it cannot change at runtime.
What we actually want from "exclude" is a passthrough: the app stays in the
tun, its packets are relayed unchanged, and no block decision or recording is
made for it.
Scope of the change
Once a packet is in the tun there is no bypass — it can only leave through a
protected socket, i.e. handle_tcp / handle_udp. So passthrough cannot skip
the relay. It skips the per-session work: the create_packet + is_address_allowed JNI upcall, the DB write, the SNI reassembly, the logging.
The per-packet copy stays, so throughput and battery land roughly where filtered
apps already are. The win is semantic (lockdown-compatible, runtime-toggleable),
not performance.
The mechanism largely exists already: tracker_protect = false is passthrough with monitoring — in the tun, seen, not blocked. The missing state is "in the
tun, relayed, not recorded". That is one more verdict at the same fork in handle_ip() (ip.c:344) that #730 turned into route_decide(), and can follow
the same shape: a sorted UID array pushed over JNI, an I/O-free filter_decide(),
mirrored by a JVM-testable Java class.
Open questions (design, not plumbing)
System apps.!includeSystem && rule.system uses the same addDisallowedApplication path. Converting that set to userspace passthrough
would drag all system traffic through the relay — a real regression. Argues for
keeping the kernel exclusion available as a separate, clearly-labelled escape
hatch rather than replacing it.
DNS. Port 53 skips the UID lookup entirely today, so a passthrough app's
queries would still be parsed and attributed unless we pay the fwd53-style
cost described in Route apps around the remote VPN without leaving TrackerControl #730. Since attribution is global anyway, "still monitored"
is probably right — but then "excluded" no longer means invisible, and shouldTrackApp (ServiceSinkhole.java:2431) has to change to match.
Configurability. This is a third orthogonal axis on top of Route apps around the remote VPN without leaving TrackerControl #730's two.
Given the simplicity-over-configurability rule, it should fold into the
existing per-app control as a tri-state rather than becoming a new switch.
Proposal
Make passthrough the default meaning of the per-app exclusion toggle, and keep addDisallowedApplication as a separate escape hatch for apps that genuinely
break inside a userspace stack (VoIP, captive portals).
"Exclude from TrackerControl" currently means "leave the VPN" (
apply = false→addDisallowedApplication,ServiceSinkhole.java:1778). That is a kernel-levelbypass, and it is not what the toggle is supposed to mean.
Consequences:
under lockdown an excluded app gets no network, not the raw network.
in the tunnel — in exactly the way Route apps around the remote VPN without leaving TrackerControl #730 has just separated is this app
filtered from is this app routed through the remote VPN.
What we actually want from "exclude" is a passthrough: the app stays in the
tun, its packets are relayed unchanged, and no block decision or recording is
made for it.
Scope of the change
Once a packet is in the tun there is no bypass — it can only leave through a
protected socket, i.e.
handle_tcp/handle_udp. So passthrough cannot skipthe relay. It skips the per-session work: the
create_packet+is_address_allowedJNI upcall, the DB write, the SNI reassembly, the logging.The per-packet copy stays, so throughput and battery land roughly where filtered
apps already are. The win is semantic (lockdown-compatible, runtime-toggleable),
not performance.
The mechanism largely exists already:
tracker_protect = falseis passthroughwith monitoring — in the tun, seen, not blocked. The missing state is "in the
tun, relayed, not recorded". That is one more verdict at the same fork in
handle_ip()(ip.c:344) that #730 turned intoroute_decide(), and can followthe same shape: a sorted UID array pushed over JNI, an I/O-free
filter_decide(),mirrored by a JVM-testable Java class.
Open questions (design, not plumbing)
!includeSystem && rule.systemuses the sameaddDisallowedApplicationpath. Converting that set to userspace passthroughwould drag all system traffic through the relay — a real regression. Argues for
keeping the kernel exclusion available as a separate, clearly-labelled escape
hatch rather than replacing it.
queries would still be parsed and attributed unless we pay the
fwd53-stylecost described in Route apps around the remote VPN without leaving TrackerControl #730. Since attribution is global anyway, "still monitored"
is probably right — but then "excluded" no longer means invisible, and
shouldTrackApp(ServiceSinkhole.java:2431) has to change to match.uid == -1trap as Route apps around the remote VPN without leaving TrackerControl #730. Easier here: stamp theverdict on the session at creation, since existing sessions already
short-circuit to
allowed = 1.Given the simplicity-over-configurability rule, it should fold into the
existing per-app control as a tri-state rather than becoming a new switch.
Proposal
Make passthrough the default meaning of the per-app exclusion toggle, and keep
addDisallowedApplicationas a separate escape hatch for apps that genuinelybreak inside a userspace stack (VoIP, captive portals).
Follows on from #730.