- Fix jshn boolean handling (use 1/0 instead of "true"/"false") - Rework UI with dark theme compatible styling - Add emoji-based status indicators (🔗🔒🛡️✅) - Simplify interface with async Load More pagination - Update README.md to v0.18.0 with 86 modules Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
242 lines
5.7 KiB
Bash
Executable File
242 lines
5.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# RPCD handler for Routes Status dashboard
|
|
# Shows HAProxy vhosts and mitmproxy route configuration status
|
|
# Optimized with pagination
|
|
|
|
. /usr/share/libubox/jshn.sh
|
|
|
|
MITMPROXY_ROUTES="/srv/mitmproxy/haproxy-routes.json"
|
|
MITMPROXY_IN_ROUTES="/srv/mitmproxy-in/haproxy-routes.json"
|
|
HAPROXY_CERTS="/srv/haproxy/certs"
|
|
|
|
# Get host LAN IP for route configuration
|
|
get_host_ip() {
|
|
uci -q get network.lan.ipaddr || echo "192.168.255.1"
|
|
}
|
|
|
|
# Main status method - optimized with pagination
|
|
method_status() {
|
|
local offset=0
|
|
local limit=50
|
|
|
|
# Read JSON input for pagination params
|
|
read -r input 2>/dev/null
|
|
if [ -n "$input" ]; then
|
|
json_load "$input" 2>/dev/null
|
|
json_get_var offset offset 2>/dev/null
|
|
json_get_var limit limit 2>/dev/null
|
|
fi
|
|
[ -z "$offset" ] && offset=0
|
|
[ -z "$limit" ] && limit=50
|
|
|
|
local host_ip=$(get_host_ip)
|
|
local haproxy_running=$(pgrep haproxy >/dev/null 2>&1 && echo "1" || echo "0")
|
|
local mitmproxy_running=$(pgrep -f mitmproxy >/dev/null 2>&1 && echo "1" || echo "0")
|
|
|
|
# Fetch vhost list once to temp file
|
|
local vhost_tmp="/tmp/vhosts_$$"
|
|
if command -v haproxyctl >/dev/null 2>&1; then
|
|
haproxyctl vhost list 2>/dev/null | tail -n +3 > "$vhost_tmp"
|
|
else
|
|
touch "$vhost_tmp"
|
|
fi
|
|
|
|
# Count total vhosts
|
|
local total=$(wc -l < "$vhost_tmp" | tr -d ' ')
|
|
|
|
json_init
|
|
json_add_boolean haproxy_running "$haproxy_running"
|
|
json_add_boolean mitmproxy_running "$mitmproxy_running"
|
|
json_add_string host_ip "$host_ip"
|
|
json_add_int total "$total"
|
|
json_add_int offset "$offset"
|
|
json_add_int limit "$limit"
|
|
|
|
json_add_array vhosts
|
|
|
|
# Process vhost data with pagination
|
|
local count=0
|
|
local processed=0
|
|
while IFS= read -r line; do
|
|
[ -z "$line" ] && continue
|
|
|
|
# Skip until offset
|
|
if [ "$count" -lt "$offset" ]; then
|
|
count=$((count + 1))
|
|
continue
|
|
fi
|
|
|
|
# Stop after limit
|
|
if [ "$processed" -ge "$limit" ]; then
|
|
break
|
|
fi
|
|
|
|
# Parse line: " domain.com -> backend_name [enabled] SSL ..."
|
|
local domain=$(echo "$line" | awk '{print $1}')
|
|
local backend=$(echo "$line" | awk '{print $3}')
|
|
local enabled=$(echo "$line" | grep -qF '[enabled]' && echo "1" || echo "0")
|
|
|
|
[ -z "$domain" ] && continue
|
|
|
|
# Check mitmproxy routes (use 1/0 for jshn booleans)
|
|
local has_route_out="0"
|
|
local has_route_in="0"
|
|
if [ -f "$MITMPROXY_ROUTES" ] && grep "$domain" "$MITMPROXY_ROUTES" >/dev/null 2>&1; then
|
|
has_route_out="1"
|
|
fi
|
|
if [ -f "$MITMPROXY_IN_ROUTES" ] && grep "$domain" "$MITMPROXY_IN_ROUTES" >/dev/null 2>&1; then
|
|
has_route_in="1"
|
|
fi
|
|
|
|
# Check SSL cert
|
|
local ssl_status="missing"
|
|
[ -f "$HAPROXY_CERTS/${domain}.pem" ] && ssl_status="valid"
|
|
|
|
# WAF bypass check (1=bypassed, 0=waf active)
|
|
local waf_bypass="0"
|
|
[ "$backend" != "mitmproxy_inspector" ] && waf_bypass="1"
|
|
|
|
json_add_object ""
|
|
json_add_string domain "$domain"
|
|
json_add_string backend "$backend"
|
|
json_add_string backend_port ""
|
|
json_add_boolean active "$enabled"
|
|
json_add_string ssl_status "$ssl_status"
|
|
json_add_boolean has_route_out "$has_route_out"
|
|
json_add_boolean has_route_in "$has_route_in"
|
|
json_add_string route_target_out ""
|
|
json_add_string route_target_in ""
|
|
json_add_boolean waf_bypass "$waf_bypass"
|
|
json_close_object
|
|
|
|
count=$((count + 1))
|
|
processed=$((processed + 1))
|
|
done < "$vhost_tmp"
|
|
|
|
json_close_array
|
|
json_dump
|
|
|
|
# Cleanup
|
|
rm -f "$vhost_tmp"
|
|
}
|
|
|
|
# Sync routes from HAProxy backends to mitmproxy
|
|
method_sync_routes() {
|
|
local result
|
|
if [ -x /usr/sbin/mitmproxyctl ]; then
|
|
result=$(/usr/sbin/mitmproxyctl sync-routes 2>&1)
|
|
json_init
|
|
json_add_boolean success 1
|
|
json_add_string output "$result"
|
|
json_dump
|
|
else
|
|
json_init
|
|
json_add_boolean success 0
|
|
json_add_string error "mitmproxyctl not found"
|
|
json_dump
|
|
fi
|
|
}
|
|
|
|
# Add a missing route for a domain
|
|
method_add_route() {
|
|
local domain port
|
|
|
|
# Read JSON input
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var domain domain
|
|
json_get_var port port
|
|
|
|
if [ -z "$domain" ] || [ -z "$port" ]; then
|
|
json_init
|
|
json_add_boolean success 0
|
|
json_add_string error "Missing domain or port parameter"
|
|
json_dump
|
|
return
|
|
fi
|
|
|
|
local host_ip=$(get_host_ip)
|
|
|
|
# Add route to both mitmproxy route files
|
|
local success="1"
|
|
local errors=""
|
|
|
|
for routes_file in "$MITMPROXY_ROUTES" "$MITMPROXY_IN_ROUTES"; do
|
|
if [ -f "$routes_file" ]; then
|
|
# Create temp file with new route
|
|
local tmpfile=$(mktemp)
|
|
if command -v jq >/dev/null 2>&1; then
|
|
jq --arg d "$domain" --arg h "$host_ip" --argjson p "$port" \
|
|
'. + {($d): [$h, $p]}' "$routes_file" > "$tmpfile" 2>/dev/null
|
|
else
|
|
# Fallback: manual JSON manipulation
|
|
sed 's/}$//' "$routes_file" > "$tmpfile"
|
|
if grep -q '": \[' "$routes_file"; then
|
|
printf ',\n "%s": ["%s", %s]\n}\n' "$domain" "$host_ip" "$port" >> "$tmpfile"
|
|
else
|
|
printf ' "%s": ["%s", %s]\n}\n' "$domain" "$host_ip" "$port" >> "$tmpfile"
|
|
fi
|
|
fi
|
|
|
|
if [ -s "$tmpfile" ]; then
|
|
mv "$tmpfile" "$routes_file"
|
|
else
|
|
rm -f "$tmpfile"
|
|
success="0"
|
|
errors="$errors Failed to update $routes_file."
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Restart mitmproxy to apply changes
|
|
if [ "$success" = "1" ]; then
|
|
/etc/init.d/mitmproxy restart >/dev/null 2>&1
|
|
fi
|
|
|
|
json_init
|
|
json_add_boolean success "$success"
|
|
[ -n "$errors" ] && json_add_string error "$errors"
|
|
json_dump
|
|
}
|
|
|
|
# List available methods
|
|
list_methods() {
|
|
json_init
|
|
json_add_object status
|
|
json_add_int offset 0
|
|
json_add_int limit 50
|
|
json_close_object
|
|
json_add_object sync_routes
|
|
json_close_object
|
|
json_add_object add_route
|
|
json_add_string domain "string"
|
|
json_add_int port 0
|
|
json_close_object
|
|
json_dump
|
|
}
|
|
|
|
case "$1" in
|
|
list)
|
|
list_methods
|
|
;;
|
|
call)
|
|
case "$2" in
|
|
status)
|
|
method_status
|
|
;;
|
|
sync_routes)
|
|
method_sync_routes
|
|
;;
|
|
add_route)
|
|
method_add_route
|
|
;;
|
|
*)
|
|
echo '{"error":"Unknown method"}'
|
|
;;
|
|
esac
|
|
;;
|
|
*)
|
|
echo '{"error":"Unknown action"}'
|
|
;;
|
|
esac
|