secubox-openwrt/package/secubox/secubox-p2p/root/usr/sbin/secubox-p2p
CyberMind-FR 5a40e8a61e feat: Major updates - CDN cache with Squid, network modes UI rework, bugfixes
CDN Cache:
- Migrate from nginx to Squid proxy for better caching
- Add aggressive caching rules for Windows Update, Linux repos, Steam, Apple
- Proper firewall integration via UCI (transparent proxy)
- Real-time stats from Squid access logs

Network Modes:
- Complete UI rework with MirrorBox dark theme
- 9 network modes with emojis and descriptions
- Dynamic CSS animations and modern styling

Fixes:
- Fix jshn boolean handling in secubox-recovery (1/0 vs true/false)
- Fix nDPId RPCD to use netifyd as fallback DPI provider
- Update media-flow and security-threats dashboards

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:03:02 +01:00

367 lines
9.1 KiB
Bash

#!/bin/sh
# SecuBox P2P Hub Manager
# Handles peer discovery, mesh networking, and service federation
VERSION="0.1.0"
CONFIG_FILE="/etc/config/secubox-p2p"
PEERS_FILE="/tmp/secubox-p2p-peers.json"
SERVICES_FILE="/tmp/secubox-p2p-services.json"
STATE_DIR="/var/run/secubox-p2p"
# Initialize
init() {
mkdir -p "$STATE_DIR"
[ -f "$PEERS_FILE" ] || echo '{"peers":[]}' > "$PEERS_FILE"
[ -f "$SERVICES_FILE" ] || echo '{"services":[]}' > "$SERVICES_FILE"
}
# Get config value
get_config() {
local section="$1"
local option="$2"
local default="$3"
uci -q get "secubox-p2p.${section}.${option}" || echo "$default"
}
# Set config value
set_config() {
local section="$1"
local option="$2"
local value="$3"
uci set "secubox-p2p.${section}.${option}=$value"
uci commit secubox-p2p
}
# Discover peers via mDNS
discover_mdns() {
local timeout="${1:-5}"
local peers="[]"
# Check if avahi-browse is available
if command -v avahi-browse >/dev/null 2>&1; then
# Discover _secubox._tcp services
local discovered=$(avahi-browse -t -r _secubox._tcp 2>/dev/null | grep -E "^=|hostname|address" || true)
if [ -n "$discovered" ]; then
# Parse discovered services into JSON
echo "$discovered" | awk '
/^=/ { name=$4 }
/hostname/ { host=$3 }
/address/ {
addr=$3
if (name && addr) {
printf "{\"id\":\"%s\",\"name\":\"%s\",\"address\":\"%s\",\"status\":\"online\"},", name, name, addr
}
}
' | sed 's/,$//' | awk '{print "["$0"]"}'
else
echo "[]"
fi
else
# Fallback: scan local network
local gateway=$(ip route | grep default | awk '{print $3}')
local subnet=$(echo "$gateway" | sed 's/\.[0-9]*$/./')
# Quick ping scan
for i in $(seq 1 254); do
ping -c1 -W1 "${subnet}${i}" >/dev/null 2>&1 &
done
wait
# Check for SecuBox peers via HTTP
arp -n | grep -v incomplete | awk '{print $1}' | while read ip; do
if curl -s --connect-timeout 1 "http://${ip}/cgi-bin/luci/admin/secubox" >/dev/null 2>&1; then
echo "{\"id\":\"peer-${ip}\",\"name\":\"SecuBox@${ip}\",\"address\":\"${ip}\",\"status\":\"online\"}"
fi
done | jq -s '.' 2>/dev/null || echo "[]"
fi
}
# Get peers list
get_peers() {
if [ -f "$PEERS_FILE" ]; then
cat "$PEERS_FILE"
else
echo '{"peers":[]}'
fi
}
# Add peer
add_peer() {
local address="$1"
local name="${2:-Peer}"
local id="peer-$(echo "$address" | md5sum | cut -c1-8)"
local peers=$(get_peers)
local new_peer="{\"id\":\"$id\",\"name\":\"$name\",\"address\":\"$address\",\"status\":\"unknown\",\"added\":\"$(date -Iseconds)\"}"
echo "$peers" | jq ".peers += [$new_peer]" > "$PEERS_FILE"
echo "{\"success\":true,\"peer_id\":\"$id\"}"
}
# Remove peer
remove_peer() {
local peer_id="$1"
local peers=$(get_peers)
echo "$peers" | jq ".peers = [.peers[] | select(.id != \"$peer_id\")]" > "$PEERS_FILE"
echo "{\"success\":true}"
}
# Get settings
get_settings() {
cat <<EOF
{
"enabled": $(get_config main enabled 1),
"node_name": "$(get_config main node_name "")",
"discovery_enabled": $(get_config main discovery_enabled 1),
"sharing_enabled": $(get_config main sharing_enabled 1),
"auto_sync": $(get_config main auto_sync 1),
"sync_interval": $(get_config main sync_interval 60),
"dns_federation": {
"enabled": $(get_config dns enabled 0),
"primary_dns": "$(get_config dns primary_dns "127.0.0.1:53")",
"base_domain": "$(get_config dns base_domain "sb.local")"
},
"wireguard": {
"enabled": $(get_config wireguard enabled 0),
"listen_port": $(get_config wireguard listen_port 51820),
"network_cidr": "$(get_config wireguard network_cidr "10.100.0.0/24")"
},
"haproxy": {
"enabled": $(get_config haproxy enabled 0),
"strategy": "$(get_config haproxy strategy "round-robin")"
},
"registry": {
"base_url": "$(get_config registry base_url "sb.local")",
"cache_enabled": $(get_config registry cache_enabled 1)
}
}
EOF
}
# Set settings
set_settings() {
local json="$1"
# Parse and apply settings
local enabled=$(echo "$json" | jsonfilter -e '@.enabled')
local sharing=$(echo "$json" | jsonfilter -e '@.sharing_enabled')
local discovery=$(echo "$json" | jsonfilter -e '@.discovery_enabled')
[ -n "$enabled" ] && set_config main enabled "$enabled"
[ -n "$sharing" ] && set_config main sharing_enabled "$sharing"
[ -n "$discovery" ] && set_config main discovery_enabled "$discovery"
echo "{\"success\":true}"
}
# Get local services - scan init.d and detect running status
get_services() {
local services=""
local count=0
# Service port mapping
get_service_port() {
case "$1" in
dnsmasq) echo "53" ;;
uhttpd) echo "80" ;;
nginx) echo "80" ;;
haproxy) echo "80,443" ;;
crowdsec) echo "8080" ;;
crowdsec-firewall-bouncer) echo "" ;;
dropbear) echo "22" ;;
sshd) echo "22" ;;
firewall*) echo "" ;;
wireguard|wg*) echo "51820" ;;
gitea) echo "3000" ;;
localai) echo "8080" ;;
ollama) echo "11434" ;;
nextcloud) echo "8080" ;;
lxc*) echo "" ;;
rpcd) echo "" ;;
*) echo "" ;;
esac
}
# Scan init.d services
for init_script in /etc/init.d/*; do
[ -x "$init_script" ] || continue
local svc_name=$(basename "$init_script")
# Skip system services
case "$svc_name" in
boot|done|rcS|rc.local|umount|sysfixtime|sysntpd|gpio_switch) continue ;;
esac
# Check if service is running
local status="stopped"
local pid=""
# Method 1: Check via init script status
if "$init_script" status >/dev/null 2>&1; then
if "$init_script" status 2>&1 | grep -qiE "running|active"; then
status="running"
fi
fi
# Method 2: Check via pgrep (fallback)
if [ "$status" = "stopped" ]; then
if pgrep -f "$svc_name" >/dev/null 2>&1; then
status="running"
pid=$(pgrep -f "$svc_name" | head -1)
fi
fi
# Method 3: Check if enabled in UCI/procd
local enabled="0"
if "$init_script" enabled 2>/dev/null; then
enabled="1"
fi
local port=$(get_service_port "$svc_name")
# Build JSON entry
if [ $count -gt 0 ]; then
services="$services,"
fi
services="$services{\"name\":\"$svc_name\",\"status\":\"$status\",\"enabled\":$enabled,\"port\":\"$port\",\"pid\":\"$pid\"}"
count=$((count + 1))
done
echo "{\"services\":[$services],\"total\":$count}"
}
# Get shared services (from peers)
get_shared_services() {
local all_services="[]"
local peers=$(get_peers | jq -r '.peers[] | select(.status=="online") | .address')
for peer_addr in $peers; do
local peer_services=$(curl -s --connect-timeout 2 "http://${peer_addr}:8080/p2p/services" 2>/dev/null || echo "[]")
all_services=$(echo "$all_services" | jq ". += $peer_services")
done
echo "{\"shared_services\":$all_services}"
}
# Sync with peers
sync_catalog() {
local peers=$(get_peers | jq -r '.peers[].address')
local synced=0
for peer_addr in $peers; do
if curl -s --connect-timeout 2 "http://${peer_addr}/cgi-bin/luci" >/dev/null 2>&1; then
synced=$((synced + 1))
fi
done
echo "{\"success\":true,\"synced_peers\":$synced}"
}
# Broadcast command to all peers
broadcast_command() {
local cmd="$1"
local peers=$(get_peers | jq -r '.peers[] | select(.status=="online") | .address')
local success=0
local failed=0
for peer_addr in $peers; do
if curl -s --connect-timeout 5 -X POST "http://${peer_addr}:8080/p2p/command" -d "{\"command\":\"$cmd\"}" >/dev/null 2>&1; then
success=$((success + 1))
else
failed=$((failed + 1))
fi
done
echo "{\"success\":true,\"broadcast_success\":$success,\"broadcast_failed\":$failed}"
}
# Daemon mode
daemon_loop() {
init
while true; do
# Auto-discovery if enabled
if [ "$(get_config main discovery_enabled 1)" = "1" ]; then
local discovered=$(discover_mdns 3)
if [ "$discovered" != "[]" ]; then
# Update peers file with discovered peers
local current=$(get_peers)
for peer in $(echo "$discovered" | jq -c '.[]'); do
local peer_id=$(echo "$peer" | jq -r '.id')
local exists=$(echo "$current" | jq ".peers[] | select(.id==\"$peer_id\")")
if [ -z "$exists" ]; then
current=$(echo "$current" | jq ".peers += [$peer]")
fi
done
echo "$current" > "$PEERS_FILE"
fi
fi
# Update peer status
local peers=$(get_peers)
local updated_peers=$(echo "$peers" | jq '.peers | map(. + {"status": "checking"})' | jq -c '.[]')
for peer in $updated_peers; do
local addr=$(echo "$peer" | jq -r '.address')
local id=$(echo "$peer" | jq -r '.id')
if ping -c1 -W1 "$addr" >/dev/null 2>&1; then
peers=$(echo "$peers" | jq "(.peers[] | select(.id==\"$id\")).status = \"online\"")
else
peers=$(echo "$peers" | jq "(.peers[] | select(.id==\"$id\")).status = \"offline\"")
fi
done
echo "$peers" > "$PEERS_FILE"
# Sleep interval
local interval=$(get_config main sync_interval 60)
sleep "$interval"
done
}
# Main
case "$1" in
daemon)
daemon_loop
;;
discover)
discover_mdns "${2:-5}"
;;
peers)
get_peers
;;
add-peer)
add_peer "$2" "$3"
;;
remove-peer)
remove_peer "$2"
;;
settings)
get_settings
;;
set-settings)
set_settings "$2"
;;
services)
get_services
;;
shared-services)
get_shared_services
;;
sync)
sync_catalog
;;
broadcast)
broadcast_command "$2"
;;
version)
echo "$VERSION"
;;
*)
echo "Usage: $0 {daemon|discover|peers|add-peer|remove-peer|settings|set-settings|services|shared-services|sync|broadcast|version}"
exit 1
;;
esac