testsAndMisc/phone_focus_mode/magisk_service.sh
Krzysztof kuhy Rudnicki ef892eb162 phone_focus_mode: block hotspot/tethering to close the second-phone bypass
The focus system only ever filtered this phone's own traffic: /system/etc/hosts
via the system resolver, dns_enforcer and the curfew net layer via OUTPUT. A
tethered second phone's packets are FORWARDed + NAT'd through us on a path none
of that covers, so a second phone on the hotspot browses freely on our mobile
data and defeats focus mode.

Add tether_enforcer.sh: an always-on daemon that acts while focus mode is ON
(at home) or a force-test file is present, converging three levers each tick:
  1. disable Android tether offload (settings global tether_offload_disabled=1,
     snapshot/restore) so forwarded traffic goes through netfilter;
  2. blanket REJECT of the FORWARD chain (iptables + ip6tables, FOCUS_TETHER_BLOCK
     pinned at position 1), rebuilt only when tampered via a chain_intact gate so
     it does not fork an `iptables -L` every second (that overheated the phone
     during curfew-net tuning). Covers WiFi, USB and BT tethering;
  3. best-effort `cmd wifi stop-softap` (Android 11+) so the hotspot visibly
     flips off.
Reverts offload + tears down FORWARD on transition away from home / on SIGTERM.

Wiring: config.sh flags, focus_ctl.sh (tether-status/start/stop/log/test-on/off),
magisk_service.sh boot autostart, deploy.sh push/cp/restart. README section and
a working subprocess regression test (lib/tests/test_tether_enforcer.sh, 17/17).

Verified on-device (BL9000, Android 13): our REJECT jump sits ABOVE Android's
tetherctrl_FORWARD chain, tether_offload_disabled=1 took effect, and
`cmd wifi stop-softap` reports "Soft AP stopped successfully".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6i3cdhKBoUrKxy4rmx6hH
2026-07-13 10:48:59 +02:00

60 lines
2.7 KiB
Bash
Executable File

#!/bin/sh
# ============================================================
# Magisk service.d autostart script
# This file is placed on the device at:
# /data/adb/service.d/99-focus-mode.sh
# Magisk executes everything in service.d on boot with root.
# ============================================================
# Wait for system to be fully booted before starting daemons
sleep 120
SCRIPT_DIR="/data/local/tmp/focus_mode"
# Ensure scripts are executable
chmod +x "$SCRIPT_DIR/focus_daemon.sh"
chmod +x "$SCRIPT_DIR/focus_ctl.sh"
chmod +x "$SCRIPT_DIR/hosts_enforcer.sh"
chmod +x "$SCRIPT_DIR/dns_enforcer.sh"
chmod +x "$SCRIPT_DIR/launcher_enforcer.sh"
chmod +x "$SCRIPT_DIR/curfew_enforcer.sh" 2>/dev/null
chmod +x "$SCRIPT_DIR/tether_enforcer.sh" 2>/dev/null
chmod +x "$SCRIPT_DIR/workout_detector.sh" 2>/dev/null
chmod +x "$SCRIPT_DIR/sqlite3" 2>/dev/null
# Start hosts enforcer FIRST - it must bind-mount the hosts file before
# the user has a chance to exploit it. This runs even outside focus mode
# because hosts hardening should always be active.
setsid sh "$SCRIPT_DIR/hosts_enforcer.sh" </dev/null >/dev/null 2>&1 &
# Start workout detector early so the hosts enforcer's first integrity
# check sees the correct workout_active flag. The detector itself is
# harmless when no workout is in progress (writes "0" and idles).
if [ -x "$SCRIPT_DIR/sqlite3" ] && [ -f "$SCRIPT_DIR/workout_detector.sh" ]; then
setsid sh "$SCRIPT_DIR/workout_detector.sh" </dev/null >/dev/null 2>&1 &
fi
# Start DNS enforcer - forces Private DNS off and blocks DoH/DoT endpoints
# so the hosts file actually gets consulted by apps that would otherwise
# bypass it (e.g. Chrome's built-in secure DNS). Always on.
setsid sh "$SCRIPT_DIR/dns_enforcer.sh" </dev/null >/dev/null 2>&1 &
# Start launcher enforcer - keeps Minimalist Phone installed and pinned as
# the default HOME. Always on (not location-gated).
setsid sh "$SCRIPT_DIR/launcher_enforcer.sh" </dev/null >/dev/null 2>&1 &
# Start night-curfew enforcer - locks grayscale + DND (and optional per-UID
# network allow-list) while the curfew window is open at home. Always on; it
# self-gates on the clock + focus mode and is a no-op during the day.
setsid sh "$SCRIPT_DIR/curfew_enforcer.sh" </dev/null >/dev/null 2>&1 &
# Start hotspot/tethering enforcer - blocks forwarded (tethered) traffic so a
# second phone on our hotspot can't bypass focus mode. Always on; it self-gates
# on focus mode and is a no-op while away from home.
setsid sh "$SCRIPT_DIR/tether_enforcer.sh" </dev/null >/dev/null 2>&1 &
# Start focus daemon in a new session (detached from any controlling terminal)
setsid sh "$SCRIPT_DIR/focus_daemon.sh" </dev/null >/dev/null 2>&1 &
exit 0