secubox-openwrt/package/secubox/secubox-p2p/root/usr/sbin/secubox-p2p
CyberMind-FR 2b913d5005 feat(p2p): Add SecuBox P2P Hub packages and Services Registry
- Add secubox-p2p backend package:
  - UCI configuration for P2P settings, DNS federation, WireGuard mesh, HAProxy
  - RPCD handler for peer management, service discovery, mesh configuration
  - Init script and main P2P manager daemon

- Add luci-app-secubox-p2p frontend package:
  - Main hub view with master control, network matrix visualization
  - Peers management with discovery and manual add
  - Services view showing local and shared services
  - Mesh network configuration (DNS, WireGuard, HAProxy)
  - Settings for P2P and registry configuration

- Add Services Registry view to luci-app-secubox
- Add listProfiles/applyProfile to secubox-admin API
- Fix P2P ACL permissions
- Remove old hub.js from luci-app-secubox (moved to dedicated package)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 19:46:28 +01:00

316 lines
7.9 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
get_services() {
local services="[]"
# Detect running services
for svc in dnsmasq uhttpd nginx crowdsec haproxy wireguard; do
if pgrep "$svc" >/dev/null 2>&1; then
local port=""
local protocol="tcp"
case "$svc" in
dnsmasq) port="53"; protocol="udp" ;;
uhttpd) port="80" ;;
nginx) port="80" ;;
crowdsec) port="8080" ;;
haproxy) port="80" ;;
esac
services=$(echo "$services" | jq ". += [{\"name\":\"$svc\",\"status\":\"running\",\"port\":\"$port\",\"protocol\":\"$protocol\"}]")
fi
done
echo "{\"services\":$services}"
}
# 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