#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
# Copyright (c) 2026 CyberMind — Gérald Kerma <devel@cybermind.fr>
#
# Phase 6.F (#496) — launcher wrapper for secubox-toolbox-mitm-wg.service.
# Reads the mitm bypass list from /etc/secubox/toolbox/mitm-bypass.conf and
# turns it into a single mitmproxy --set ignore_hosts=<regex> alternation.
#
# Why a wrapper instead of inline ExecStart: systemd doesn't expand $(cat)
# or do regex composition; we need a real shell. Also, when the admin UI
# adds/removes entries, restarting this service picks them up automatically
# without editing the unit file.

set -euo pipefail

MITM_BIN=/opt/mitmproxy-toolbox/bin/mitmdump
BYPASS_FILE=/var/lib/secubox/toolbox/mitm-bypass.conf
DYNAMIC_FILE=/var/lib/secubox/toolbox/mitm-bypass-dynamic.conf  # noqa: SC2034 (used by addon hint)
SEED_FILE=/usr/lib/secubox/toolbox/conf/mitm-bypass-seed.conf
ADDON_DIR=/usr/lib/secubox/toolbox/mitmproxy_addons

# Phase 11.A (#505) — make the secubox_toolbox package importable from
# addons running inside /opt/mitmproxy-toolbox/bin/python3 (a venv that
# has its own site-packages and never sees /usr/lib/secubox/toolbox).
# Without this PYTHONPATH every addon's `from secubox_toolbox import …`
# silently degrades — inject_banner loses host classification + GeoIP,
# social_graph loses its SQLite store reference, etc.
export PYTHONPATH="/usr/lib/secubox/toolbox${PYTHONPATH:+:$PYTHONPATH}"

# ── Compose ignore_hosts regex : merge static + dynamic bypass lists ──
# Phase 6.N (#496) : the dynamic file is auto-populated by the cert_pin_detect
# addon when it observes repeated TLS handshake failures (cert pinning).
# We merge both lists here so a single regex covers known + learned pinned
# domains. Dedup happens at line level (sort -u).
IGNORE_REGEX=""
PATTERNS=""
COUNT=0
for src in "$SEED_FILE" "$BYPASS_FILE" "$DYNAMIC_FILE"; do
    if [ -r "$src" ]; then
        ADD=$(grep -v '^[[:space:]]*#' "$src" | sed 's/[[:space:]]*#.*$//' | grep -v '^[[:space:]]*$' || true)
        if [ -n "$ADD" ]; then
            PATTERNS="${PATTERNS}${PATTERNS:+\n}${ADD}"
        fi
    fi
done
if [ -n "$PATTERNS" ]; then
    # Dedup + join with |
    JOINED=$(printf '%b' "$PATTERNS" | sort -u | tr '\n' '|' | sed 's/|$//')
    COUNT=$(printf '%b' "$PATTERNS" | sort -u | grep -cv '^[[:space:]]*$' || echo 0)
    IGNORE_REGEX="($JOINED)"
fi

# ── Build mitm args ──
# Phase 7 (#498) — listen-host is overridable via env. Host (default) binds
# 10.99.1.1 (the wg-toolbox interface IP) ; LXC variant sets 0.0.0.0 so it
# accepts the DNAT'd traffic on the 10.100.0.62 br-lxc interface.
# Phase 9 (#501) — listen-port is overridable too. Each fanout worker
# instance (secubox-toolbox-mitm-wg-worker@N) sets MITM_WG_LISTEN_PORT
# to 808N. The legacy single-process service keeps the 8081 default.
MITM_WG_LISTEN_HOST="${MITM_WG_LISTEN_HOST:-10.99.1.1}"
MITM_WG_LISTEN_PORT="${MITM_WG_LISTEN_PORT:-8081}"
ARGS=(
    --mode transparent
    --listen-host "$MITM_WG_LISTEN_HOST"
    --listen-port "$MITM_WG_LISTEN_PORT"
    --set confdir=/etc/secubox/toolbox/ca-wg
    --set ssl_insecure=false
    --set web_open_browser=false
    # Phase 8.1 (#500 perf) — RE-ENABLE HTTP/2.
    # Phase 6.P had disabled it to bound memory growth ; observation
    # 2026-06-08 shows the actual problem is single-thread CPU saturation
    # (mitm-wg hits 65 % CPU on one core even at near-zero throughput
    # with 35 enrolled peers + 3 concurrent active).  HTTP/2 multiplex
    # halves the number of TLS handshakes per page load + reuses
    # connections, which translates directly into less work per
    # browsing session.  We compensate the memory drift by halving
    # RuntimeMaxSec from 6 h to 3 h (drop-in 10-runtime-max.conf).
    --set http2=true
    # Phase 8.1 — connection_strategy=eager makes mitm open the upstream
    # connection at requestheaders rather than waiting for the body,
    # which lets the asyncio loop overlap upstream RTT with downstream
    # parsing.  Marginal win on slow-RTT publishers.
    --set connection_strategy=eager
    # Phase 8.1 — keep upstream connections alive for reuse across
    # flows from the same source.  Phase 6.J's Connection:close fix
    # forced close to prevent a memory leak that was actually patched
    # upstream in mitmproxy 10.4 ; with mitmproxy 11+ we can safely
    # re-enable keep-alive.  Halves TCP handshakes towards busy CDNs.
    --set keep_host_header=true
    # #686 — large-binary streaming is now content-aware via the stream_binaries
    # addon (streams APK/XPI/video/large NON-HTML verbatim) instead of the blunt
    # `stream_large_bodies=1m`, which also streamed large HTML and killed banner
    # injection on heavy sites (leparisien.fr).
)

if [ -n "$IGNORE_REGEX" ]; then
    ARGS+=(--set "ignore_hosts=$IGNORE_REGEX")
    echo "[mitm-wg-launch] ignore_hosts regex applied (${#IGNORE_REGEX} chars, ${COUNT} patterns, static+dynamic)"
fi

# Addons :
#   - tls_splice (#649) runs at tls_clienthello (BEFORE any requestheaders
#     addon) — it splices pure-asset flows so the rest of the chain never even
#     sees them. Listed first for clarity; its hook phase makes ordering vs the
#     requestheaders addons irrelevant, so inject_xff stays first-at-requestheaders.
#   - inject_xff (Phase 7 #498) MUST be FIRST among requestheaders addons — sets
#     X-Forwarded-For at requestheaders so other addons and the upstream see the real peer IP
#   - utiq_defense (Phase 8 #500) runs at requestheaders too ; placed
#     EARLY so a R1 block short-circuits the flow before downstream
#     addons spend cycles on it
#   - social_graph (Phase 11.A #505) sees the same cookie state as
#     local_store but records cross-site identifiers separately ; it
#     must run BEFORE inject_banner so the banner cookies our addon
#     emits don't pollute the graph
#   - cert_pin_detect auto-learns pinned hosts (Phase 6.N)
# protective_mode (#560) runs right after utiq_defense — early, so spoof-level
# header/cookie stripping happens before the logging addons record the flow.
# Inert unless SECUBOX_PROTECTIVE_MODE=alert|spoof (default off).
# ad_ghost (#566) runs right after protective_mode: for R3+/R4 it 204s known
# ad/tracker hosts (bandwidth save) at request time and injects ad-hiding CSS
# on HTML responses. Gated by the modular filter config (toolbox WebUI).
for addon in stream_binaries tls_splice inject_xff utiq_defense protective_mode privacy_guard ad_ghost media_cache local_store social_graph inject_banner dpi cookies avatar ja4 soc_relay cert_pin_detect media_stats; do
    ARGS+=(-s "$ADDON_DIR/${addon}.py")
done

exec "$MITM_BIN" "${ARGS[@]}"
