#!/bin/sh # RPCD backend for mitmproxy LuCI app . /usr/share/libubox/jshn.sh CONFIG="mitmproxy" LXC_NAME="mitmproxy" LXC_PATH="/srv/lxc" LXC_ROOTFS="$LXC_PATH/$LXC_NAME/rootfs" uci_get() { uci -q get ${CONFIG}.$1; } uci_set() { uci set ${CONFIG}.$1="$2"; } get_status() { local enabled=$(uci_get main.enabled) local web_port=$(uci_get main.web_port) local proxy_port=$(uci_get main.proxy_port) local data_path=$(uci_get main.data_path) local mode=$(uci_get main.mode) local haproxy_router_enabled=$(uci_get haproxy_router.enabled) local haproxy_listen_port=$(uci_get haproxy_router.listen_port) # Check for LXC availability local lxc_available=0 command -v lxc-start >/dev/null 2>&1 && lxc_available=1 # Check if container is running local running=0 if [ "$lxc_available" = "1" ]; then lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING" && running=1 fi # Check if installed (rootfs exists) local installed=0 [ -d "$LXC_ROOTFS" ] && [ -x "$LXC_ROOTFS/usr/bin/mitmproxy" ] && installed=1 # Check nftables status for transparent mode local nft_active=0 if [ "$mode" = "transparent" ] && command -v nft >/dev/null 2>&1; then nft list table inet mitmproxy >/dev/null 2>&1 && nft_active=1 fi # Get authentication token from container data path local token="" local token_file="${data_path:-/srv/mitmproxy}/.mitmproxy_token" [ -f "$token_file" ] && token=$(cat "$token_file" 2>/dev/null | tr -d '\n') cat </dev/null 2>&1 || { uci set mitmproxy.main=mitmproxy uci set mitmproxy.main.enabled='0' uci set mitmproxy.main.mode='regular' } uci -q get mitmproxy.transparent >/dev/null 2>&1 || { uci set mitmproxy.transparent=transparent uci set mitmproxy.transparent.enabled='0' } uci -q get mitmproxy.filtering >/dev/null 2>&1 || { uci set mitmproxy.filtering=filtering uci set mitmproxy.filtering.enabled='0' } # Apply main settings [ -n "$mode" ] && uci_set main.mode "$mode" [ -n "$enabled" ] && uci_set main.enabled "$enabled" [ -n "$proxy_port" ] && uci_set main.proxy_port "$proxy_port" [ -n "$web_port" ] && uci_set main.web_port "$web_port" [ -n "$web_host" ] && uci_set main.web_host "$web_host" [ -n "$data_path" ] && uci_set main.data_path "$data_path" [ -n "$memory_limit" ] && uci_set main.memory_limit "$memory_limit" [ -n "$upstream_proxy" ] && uci_set main.upstream_proxy "$upstream_proxy" [ -n "$reverse_target" ] && uci_set main.reverse_target "$reverse_target" [ -n "$ssl_insecure" ] && uci_set main.ssl_insecure "$ssl_insecure" [ -n "$anticache" ] && uci_set main.anticache "$anticache" [ -n "$anticomp" ] && uci_set main.anticomp "$anticomp" # Apply transparent settings [ -n "$transparent_enabled" ] && uci_set transparent.enabled "$transparent_enabled" [ -n "$transparent_interface" ] && uci_set transparent.interface "$transparent_interface" [ -n "$redirect_http" ] && uci_set transparent.redirect_http "$redirect_http" [ -n "$redirect_https" ] && uci_set transparent.redirect_https "$redirect_https" # Apply filtering settings [ -n "$filtering_enabled" ] && uci_set filtering.enabled "$filtering_enabled" [ -n "$log_requests" ] && uci_set filtering.log_requests "$log_requests" [ -n "$filter_cdn" ] && uci_set filtering.filter_cdn "$filter_cdn" [ -n "$filter_media" ] && uci_set filtering.filter_media "$filter_media" [ -n "$block_ads" ] && uci_set filtering.block_ads "$block_ads" uci commit mitmproxy # Restart service to apply firewall rules if enabled and apply_now is set local is_enabled=$(uci_get main.enabled) local restarted=0 if [ "$is_enabled" = "1" ] && [ "$apply_now" = "1" ]; then /etc/init.d/mitmproxy restart >/dev/null 2>&1 & restarted=1 fi json_add_boolean "success" 1 if [ "$restarted" = "1" ]; then json_add_string "message" "Settings saved and applied" json_add_boolean "restarted" 1 else json_add_string "message" "Settings saved" json_add_boolean "restarted" 0 fi json_dump } set_mode() { read input json_load "$input" local mode apply_now json_get_var mode mode json_get_var apply_now apply_now json_init if [ -z "$mode" ]; then json_add_boolean "success" 0 json_add_string "error" "Mode is required" json_dump return fi # Validate mode case "$mode" in regular|transparent|upstream|reverse) ;; *) json_add_boolean "success" 0 json_add_string "error" "Invalid mode: $mode" json_dump return ;; esac # Ensure section exists uci -q get mitmproxy.main >/dev/null 2>&1 || { uci set mitmproxy.main=mitmproxy uci set mitmproxy.main.enabled='0' } uci_set main.mode "$mode" uci commit mitmproxy # Restart to apply firewall rules if needed local is_enabled=$(uci_get main.enabled) local restarted=0 if [ "$is_enabled" = "1" ] && [ "$apply_now" = "1" ]; then /etc/init.d/mitmproxy restart >/dev/null 2>&1 & restarted=1 fi json_add_boolean "success" 1 json_add_string "mode" "$mode" if [ "$restarted" = "1" ]; then json_add_string "message" "Mode set to $mode and applied" json_add_boolean "restarted" 1 else json_add_string "message" "Mode set to $mode" json_add_boolean "restarted" 0 fi json_dump } setup_firewall() { json_init if ! command -v mitmproxyctl >/dev/null 2>&1; then json_add_boolean "success" 0 json_add_string "error" "mitmproxyctl not found" json_dump return fi mitmproxyctl firewall-setup >/tmp/mitmproxy-fw.log 2>&1 local result=$? if [ $result -eq 0 ]; then json_add_boolean "success" 1 json_add_string "message" "Firewall rules applied" else json_add_boolean "success" 0 json_add_string "error" "Failed to setup firewall rules" local log=$(cat /tmp/mitmproxy-fw.log 2>/dev/null) [ -n "$log" ] && json_add_string "details" "$log" fi json_dump } clear_firewall() { json_init if ! command -v mitmproxyctl >/dev/null 2>&1; then json_add_boolean "success" 0 json_add_string "error" "mitmproxyctl not found" json_dump return fi mitmproxyctl firewall-clear >/tmp/mitmproxy-fw.log 2>&1 local result=$? if [ $result -eq 0 ]; then json_add_boolean "success" 1 json_add_string "message" "Firewall rules cleared" else json_add_boolean "success" 0 json_add_string "error" "Failed to clear firewall rules" fi json_dump } do_install() { command -v mitmproxyctl >/dev/null 2>&1 && { mitmproxyctl install >/tmp/mitmproxy-install.log 2>&1 & echo '{"success":true,"message":"Installing"}'; } || echo '{"success":false,"error":"mitmproxyctl not found"}' } do_start() { [ -x /etc/init.d/mitmproxy ] && /etc/init.d/mitmproxy start >/dev/null 2>&1; echo '{"success":true}'; } do_stop() { [ -x /etc/init.d/mitmproxy ] && /etc/init.d/mitmproxy stop >/dev/null 2>&1; echo '{"success":true}'; } do_restart() { [ -x /etc/init.d/mitmproxy ] && /etc/init.d/mitmproxy restart >/dev/null 2>&1; echo '{"success":true}'; } get_alerts() { # Read alerts from host-visible JSONL log file # The analytics addon writes to /data/threats.log inside container # which is bind-mounted to /srv/mitmproxy/threats.log on host local log_file="/srv/mitmproxy/threats.log" local max_alerts=50 local alerts_json="[]" # Read last N lines from the host-accessible log file if [ -f "$log_file" ]; then local lines=$(tail -n "$max_alerts" "$log_file" 2>/dev/null) if [ -n "$lines" ]; then # Convert JSONL to JSON array: join lines with commas, wrap in brackets alerts_json=$(echo "$lines" | awk ' BEGIN { printf "[" } NR > 1 { printf "," } { printf "%s", $0 } END { printf "]" } ') fi fi # Validate JSON - if invalid, return empty array if ! echo "$alerts_json" | jsonfilter -e '@' >/dev/null 2>&1; then alerts_json="[]" fi cat </dev/null 2>&1; then container_stats=$(lxc-attach -n "$LXC_NAME" -- cat /tmp/secubox-mitm-stats.json 2>/dev/null) fi # Fall back to host path if [ -z "$container_stats" ]; then [ -f "$stats_file" ] && container_stats=$(cat "$stats_file" 2>/dev/null) fi # Default stats [ -z "$container_stats" ] && container_stats='{"total":{"requests":0,"threats":0,"bots":0}}' cat < "$log_file" 2>/dev/null # Also clear the legacy alerts file echo "[]" > /tmp/secubox-mitm-alerts.json 2>/dev/null echo '{"success":true,"message":"Alerts cleared"}' } haproxy_enable() { json_init if ! command -v mitmproxyctl >/dev/null 2>&1; then json_add_boolean "success" 0 json_add_string "error" "mitmproxyctl not found" json_dump return fi mitmproxyctl haproxy-enable >/tmp/haproxy-enable.log 2>&1 local result=$? if [ $result -eq 0 ]; then json_add_boolean "success" 1 json_add_string "message" "HAProxy backend inspection enabled" else json_add_boolean "success" 0 json_add_string "error" "Failed to enable HAProxy inspection" local log=$(cat /tmp/haproxy-enable.log 2>/dev/null) [ -n "$log" ] && json_add_string "details" "$log" fi json_dump } haproxy_disable() { json_init if ! command -v mitmproxyctl >/dev/null 2>&1; then json_add_boolean "success" 0 json_add_string "error" "mitmproxyctl not found" json_dump return fi mitmproxyctl haproxy-disable >/tmp/haproxy-disable.log 2>&1 local result=$? if [ $result -eq 0 ]; then json_add_boolean "success" 1 json_add_string "message" "HAProxy backend inspection disabled" else json_add_boolean "success" 0 json_add_string "error" "Failed to disable HAProxy inspection" fi json_dump } sync_routes() { json_init if ! command -v mitmproxyctl >/dev/null 2>&1; then json_add_boolean "success" 0 json_add_string "error" "mitmproxyctl not found" json_dump return fi mitmproxyctl sync-routes >/tmp/sync-routes.log 2>&1 local result=$? if [ $result -eq 0 ]; then json_add_boolean "success" 1 json_add_string "message" "Routes synced from HAProxy" else json_add_boolean "success" 0 json_add_string "error" "Failed to sync routes" fi json_dump } list_methods() { cat <<'EOFM' {"status":{},"settings":{},"save_settings":{"mode":"str","enabled":"bool","proxy_port":"int","web_port":"int","apply_now":"bool"},"set_mode":{"mode":"str","apply_now":"bool"},"setup_firewall":{},"clear_firewall":{},"install":{},"start":{},"stop":{},"restart":{},"alerts":{},"threat_stats":{},"clear_alerts":{},"haproxy_enable":{},"haproxy_disable":{},"sync_routes":{}} EOFM } case "$1" in list) list_methods ;; call) case "$2" in status) get_status ;; settings) get_settings ;; save_settings) save_settings ;; set_mode) set_mode ;; setup_firewall) setup_firewall ;; clear_firewall) clear_firewall ;; install) do_install ;; start) do_start ;; stop) do_stop ;; restart) do_restart ;; alerts) get_alerts ;; threat_stats) get_threat_stats ;; clear_alerts) clear_alerts ;; haproxy_enable) haproxy_enable ;; haproxy_disable) haproxy_disable ;; sync_routes) sync_routes ;; *) echo '{"error":"Unknown method"}' ;; esac ;; *) echo '{"error":"Unknown command"}' ;; esac