308 lines
7.4 KiB
Bash
Executable File
308 lines
7.4 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# RPCD backend for mitmproxy LuCI interface
|
|
# Copyright (C) 2025 CyberMind.fr (SecuBox)
|
|
#
|
|
|
|
. /lib/functions.sh
|
|
|
|
CONF_DIR=/etc/mitmproxy
|
|
DATA_DIR=/tmp/mitmproxy
|
|
LOG_FILE=/tmp/mitmproxy/requests.log
|
|
FLOW_FILE=/tmp/mitmproxy/flows.bin
|
|
|
|
# JSON helpers
|
|
json_init() { echo "{"; }
|
|
json_close() { echo "}"; }
|
|
json_add_string() { printf '"%s":"%s"' "$1" "$2"; }
|
|
json_add_int() { printf '"%s":%d' "$1" "${2:-0}"; }
|
|
json_add_bool() { [ "$2" = "1" ] && printf '"%s":true' "$1" || printf '"%s":false' "$1"; }
|
|
|
|
# Get service status
|
|
get_status() {
|
|
local running=0
|
|
local pid=""
|
|
local mode="unknown"
|
|
local web_url=""
|
|
|
|
if pgrep -x mitmweb >/dev/null 2>&1; then
|
|
running=1
|
|
pid=$(pgrep -x mitmweb | head -1)
|
|
mode="mitmweb"
|
|
elif pgrep -x mitmdump >/dev/null 2>&1; then
|
|
running=1
|
|
pid=$(pgrep -x mitmdump | head -1)
|
|
mode="mitmdump"
|
|
elif pgrep -f "python.*mitmproxy" >/dev/null 2>&1; then
|
|
running=1
|
|
pid=$(pgrep -f "python.*mitmproxy" | head -1)
|
|
mode="mitmproxy"
|
|
fi
|
|
|
|
local enabled=$(uci -q get mitmproxy.main.enabled || echo "0")
|
|
local listen_port=$(uci -q get mitmproxy.main.listen_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 "transparent")
|
|
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 <<EOF
|
|
{
|
|
"running": $([ "$running" = "1" ] && echo "true" || echo "false"),
|
|
"enabled": $([ "$enabled" = "1" ] && echo "true" || echo "false"),
|
|
"pid": ${pid:-0},
|
|
"mode": "$mode",
|
|
"proxy_mode": "$proxy_mode",
|
|
"listen_port": $listen_port,
|
|
"web_port": $web_port,
|
|
"web_url": "$web_url",
|
|
"ca_installed": $([ -f "$CONF_DIR/mitmproxy-ca-cert.pem" ] && echo "true" || echo "false")
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Get configuration
|
|
get_config() {
|
|
local enabled=$(uci -q get mitmproxy.main.enabled || echo "0")
|
|
local mode=$(uci -q get mitmproxy.main.mode || echo "transparent")
|
|
local listen_host=$(uci -q get mitmproxy.main.listen_host || echo "0.0.0.0")
|
|
local listen_port=$(uci -q get mitmproxy.main.listen_port || echo "8080")
|
|
local web_host=$(uci -q get mitmproxy.main.web_host || echo "0.0.0.0")
|
|
local web_port=$(uci -q get mitmproxy.main.web_port || echo "8081")
|
|
local ssl_insecure=$(uci -q get mitmproxy.main.ssl_insecure || echo "0")
|
|
local flow_detail=$(uci -q get mitmproxy.main.flow_detail || echo "2")
|
|
|
|
local save_flows=$(uci -q get mitmproxy.capture.save_flows || echo "1")
|
|
local capture_urls=$(uci -q get mitmproxy.capture.capture_urls || echo "1")
|
|
local capture_cookies=$(uci -q get mitmproxy.capture.capture_cookies || echo "1")
|
|
local capture_headers=$(uci -q get mitmproxy.capture.capture_headers || echo "1")
|
|
local capture_body=$(uci -q get mitmproxy.capture.capture_body || echo "0")
|
|
|
|
cat <<EOF
|
|
{
|
|
"enabled": $([ "$enabled" = "1" ] && echo "true" || echo "false"),
|
|
"mode": "$mode",
|
|
"listen_host": "$listen_host",
|
|
"listen_port": $listen_port,
|
|
"web_host": "$web_host",
|
|
"web_port": $web_port,
|
|
"ssl_insecure": $([ "$ssl_insecure" = "1" ] && echo "true" || echo "false"),
|
|
"flow_detail": $flow_detail,
|
|
"save_flows": $([ "$save_flows" = "1" ] && echo "true" || echo "false"),
|
|
"capture_urls": $([ "$capture_urls" = "1" ] && echo "true" || echo "false"),
|
|
"capture_cookies": $([ "$capture_cookies" = "1" ] && echo "true" || echo "false"),
|
|
"capture_headers": $([ "$capture_headers" = "1" ] && echo "true" || echo "false"),
|
|
"capture_body": $([ "$capture_body" = "1" ] && echo "true" || echo "false")
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Get statistics
|
|
get_stats() {
|
|
local total_requests=0
|
|
local unique_hosts=0
|
|
local flow_size="0"
|
|
|
|
if [ -f "$LOG_FILE" ]; then
|
|
total_requests=$(wc -l < "$LOG_FILE" 2>/dev/null || echo "0")
|
|
if command -v jq >/dev/null 2>&1; then
|
|
unique_hosts=$(jq -r '.request.host // .host // empty' "$LOG_FILE" 2>/dev/null | sort -u | wc -l)
|
|
fi
|
|
fi
|
|
|
|
if [ -f "$FLOW_FILE" ]; then
|
|
flow_size=$(ls -l "$FLOW_FILE" 2>/dev/null | awk '{print $5}' || echo "0")
|
|
fi
|
|
|
|
cat <<EOF
|
|
{
|
|
"total_requests": $total_requests,
|
|
"unique_hosts": $unique_hosts,
|
|
"flow_file_size": $flow_size
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Get recent requests
|
|
get_requests() {
|
|
local limit="${1:-50}"
|
|
|
|
if [ ! -f "$LOG_FILE" ]; then
|
|
echo '{"requests":[]}'
|
|
return
|
|
fi
|
|
|
|
if command -v jq >/dev/null 2>&1; then
|
|
echo '{"requests":'
|
|
tail -"$limit" "$LOG_FILE" 2>/dev/null | jq -s '.' 2>/dev/null || echo '[]'
|
|
echo '}'
|
|
else
|
|
echo '{"requests":[]}'
|
|
fi
|
|
}
|
|
|
|
# Get top hosts
|
|
get_top_hosts() {
|
|
local limit="${1:-20}"
|
|
|
|
if [ ! -f "$LOG_FILE" ] || ! command -v jq >/dev/null 2>&1; then
|
|
echo '{"hosts":[]}'
|
|
return
|
|
fi
|
|
|
|
echo '{"hosts":['
|
|
jq -r '.request.host // .host // "unknown"' "$LOG_FILE" 2>/dev/null | \
|
|
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
|
|
}
|
|
|
|
# Set configuration
|
|
set_config() {
|
|
local key="$1"
|
|
local value="$2"
|
|
local section="main"
|
|
|
|
case "$key" in
|
|
save_flows|capture_*)
|
|
section="capture"
|
|
;;
|
|
esac
|
|
|
|
uci set "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 <<EOF
|
|
{
|
|
"installed": true,
|
|
"path": "$cert",
|
|
"subject": "$subject",
|
|
"expires": "$expires",
|
|
"download_url": "http://$router_ip:$web_port/cert"
|
|
}
|
|
EOF
|
|
else
|
|
cat <<EOF
|
|
{
|
|
"installed": false,
|
|
"path": "$cert",
|
|
"download_url": ""
|
|
}
|
|
EOF
|
|
fi
|
|
}
|
|
|
|
# RPCD list method
|
|
case "$1" in
|
|
list)
|
|
cat <<EOF
|
|
{
|
|
"get_status": {},
|
|
"get_config": {},
|
|
"get_stats": {},
|
|
"get_requests": {"limit": 50},
|
|
"get_top_hosts": {"limit": 20},
|
|
"get_ca_info": {},
|
|
"service_start": {},
|
|
"service_stop": {},
|
|
"service_restart": {},
|
|
"set_config": {"key": "string", "value": "string"},
|
|
"clear_data": {}
|
|
}
|
|
EOF
|
|
;;
|
|
call)
|
|
case "$2" in
|
|
get_status)
|
|
get_status
|
|
;;
|
|
get_config)
|
|
get_config
|
|
;;
|
|
get_stats)
|
|
get_stats
|
|
;;
|
|
get_requests)
|
|
read -r input
|
|
limit=$(echo "$input" | jsonfilter -e '@.limit' 2>/dev/null || echo "50")
|
|
get_requests "$limit"
|
|
;;
|
|
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
|
|
;;
|
|
service_start)
|
|
service_start
|
|
;;
|
|
service_stop)
|
|
service_stop
|
|
;;
|
|
service_restart)
|
|
service_restart
|
|
;;
|
|
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"
|
|
;;
|
|
clear_data)
|
|
clear_data
|
|
;;
|
|
*)
|
|
echo '{"error":"Unknown method"}'
|
|
;;
|
|
esac
|
|
;;
|
|
*)
|
|
echo '{"error":"Unknown command"}'
|
|
;;
|
|
esac
|