secubox-openwrt/package/secubox/luci-app-metrics-dashboard/root/usr/libexec/rpcd/luci.metrics
CyberMind-FR 678e5a5921 feat(luci): Add Metrics Dashboard + fix WAF filters layout
New luci-app-metrics-dashboard with real-time system overview:
- System uptime, memory, load stats
- Core services status (HAProxy, mitmproxy, CrowdSec)
- vHosts, MetaBlog sites, Streamlit apps counts
- WAF alerts, bans, threats statistics
- Active connections (HTTP, HTTPS, SSH, TCP total)
- SSL certificates list
- Auto-refresh every 5 seconds

WAF Filters page:
- Changed stats display to single-line compact format
- Shows "17 Categories · 17 Active · 150 Rules" inline

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-17 11:54:37 +01:00

273 lines
8.1 KiB
Bash

#!/bin/sh
# SecuBox Metrics Dashboard - RPCD Backend
# Real-time system metrics for LuCI dashboard
. /usr/share/libubox/jshn.sh
# Get SSL certificates status
get_certs() {
json_init
json_add_array "certs"
local certs_dir="/srv/haproxy/certs"
local count=0
for pem in "$certs_dir"/*.pem; do
[ -f "$pem" ] || continue
count=$((count + 1))
[ $count -gt 20 ] && break
local name
name=$(basename "$pem" .pem)
local expiry
expiry=$(openssl x509 -enddate -noout -in "$pem" 2>/dev/null | cut -d= -f2)
json_add_object ""
json_add_string "name" "$name"
json_add_string "expiry" "${expiry:-unknown}"
json_add_int "days_left" "365"
json_add_string "status" "valid"
json_close_object
done
json_close_array
json_dump
}
# Get vHosts status
get_vhosts() {
json_init
json_add_array "vhosts"
local section domain backend enabled ssl
for section in $(uci show haproxy 2>/dev/null | grep "=vhost$" | cut -d. -f2 | cut -d= -f1); do
domain=$(uci -q get "haproxy.$section.domain")
backend=$(uci -q get "haproxy.$section.backend")
enabled=$(uci -q get "haproxy.$section.enabled")
ssl=$(uci -q get "haproxy.$section.ssl")
[ -z "$domain" ] && continue
[ "$enabled" != "1" ] && continue
json_add_object ""
json_add_string "domain" "$domain"
json_add_string "backend" "$backend"
json_add_boolean "ssl" "${ssl:-0}"
json_add_boolean "enabled" "$enabled"
json_close_object
done
json_close_array
local total
total=$(uci show haproxy 2>/dev/null | grep -c '=vhost$')
json_add_int "total" "$total"
json_dump
}
# Get MetaBlog sites
get_metablogs() {
json_init
json_add_array "sites"
local section name domain port enabled running
for section in $(uci show metablogizer 2>/dev/null | grep "=site$" | cut -d. -f2 | cut -d= -f1); do
name=$(echo "$section" | sed 's/^site_//')
domain=$(uci -q get "metablogizer.$section.domain")
port=$(uci -q get "metablogizer.$section.port")
enabled=$(uci -q get "metablogizer.$section.enabled")
running=0
netstat -tln 2>/dev/null | grep -q ":${port:-0} " && running=1
json_add_object ""
json_add_string "name" "$name"
json_add_string "domain" "$domain"
json_add_int "port" "${port:-0}"
json_add_boolean "enabled" "${enabled:-0}"
json_add_boolean "running" "$running"
json_close_object
done
json_close_array
json_dump
}
# Get Streamlit apps
get_streamlits() {
json_init
json_add_array "apps"
local section name domain port enabled running
for section in $(uci show streamlit 2>/dev/null | grep "=instance$" | cut -d. -f2 | cut -d= -f1); do
name="$section"
domain=$(uci -q get "streamlit.$section.domain")
port=$(uci -q get "streamlit.$section.port")
enabled=$(uci -q get "streamlit.$section.enabled")
running=0
pgrep -f "streamlit.*$port" >/dev/null 2>&1 && running=1
json_add_object ""
json_add_string "name" "$name"
json_add_string "domain" "$domain"
json_add_int "port" "${port:-0}"
json_add_boolean "enabled" "${enabled:-0}"
json_add_boolean "running" "$running"
json_close_object
done
json_close_array
json_dump
}
# Get WAF/CrowdSec stats
get_waf_stats() {
json_init
local cs_running=0
pgrep crowdsec >/dev/null 2>&1 && cs_running=1
local bans=0
local alerts_today=0
if [ "$cs_running" = "1" ]; then
bans=$(cscli decisions list -o json 2>/dev/null | grep -c '"id"' || echo 0)
alerts_today=$(cscli alerts list --since 24h -o json 2>/dev/null | grep -c '"id"' || echo 0)
fi
local mitmproxy_running=0
pgrep -f mitmdump >/dev/null 2>&1 && mitmproxy_running=1
local waf_threats=0
local waf_blocked=0
if [ -f "/tmp/secubox-mitm-stats.json" ]; then
waf_threats=$(jsonfilter -i /tmp/secubox-mitm-stats.json -e '@.threats_today' 2>/dev/null || echo 0)
waf_blocked=$(jsonfilter -i /tmp/secubox-mitm-stats.json -e '@.blocked_today' 2>/dev/null || echo 0)
fi
json_add_boolean "crowdsec_running" "$cs_running"
json_add_boolean "mitmproxy_running" "$mitmproxy_running"
json_add_int "active_bans" "${bans:-0}"
json_add_int "alerts_today" "${alerts_today:-0}"
json_add_int "waf_threats" "${waf_threats:-0}"
json_add_int "waf_blocked" "${waf_blocked:-0}"
json_dump
}
# Get active connections
get_connections() {
json_init
local http_conns https_conns ssh_conns total_tcp
http_conns=$(netstat -an 2>/dev/null | grep -c ":80 .*ESTABLISHED" || echo 0)
https_conns=$(netstat -an 2>/dev/null | grep -c ":443 .*ESTABLISHED" || echo 0)
ssh_conns=$(netstat -an 2>/dev/null | grep -c ":22 .*ESTABLISHED" || echo 0)
total_tcp=$(netstat -an 2>/dev/null | grep -c "ESTABLISHED" || echo 0)
json_add_int "http" "$http_conns"
json_add_int "https" "$https_conns"
json_add_int "ssh" "$ssh_conns"
json_add_int "total_tcp" "$total_tcp"
json_dump
}
# Get firewall stats
get_firewall_stats() {
json_init
local bouncer_blocks=0
if [ -f "/var/log/crowdsec-firewall-bouncer.log" ]; then
bouncer_blocks=$(grep -c "blocked" /var/log/crowdsec-firewall-bouncer.log 2>/dev/null || echo 0)
fi
json_add_int "iptables_drops" "0"
json_add_int "nft_drops" "0"
json_add_int "bouncer_blocks" "$bouncer_blocks"
json_dump
}
# Get system overview
get_overview() {
json_init
local uptime load mem_total mem_free mem_used mem_pct
uptime=$(cut -d. -f1 /proc/uptime)
load=$(cut -d' ' -f1-3 /proc/loadavg)
mem_total=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
mem_free=$(awk '/MemAvailable/ {print $2}' /proc/meminfo)
mem_used=$((mem_total - mem_free))
mem_pct=$((mem_used * 100 / mem_total))
local haproxy_up=0
lxc-info -n haproxy -s 2>/dev/null | grep -q RUNNING && haproxy_up=1
local mitmproxy_up=0
lxc-info -n mitmproxy-in -s 2>/dev/null | grep -q RUNNING && mitmproxy_up=1
local crowdsec_up=0
pgrep crowdsec >/dev/null 2>&1 && crowdsec_up=1
local vhost_count metablog_count streamlit_count cert_count lxc_running
vhost_count=$(uci show haproxy 2>/dev/null | grep -c '=vhost$')
metablog_count=$(uci show metablogizer 2>/dev/null | grep -c '=site$')
streamlit_count=$(uci show streamlit 2>/dev/null | grep -c '=instance$')
cert_count=$(ls /srv/haproxy/certs/*.pem 2>/dev/null | wc -l)
lxc_running=$(lxc-ls --running 2>/dev/null | wc -w)
json_add_int "uptime" "$uptime"
json_add_string "load" "$load"
json_add_int "mem_total_kb" "$mem_total"
json_add_int "mem_used_kb" "$mem_used"
json_add_int "mem_pct" "$mem_pct"
json_add_boolean "haproxy" "$haproxy_up"
json_add_boolean "mitmproxy" "$mitmproxy_up"
json_add_boolean "crowdsec" "$crowdsec_up"
json_add_int "vhosts" "$vhost_count"
json_add_int "metablogs" "$metablog_count"
json_add_int "streamlits" "$streamlit_count"
json_add_int "certificates" "$cert_count"
json_add_int "lxc_containers" "$lxc_running"
json_add_string "timestamp" "$(date -Iseconds)"
json_dump
}
# Get all metrics
get_all() {
local overview waf conns fw
overview=$(get_overview)
waf=$(get_waf_stats)
conns=$(get_connections)
fw=$(get_firewall_stats)
printf '{"overview":%s,"waf":%s,"connections":%s,"firewall":%s}' "$overview" "$waf" "$conns" "$fw"
}
case "$1" in
list)
echo '{"overview":{},"certs":{},"vhosts":{},"metablogs":{},"streamlits":{},"waf_stats":{},"connections":{},"firewall_stats":{},"all":{}}'
;;
call)
case "$2" in
overview) get_overview ;;
certs) get_certs ;;
vhosts) get_vhosts ;;
metablogs) get_metablogs ;;
streamlits) get_streamlits ;;
waf_stats) get_waf_stats ;;
connections) get_connections ;;
firewall_stats) get_firewall_stats ;;
all) get_all ;;
*) echo '{"error":"Unknown method"}' ;;
esac
;;
esac