Phase 4: authorised HTTPS interception (Mode B)

Toggleable transparent interception via mitmdump in a venv. Own RSA CA generated
in-app, downloadable (public cert only, key never leaves the box), with per-OS
install guide and fingerprint. nftables redirect accepts only dnat'd connections
(never an open proxy). HTTP Explorer with headers and opt-in body viewers (JSON/
text/hex/image, sandboxed). Honest status: pinned/untrusting = reported errors,
excluded hosts pass through, bodies off by default. Helper op + systemd unit +
installer venv build + boot restore.
This commit is contained in:
Andy Dixon
2026-10-10 08:05:42 +01:00
parent 4320428f41
commit 5dbf85f84e
25 changed files with 1460 additions and 13 deletions
+2 -1
View File
@@ -11,7 +11,7 @@ run() { local f="$D/$1"; shift; { echo "\$ $*"; "$@"; } >"$f" 2>&1 || true; }
redact() { sed -E 's/("passphrase"[[:space:]]*:[[:space:]]*")[^"]*/\1REDACTED/g; s/^(psk=).*/\1REDACTED/; s/(setup_token=).*/\1REDACTED/'; }
run versions.txt sh -c 'cat /opt/pilens/VERSION; uname -a; cat /etc/os-release; tr -d "\0" </proc/device-tree/model; echo; tshark --version | head -1; nmcli --version; dnsmasq --version | head -1; nft --version'
run services.txt systemctl status --no-pager pilens pilens-helper pilens-firewall pilens-dnsmasq NetworkManager
run services.txt systemctl status --no-pager pilens pilens-helper pilens-firewall pilens-dnsmasq pilens-proxy NetworkManager
run journal.txt journalctl --no-pager -n 3000 -u pilens -u pilens-helper -u pilens-firewall -u pilens-dnsmasq
run journal-nm.txt journalctl --no-pager -n 800 -u NetworkManager
run nft-pilens.txt nft list table inet pilens
@@ -20,6 +20,7 @@ run ip.txt sh -c 'ip -br link; ip addr; ip route; ip -6 route; sysctl net.ipv4.i
run nm.txt sh -c 'nmcli general; nmcli device; nmcli connection show'
run nm-pilens-ap.txt nmcli connection show pilens-ap
run wifi.txt sh -c 'iw dev; iw reg get; iw list'
run interception.txt sh -c 'ls -la /var/lib/pilens/proxy 2>/dev/null; echo; [ -f /var/lib/pilens/proxy/ca/mitmproxy-ca-cert.pem ] && openssl x509 -in /var/lib/pilens/proxy/ca/mitmproxy-ca-cert.pem -noout -subject -fingerprint -sha256 -dates; /opt/pilens/proxy-venv/bin/mitmdump --version 2>/dev/null | head -1'
run capture.txt sh -c 'getcap /usr/bin/dumpcap; id pilens; ls -la /var/lib/pilens /var/lib/pilens-helper'
run resources.txt sh -c 'df -h; free -m; uptime; vcgencmd get_throttled; vcgencmd measure_temp; timedatectl'
cp /var/lib/pilens-helper/dnsmasq.conf "$D/dnsmasq.conf" 2>/dev/null
+19
View File
@@ -169,14 +169,33 @@ usermod -aG wireshark pilens
systemctl stop pilens 2>/dev/null || true
mkdir -p "$PREFIX"
install -m 0755 "$SRC/bin/pilens" "$SRC/bin/pilens-helper" -D -t "$PREFIX/bin"
install -m 0755 "$SRC/proxy-run.sh" "$PREFIX/proxy-run.sh"
install -m 0644 "$SRC/mitm_addon.py" "$PREFIX/mitm_addon.py"
for f in install.sh uninstall.sh repair.sh diagnose.sh setup.example.yaml VERSION README.md LICENSE; do install -m 0644 "$SRC/$f" "$PREFIX/$f"; done
chmod 0755 "$PREFIX"/*.sh
rm -rf "$PREFIX/docs"; cp -r "$SRC/docs" "$PREFIX/docs"
install -d -o pilens -g pilens -m 0750 "$DATA"
install -d -o pilens -g pilens -m 0750 "$DATA/proxy"
install -d -o root -g root -m 0700 /var/lib/pilens-helper
install -m 0644 "$SRC"/systemd/*.service /etc/systemd/system/
systemctl daemon-reload
# ---------------------------------------------------------------- 16. optional TLS proxy deps
say "Preparing optional HTTPS-interception proxy (mitmproxy)"
VENV="$PREFIX/proxy-venv"
if [ -x "$VENV/bin/mitmdump" ]; then
echo " mitmproxy venv already present"
elif apt-get install -y -qq --no-install-recommends python3-venv >>"$LOG" 2>&1 && python3 -m venv "$VENV" >>"$LOG" 2>&1; then
if "$VENV/bin/pip" install --quiet --only-binary=:all: --upgrade pip >>"$LOG" 2>&1 && "$VENV/bin/pip" install --quiet --only-binary=:all: mitmproxy >>"$LOG" 2>&1; then
chown -R pilens:pilens "$VENV"
echo " mitmproxy installed ($("$VENV/bin/mitmdump" --version 2>/dev/null | head -1))"
else
warn "mitmproxy install failed (needs internet + arm64 wheels). HTTPS interception will be unavailable until you run: sudo $PREFIX/repair.sh"
fi
else
warn "could not create the proxy virtualenv; HTTPS interception will be unavailable (optional feature)"
fi
# ---------------------------------------------------------------- 15. initialise data
say "Initialising database and management certificate"
INIT=$(runuser -u pilens -- "$PREFIX/bin/pilens" init -data "$DATA" -mgmt-iface "$MGMT_IF" -mgmt-subnet "$MGMT_NET")
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# Launches mitmdump for PiLens interception from the core-written env file.
# Runs as the unprivileged 'pilens' user under the pilens-proxy.service unit.
set -eu
ENV=/var/lib/pilens/proxy/proxy.env
[ -f "$ENV" ] || { echo "no proxy.env; interception not configured" >&2; exit 1; }
. "$ENV"
export PILENS_FLOWS PILENS_BODIES PILENS_CAPTURE_BODIES PILENS_MAX_BODY_KB
args=( --mode transparent --listen-host 0.0.0.0 --listen-port "$PILENS_PROXY_PORT"
--set "confdir=$PILENS_CONFDIR" --set block_global=false --set connection_strategy=lazy
--set stream_large_bodies=1m -s "$PILENS_ADDON" -q )
if [ -n "${PILENS_IGNORE:-}" ]; then args+=( --ignore-hosts "$PILENS_IGNORE" ); fi
exec "$PILENS_VENV/bin/mitmdump" "${args[@]}"
+12
View File
@@ -18,6 +18,18 @@ if ! getcap /usr/bin/dumpcap 2>/dev/null | grep -q cap_net_raw; then
fi
getcap /usr/bin/dumpcap | grep -q cap_net_raw && ok "dumpcap capture capabilities" || bad "dumpcap lacks capabilities"
# Optional: rebuild the mitmproxy venv if it is missing (HTTPS interception).
VENV=/opt/pilens/proxy-venv
if [ ! -x "$VENV/bin/mitmdump" ]; then
if python3 -m venv "$VENV" >/dev/null 2>&1 && "$VENV/bin/pip" install --quiet --only-binary=:all: mitmproxy >/dev/null 2>&1; then
chown -R pilens:pilens "$VENV"; ok "mitmproxy venv rebuilt"
else
bad "mitmproxy venv missing and reinstall failed (interception unavailable; needs internet)"
fi
else
ok "mitmproxy venv present"
fi
systemctl daemon-reload
systemctl enable pilens-firewall pilens-helper pilens-dnsmasq pilens >/dev/null 2>&1
systemctl reset-failed 'pilens*' 2>/dev/null
+1 -1
View File
@@ -15,7 +15,7 @@ if [ $PURGE = 1 ]; then
[ "$x" = DELETE ] || { echo "not confirmed; keeping data"; PURGE=0; }
fi
systemctl disable --now pilens pilens-dnsmasq pilens-helper pilens-firewall 2>/dev/null || true
systemctl disable --now pilens pilens-proxy pilens-dnsmasq pilens-helper pilens-firewall 2>/dev/null || true
nmcli connection delete pilens-ap 2>/dev/null && echo "removed access-point profile (other Wi-Fi profiles were never modified and will reconnect)" || true
rm -f /etc/NetworkManager/system-connections/pilens-ap.nmconnection
nft delete table inet pilens 2>/dev/null && echo "removed firewall table inet pilens" || true