#!/bin/sh # # RPCD backend for mitmproxy LuCI interface # Copyright (C) 2025 CyberMind.fr (SecuBox) # . /lib/functions.sh DATA_DIR=$(uci -q get mitmproxy.main.data_path || echo "/srv/mitmproxy") LXC_NAME="mitmproxy" CONF_DIR="$DATA_DIR" LOG_FILE="$DATA_DIR/requests.log" FLOW_FILE="$DATA_DIR/flows.bin" # Get service status get_status() { local running=0 local pid="" local mode="unknown" local web_url="" local lxc_state="" local nft_active="false" # Check LXC container status if command -v lxc-info >/dev/null 2>&1; then lxc_state=$(lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -oE 'RUNNING|STOPPED' || echo "UNKNOWN") if [ "$lxc_state" = "RUNNING" ]; then running=1 mode="mitmweb" pid=$(lxc-info -n "$LXC_NAME" -p 2>/dev/null | grep -oE '[0-9]+' || echo "0") fi fi # Fallback: check for direct process if [ "$running" = "0" ]; then if pgrep mitmweb >/dev/null 2>&1; then running=1 pid=$(pgrep mitmweb | head -1) mode="mitmweb" elif pgrep mitmdump >/dev/null 2>&1; then running=1 pid=$(pgrep mitmdump | head -1) mode="mitmdump" fi fi # Check nftables rules if command -v nft >/dev/null 2>&1; then nft list table inet mitmproxy >/dev/null 2>&1 && nft_active="true" fi local enabled=$(uci -q get mitmproxy.main.enabled || echo "0") local proxy_port=$(uci -q get mitmproxy.main.proxy_port || echo "8080") local web_port=$(uci -q get mitmproxy.main.web_port || echo "8081") local proxy_mode=$(uci -q get mitmproxy.main.mode || echo "regular") local filtering_enabled=$(uci -q get mitmproxy.filtering.enabled || echo "0") local router_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1") [ "$running" = "1" ] && [ "$mode" = "mitmweb" ] && web_url="http://${router_ip}:${web_port}" cat </dev/null | tr ' ' '\n' | while read ip; do [ -n "$ip" ] && printf '"%s",' "$ip" done | sed 's/,$//') # Get bypass_domain list local bypass_domains=$(uci -q get mitmproxy.whitelist.bypass_domain 2>/dev/null | tr ' ' '\n' | while read domain; do [ -n "$domain" ] && printf '"%s",' "$domain" done | sed 's/,$//') cat </dev/null || echo "0") # Use jsonfilter for parsing (OpenWrt native) if command -v jsonfilter >/dev/null 2>&1; then unique_hosts=$(cat "$LOG_FILE" 2>/dev/null | while read line; do echo "$line" | jsonfilter -e '@.request.host' 2>/dev/null done | sort -u | wc -l) cdn_requests=$(grep -c '"category":"cdn"' "$LOG_FILE" 2>/dev/null || echo "0") media_requests=$(grep -c '"category":"media"' "$LOG_FILE" 2>/dev/null || echo "0") blocked_ads=$(grep -c '"category":"blocked_ad"' "$LOG_FILE" 2>/dev/null || echo "0") fi fi if [ -f "$FLOW_FILE" ]; then flow_size=$(ls -l "$FLOW_FILE" 2>/dev/null | awk '{print $5}' || echo "0") fi cat </dev/null | tail -"$limit" | \ awk 'BEGIN{first=1}{if(!first)printf ",";first=0;print}' 2>/dev/null || echo "" echo ']}' else echo '{"requests":[' tail -"$limit" "$LOG_FILE" 2>/dev/null | \ awk 'BEGIN{first=1}{if(!first)printf ",";first=0;print}' 2>/dev/null || echo "" echo ']}' fi } # Get top hosts get_top_hosts() { local limit="${1:-20}" if [ ! -f "$LOG_FILE" ]; then echo '{"hosts":[]}' return fi echo '{"hosts":[' # Parse JSON using grep/sed for compatibility grep -o '"host":"[^"]*"' "$LOG_FILE" 2>/dev/null | \ sed 's/"host":"//;s/"$//' | \ sort | uniq -c | sort -rn | head -"$limit" | \ awk 'BEGIN{first=1} { if(!first) printf ","; first=0; gsub(/"/, "\\\"", $2); printf "{\"host\":\"%s\",\"count\":%d}", $2, $1 }' echo ']}' } # Service control service_start() { /etc/init.d/mitmproxy start >/dev/null 2>&1 sleep 2 get_status } service_stop() { /etc/init.d/mitmproxy stop >/dev/null 2>&1 sleep 1 get_status } service_restart() { /etc/init.d/mitmproxy restart >/dev/null 2>&1 sleep 2 get_status } # Setup firewall rules firewall_setup() { /usr/sbin/mitmproxyctl firewall-setup 2>&1 local result=$? if [ $result -eq 0 ]; then echo '{"success":true,"message":"Firewall rules applied"}' else echo '{"success":false,"message":"Failed to apply firewall rules"}' fi } # Clear firewall rules firewall_clear() { /usr/sbin/mitmproxyctl firewall-clear 2>&1 local result=$? if [ $result -eq 0 ]; then echo '{"success":true,"message":"Firewall rules cleared"}' else echo '{"success":false,"message":"Failed to clear firewall rules"}' fi } # Set configuration set_config() { local key="$1" local value="$2" local section="main" case "$key" in save_flows|capture_*) section="capture" ;; redirect_*|interface|http_port|https_port) section="transparent" ;; bypass_ip|bypass_domain) section="whitelist" ;; filter_*|log_requests|block_ads|addon_script) section="filtering" ;; esac # Handle boolean conversion case "$value" in true) value="1" ;; false) value="0" ;; esac uci set "mitmproxy.$section.$key=$value" uci commit mitmproxy echo '{"success":true}' } # Add to list (for bypass_ip, bypass_domain) add_to_list() { local key="$1" local value="$2" local section="whitelist" uci add_list "mitmproxy.$section.$key=$value" uci commit mitmproxy echo '{"success":true}' } # Remove from list remove_from_list() { local key="$1" local value="$2" local section="whitelist" uci del_list "mitmproxy.$section.$key=$value" uci commit mitmproxy echo '{"success":true}' } # Clear captured data clear_data() { rm -f "$DATA_DIR"/*.log "$DATA_DIR"/*.bin 2>/dev/null echo '{"success":true,"message":"Captured data cleared"}' } # Get CA certificate info get_ca_info() { local cert="$CONF_DIR/mitmproxy-ca-cert.pem" local router_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1") local web_port=$(uci -q get mitmproxy.main.web_port || echo "8081") if [ -f "$cert" ]; then local subject=$(openssl x509 -in "$cert" -noout -subject 2>/dev/null | sed 's/subject=//') local expires=$(openssl x509 -in "$cert" -noout -enddate 2>/dev/null | sed 's/notAfter=//') cat </dev/null | tr -d '\n\r') fi # Fallback: read token directly from container if host file is missing/empty if [ -z "$token" ] && command -v lxc-attach >/dev/null 2>&1; then if lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"; then token=$(lxc-attach -n "$LXC_NAME" -- cat /data/.mitmproxy_token 2>/dev/null | tr -d '\n\r') fi fi # Second fallback: parse token from mitmweb log inside container if [ -z "$token" ] && command -v lxc-attach >/dev/null 2>&1; then if lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"; then token=$(lxc-attach -n "$LXC_NAME" -- grep -o 'token=[a-zA-Z0-9_-]*' /tmp/mitmweb.log 2>/dev/null | head -1 | cut -d= -f2) fi fi # Construct URL - only add token parameter if token exists local web_url="http://$router_ip:$web_port" local web_url_with_token="$web_url" if [ -n "$token" ]; then web_url_with_token="$web_url/?token=$token" fi cat </dev/null || echo "50") category=$(echo "$input" | jsonfilter -e '@.category' 2>/dev/null || echo "all") get_requests "$limit" "$category" ;; get_top_hosts) read -r input limit=$(echo "$input" | jsonfilter -e '@.limit' 2>/dev/null || echo "20") get_top_hosts "$limit" ;; get_ca_info) get_ca_info ;; get_web_token) get_web_token ;; service_start) service_start ;; service_stop) service_stop ;; service_restart) service_restart ;; firewall_setup) firewall_setup ;; firewall_clear) firewall_clear ;; set_config) read -r input key=$(echo "$input" | jsonfilter -e '@.key' 2>/dev/null) value=$(echo "$input" | jsonfilter -e '@.value' 2>/dev/null) set_config "$key" "$value" ;; add_to_list) read -r input key=$(echo "$input" | jsonfilter -e '@.key' 2>/dev/null) value=$(echo "$input" | jsonfilter -e '@.value' 2>/dev/null) add_to_list "$key" "$value" ;; remove_from_list) read -r input key=$(echo "$input" | jsonfilter -e '@.key' 2>/dev/null) value=$(echo "$input" | jsonfilter -e '@.value' 2>/dev/null) remove_from_list "$key" "$value" ;; clear_data) clear_data ;; *) echo '{"error":"Unknown method"}' ;; esac ;; *) echo '{"error":"Unknown command"}' ;; esac