secubox-openwrt/package/secubox/secubox-app-yggdrasil-discovery/files/usr/lib/yggdrasil-discovery/gossip-handler.sh
CyberMind-FR 4a0ab9530f feat(mesh): Yggdrasil extended peer discovery + bugfixes
## New Features
- secubox-app-yggdrasil-discovery: Mesh peer discovery via gossip protocol
  - yggctl CLI: status, self, peers, announce, discover, bootstrap
  - Auto-peering with trust verification (master-link fingerprint)
  - Daemon for periodic announcements

## Bug Fixes
- tor-shield: Fix opkg downloads failing when Tor active
  - DNS over Tor disabled by default
  - Auto-exclude public DNS servers from iptables rules
  - Excluded domains bypass list (openwrt.org, pool.ntp.org, etc.)

- haproxy: Fix portal 503 "End of Internet" error
  - Corrected malformed vhost backend configuration
  - Regenerated HAProxy config from UCI

- luci-app-nextcloud: Fix users list showing empty
  - RPC expect clause was extracting array, render expected object

## Updated
- Bonus feed: All IPKs rebuilt
- Documentation: HISTORY.md, WIP.md, TODO.md updated

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-28 17:32:41 +01:00

125 lines
3.6 KiB
Bash

#!/bin/sh
# Yggdrasil Discovery Gossip Handler
# Handles yggdrasil_peer messages from mirrornet gossip protocol
. /usr/lib/yggdrasil-discovery/core.sh
# Handle incoming yggdrasil_peer announcement
handle_peer_announce() {
local data="$1"
local origin="$2"
# Parse announcement data
local ipv6 pubkey hostname ml_fingerprint zkp_fingerprint timestamp
ipv6=$(echo "$data" | jsonfilter -e '@.ipv6' 2>/dev/null)
pubkey=$(echo "$data" | jsonfilter -e '@.pubkey' 2>/dev/null)
hostname=$(echo "$data" | jsonfilter -e '@.hostname' 2>/dev/null)
ml_fingerprint=$(echo "$data" | jsonfilter -e '@.ml_fingerprint' 2>/dev/null)
zkp_fingerprint=$(echo "$data" | jsonfilter -e '@.zkp_fingerprint' 2>/dev/null)
timestamp=$(echo "$data" | jsonfilter -e '@.timestamp' 2>/dev/null)
# Validate IPv6 is in Yggdrasil range (200::/7)
if ! echo "$ipv6" | grep -qE '^2[0-9a-f]{2}:'; then
logger -t yggdrasil-discovery "Rejected: Invalid Yggdrasil IPv6: $ipv6"
return 1
fi
# Don't add self
local my_ipv6
my_ipv6=$(get_ygg_ipv6)
if [ "$ipv6" = "$my_ipv6" ]; then
return 0
fi
# Add to peer cache
add_peer_to_cache "$ipv6" "$pubkey" "$hostname" "$ml_fingerprint" "$zkp_fingerprint" "$timestamp"
# Auto-peer if enabled and trusted
local auto_peer
auto_peer=$(uci -q get yggdrasil-discovery.main.auto_peer)
if [ "$auto_peer" = "1" ]; then
local require_trust
require_trust=$(uci -q get yggdrasil-discovery.main.require_trust)
local should_connect=0
if [ "$require_trust" = "1" ]; then
# Only connect if trusted
if is_peer_trusted "$ml_fingerprint"; then
should_connect=1
logger -t yggdrasil-discovery "Auto-peering with trusted node: $hostname ($ipv6)"
else
logger -t yggdrasil-discovery "Skipping untrusted peer: $hostname ($ipv6)"
fi
else
# Connect to all discovered peers
should_connect=1
fi
if [ "$should_connect" = "1" ] && command -v yggdrasilctl >/dev/null 2>&1; then
# Check if already connected
local already_connected=0
yggdrasilctl -json getPeers 2>/dev/null | grep -q "$ipv6" && already_connected=1
if [ "$already_connected" = "0" ]; then
# Try to connect
yggdrasilctl addPeer "tcp://[$ipv6]:0" 2>/dev/null && {
logger -t yggdrasil-discovery "Connected to: $hostname ($ipv6)"
} || {
logger -t yggdrasil-discovery "Failed to connect to: $hostname ($ipv6)"
}
fi
fi
fi
return 0
}
# Handle peer departure (when a node goes offline)
handle_peer_departure() {
local data="$1"
local origin="$2"
local ipv6
ipv6=$(echo "$data" | jsonfilter -e '@.ipv6' 2>/dev/null)
[ -z "$ipv6" ] && return 1
remove_peer_from_cache "$ipv6"
logger -t yggdrasil-discovery "Peer departed: $ipv6"
}
# Main handler entry point (called from gossip.sh)
handle() {
local action="$1"
local data="$2"
local origin="$3"
case "$action" in
announce)
handle_peer_announce "$data" "$origin"
;;
departure)
handle_peer_departure "$data" "$origin"
;;
*)
# Default to announce
handle_peer_announce "$data" "$origin"
;;
esac
}
# CLI entry point
case "${1:-}" in
handle)
shift
handle "$@"
;;
*)
# Called with just data (from gossip.sh)
handle "announce" "$1" "$2"
;;
esac