#!/bin/sh # RPCD backend for SecuBox Dynamic Services Registry # Aggregates all SecuBox services with their published URLs, emojis, and metrics . /lib/functions.sh . /usr/share/libubox/jshn.sh # Service emoji registry get_service_emoji() { case "$1" in mitmproxy*) echo "🔍" ;; crowdsec*) echo "🛡️" ;; haproxy*) echo "⚡" ;; squid*|cdn*) echo "💾" ;; wireguard*|wg*) echo "🔐" ;; tor*) echo "🧅" ;; dnsmasq*) echo "🌐" ;; netdata*) echo "📊" ;; glances*) echo "📈" ;; sshd*|ssh*) echo "🔑" ;; uhttpd*) echo "🖥️" ;; iot*) echo "📡" ;; vortex*) echo "🌀" ;; interceptor*) echo "🧙" ;; cookie*) echo "🍪" ;; system*) echo "⚙️" ;; *) echo "📦" ;; esac } # Get service category get_service_category() { case "$1" in mitmproxy*|crowdsec*|firewall*|nftables*) echo "security" ;; haproxy*|nginx*) echo "routing" ;; squid*|cdn*) echo "caching" ;; wireguard*|wg*|vpn*) echo "vpn" ;; tor*) echo "anonymity" ;; dnsmasq*|dns*|vortex*) echo "dns" ;; netdata*|glances*|monitoring*) echo "monitoring" ;; uhttpd*|luci*) echo "web" ;; iot*) echo "iot" ;; *) echo "other" ;; esac } # Get HAProxy vhosts as published services (optimized single-pass) get_haproxy_vhosts() { local count=0 local tmpfile="/tmp/haproxy_vhosts_$$" # Single UCI call, parse with awk into temp file uci show haproxy 2>/dev/null | awk -F'[.=]' ' /=vhost$/ { section=$2; vhosts[section]=1 } /\.domain=/ { gsub(/\047/, "", $NF); domain[$2]=$NF } /\.backend=/ { gsub(/\047/, "", $NF); backend[$2]=$NF } /\.ssl_enabled=/ { gsub(/\047/, "", $NF); ssl[$2]=$NF } END { for (s in vhosts) { if (domain[s] != "") { print s "|" domain[s] "|" backend[s] "|" ssl[s] } } }' > "$tmpfile" # Process temp file with jshn while IFS='|' read -r vhost domain backend ssl; do [ -z "$domain" ] && continue local proto="http" [ "$ssl" = "1" ] && proto="https" json_add_object json_add_string "id" "haproxy-$vhost" json_add_string "name" "$domain" json_add_string "type" "vhost" json_add_string "url" "${proto}://${domain}" json_add_string "backend" "$backend" json_add_string "emoji" "🌐" json_add_string "category" "published" json_add_boolean "ssl" "${ssl:-0}" json_close_object count=$((count + 1)) done < "$tmpfile" rm -f "$tmpfile" echo "$count" } # Get Tor hidden services get_tor_services() { local count=0 local onion_dir="/var/lib/tor/hidden_services" if [ -d "$onion_dir" ]; then for svc in "$onion_dir"/*/hostname; do [ -f "$svc" ] || continue local name=$(dirname "$svc" | xargs basename) local onion=$(cat "$svc" 2>/dev/null) [ -z "$onion" ] && continue json_add_object json_add_string "id" "tor-$name" json_add_string "name" "$name" json_add_string "type" "onion" json_add_string "url" "http://${onion}" json_add_string "onion" "$onion" json_add_string "emoji" "🧅" json_add_string "category" "anonymity" json_close_object count=$((count + 1)) done fi echo "$count" } # Get mitmproxy instances get_mitmproxy_instances() { local count=0 for inst in $(uci show mitmproxy 2>/dev/null | grep "=instance" | cut -d'.' -f2 | cut -d'=' -f1); do local enabled=$(uci -q get mitmproxy.$inst.enabled || echo 0) local desc=$(uci -q get mitmproxy.$inst.description || echo "") local web_port=$(uci -q get mitmproxy.$inst.web_port || echo "8081") local proxy_port=$(uci -q get mitmproxy.$inst.proxy_port || echo "8888") local container=$(uci -q get mitmproxy.$inst.container_name || echo "mitmproxy-$inst") local mode=$(uci -q get mitmproxy.$inst.mode || echo "regular") # Check if running local running=0 lxc-info -n "$container" -s 2>/dev/null | grep -q "RUNNING" && running=1 json_add_object json_add_string "id" "mitmproxy-$inst" json_add_string "name" "mitmproxy-$inst" json_add_string "type" "proxy" json_add_string "url" "http://c3box.sblocal:$web_port" json_add_string "description" "$desc" json_add_string "emoji" "🔍" json_add_string "category" "security" json_add_string "mode" "$mode" json_add_int "proxy_port" "$proxy_port" json_add_int "web_port" "$web_port" json_add_boolean "enabled" "$enabled" json_add_boolean "running" "$running" json_close_object count=$((count + 1)) done echo "$count" } # Get init.d services with status (optimized - skip slow checks) get_init_services() { local count=0 # Only check key SecuBox services (fast list) for name in crowdsec haproxy mitmproxy wireguard tor dnsmasq uhttpd rpcd netifyd sshd; do local svc="/etc/init.d/$name" [ -x "$svc" ] || continue local enabled=0 local running=0 # Check enabled via symlink (faster than calling script) [ -L "/etc/rc.d/S"*"$name" ] 2>/dev/null && enabled=1 # Check running via pgrep pgrep -x "$name" >/dev/null 2>&1 && running=1 local emoji=$(get_service_emoji "$name") local category=$(get_service_category "$name") json_add_object json_add_string "id" "initd-$name" json_add_string "name" "$name" json_add_string "type" "service" json_add_string "emoji" "$emoji" json_add_string "category" "$category" json_add_boolean "enabled" "$enabled" json_add_boolean "running" "$running" json_close_object count=$((count + 1)) done echo "$count" } # Get LuCI apps as dashboard links get_luci_apps() { local count=0 # Parse menu.d files for SecuBox apps for menu in /usr/share/luci/menu.d/luci-app-*.json; do [ -f "$menu" ] || continue local app_name=$(basename "$menu" .json | sed 's/luci-app-//') local title=$(jsonfilter -i "$menu" -e '@.admin.*.title' 2>/dev/null | head -1) local path=$(jsonfilter -i "$menu" -e '@.admin.*.action.path' 2>/dev/null | head -1) [ -z "$title" ] && title="$app_name" [ -z "$path" ] && path="admin/$app_name" local emoji=$(get_service_emoji "$app_name") json_add_object json_add_string "id" "luci-$app_name" json_add_string "name" "$title" json_add_string "type" "dashboard" json_add_string "url" "/cgi-bin/luci/$path" json_add_string "emoji" "$emoji" json_add_string "category" "web" json_close_object count=$((count + 1)) done echo "$count" } # Get metrics summary (optimized - skip slow cscli) get_metrics_summary() { json_add_object "metrics" # System metrics from /proc (fast) local uptime=$(cut -d' ' -f1 /proc/uptime | cut -d'.' -f1) local load=$(cut -d' ' -f1 /proc/loadavg) # Memory from /proc/meminfo in one read eval $(awk '/^MemTotal:/{t=$2} /^MemAvailable:/{a=$2} END{printf "mem_total=%d mem_avail=%d", t, a}' /proc/meminfo) local mem_pct=$(( (mem_total - mem_avail) * 100 / mem_total )) json_add_int "uptime" "$uptime" json_add_string "load" "$load" json_add_int "mem_pct" "$mem_pct" # Service counts from cached data or fast check local running=$(pgrep -c . 2>/dev/null || echo 0) local total=$(ls -1 /etc/init.d/ 2>/dev/null | wc -l) json_add_int "services_running" "$running" json_add_int "services_total" "$total" # CrowdSec metrics from cache file (fast) if [ -f /tmp/secubox/crowdsec-overview.json ]; then local alerts=$(jsonfilter -i /tmp/secubox/crowdsec-overview.json -e '@.alerts_24h' 2>/dev/null || echo 0) local bans=$(jsonfilter -i /tmp/secubox/crowdsec-overview.json -e '@.active_decisions' 2>/dev/null || echo 0) json_add_int "crowdsec_alerts" "${alerts:-0}" json_add_int "crowdsec_bans" "${bans:-0}" else json_add_int "crowdsec_alerts" 0 json_add_int "crowdsec_bans" 0 fi json_close_object } case "$1" in list) json_init json_add_object "getServices" json_close_object json_add_object "getPublished" json_close_object json_add_object "getMetrics" json_close_object json_add_object "getAll" json_close_object json_dump ;; call) case "$2" in getServices) json_init json_add_boolean "success" 1 json_add_array "services" get_init_services >/dev/null json_close_array json_dump ;; getPublished) json_init json_add_boolean "success" 1 json_add_array "published" get_haproxy_vhosts >/dev/null get_tor_services >/dev/null json_close_array json_dump ;; getMetrics) json_init json_add_boolean "success" 1 get_metrics_summary json_dump ;; getAll) json_init json_add_boolean "success" 1 # All services json_add_array "services" get_init_services >/dev/null json_close_array # Published URLs (vhosts, onions) json_add_array "published" get_haproxy_vhosts >/dev/null get_tor_services >/dev/null json_close_array # Proxy instances json_add_array "proxies" get_mitmproxy_instances >/dev/null json_close_array # LuCI dashboards json_add_array "dashboards" get_luci_apps >/dev/null json_close_array # Metrics get_metrics_summary json_dump ;; *) json_init json_add_boolean "success" 0 json_add_string "error" "Unknown method" json_dump ;; esac ;; esac