From a8eb8b1271744228607985a0eeb4bfe1b8e7254c Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Tue, 24 Feb 2026 17:20:33 +0100 Subject: [PATCH] feat(p2p-intel): ZKP trust integration and IOC blockchain recording P2P Mesh Intelligence implementation: - Add ZKP trust bonus (+20) for verified peers in IOC validation - Create blockchain.sh for permanent threat_ioc and ioc_feedback blocks - Create feedback.sh for IOC effectiveness tracking and reputation updates - Enhance gossip.sh IOC handler with ZKP-validated trust checks - Add SCORE_IOC_EFFECTIVE (+5) and SCORE_IOC_FALSE_POSITIVE (-8) to reputation - Add zkp_trust_bonus and feedback config options fix(mailserver): Correct vmail UID from 102 to 5000 Dovecot was using wrong UID (102/redis instead of 5000/vmail) causing permission denied errors when accessing mailboxes. Co-Authored-By: Claude Opus 4.5 --- .claude/settings.local.json | 3 +- .../files/usr/lib/mailserver/users.sh | 8 +- .../files/usr/lib/mirrornet/gossip.sh | 51 +++- .../files/usr/lib/mirrornet/reputation.sh | 4 + .../files/etc/config/p2p-intel | 13 + .../files/usr/lib/p2p-intel/blockchain.sh | 175 +++++++++++ .../files/usr/lib/p2p-intel/feedback.sh | 282 ++++++++++++++++++ .../files/usr/lib/p2p-intel/validator.sh | 49 ++- 8 files changed, 567 insertions(+), 18 deletions(-) create mode 100644 package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/blockchain.sh create mode 100644 package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/feedback.sh diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 5693c671..633f98a6 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -431,7 +431,8 @@ "Bash(/tmp/build-zkp-x86.sh:*)", "Bash(__NEW_LINE_a9089175728efc91__ echo \"\")", "WebFetch(domain:pent.gk2.secubox.in)", - "Bash(__NEW_LINE_84a971cd6a876509__ echo \"Done deploying to clone\")" + "Bash(__NEW_LINE_84a971cd6a876509__ echo \"Done deploying to clone\")", + "Bash(# Remove build artifacts from staging git reset HEAD -- package/secubox/zkp-hamiltonian/build-musl/ package/secubox/zkp-hamiltonian/build-static/ package/secubox/zkp-hamiltonian/build-x86/ # Add to gitignore echo \"\"package/secubox/zkp-hamiltonian/build-*/\"\" # Check status git status --short)" ] } } diff --git a/package/secubox/secubox-app-mailserver/files/usr/lib/mailserver/users.sh b/package/secubox/secubox-app-mailserver/files/usr/lib/mailserver/users.sh index c90ea97d..90861a9c 100644 --- a/package/secubox/secubox-app-mailserver/files/usr/lib/mailserver/users.sh +++ b/package/secubox/secubox-app-mailserver/files/usr/lib/mailserver/users.sh @@ -54,9 +54,9 @@ user_add() { mv "${passfile}.tmp" "$passfile" # Sync to Dovecot inside container - # Use correct uid:gid for vmail user (102:105) and proper mail path with userdb_mail + # Use correct uid:gid for vmail user (5000:5000) and proper mail path with userdb_mail local mail_path="/var/mail/$domain/$user" - local dovecot_entry="$email:$hash:102:105::$mail_path::userdb_mail=maildir:$mail_path" + local dovecot_entry="$email:$hash:5000:5000::$mail_path::userdb_mail=maildir:$mail_path" # Write to temp file first to avoid shell expansion issues with $6$ in hash local tmpfile="/tmp/dovecot_entry_$$" @@ -139,14 +139,14 @@ user_passwd() { sed -i "s|^$email:.*|$email:$hash|" "$passfile" # Sync to Dovecot inside container - # Use correct uid:gid for vmail user (102:105) and proper mail path with userdb_mail + # Use correct uid:gid for vmail user (5000:5000) and proper mail path with userdb_mail local user=$(echo "$email" | cut -d@ -f1) local domain=$(echo "$email" | cut -d@ -f2) local mail_path="/var/mail/$domain/$user" # Build dovecot entry with proper format: # user:password:uid:gid:gecos:home:shell:userdb_mail=maildir:/path - local dovecot_entry="$email:$hash:102:105::$mail_path::userdb_mail=maildir:$mail_path" + local dovecot_entry="$email:$hash:5000:5000::$mail_path::userdb_mail=maildir:$mail_path" # Write to temp file first to avoid shell expansion issues with $6$ in hash local tmpfile="/tmp/dovecot_entry_$$" diff --git a/package/secubox/secubox-mirrornet/files/usr/lib/mirrornet/gossip.sh b/package/secubox/secubox-mirrornet/files/usr/lib/mirrornet/gossip.sh index 8e2bb345..d0d5f1d8 100644 --- a/package/secubox/secubox-mirrornet/files/usr/lib/mirrornet/gossip.sh +++ b/package/secubox/secubox-mirrornet/files/usr/lib/mirrornet/gossip.sh @@ -206,12 +206,51 @@ gossip_receive() { # Process by type case "$type" in ioc) - # Threat intelligence update - if [ -f /usr/lib/secubox/threat-intel.sh ]; then - . /usr/lib/secubox/threat-intel.sh - local ioc_data - ioc_data=$(echo "$message" | jsonfilter -e '@.data') - threat_intel_receive "$ioc_data" "$origin" + # Threat intelligence update - bridge to p2p-intel with ZKP trust + local ioc_data + ioc_data=$(echo "$message" | jsonfilter -e '@.data') + + if [ -f /usr/lib/p2p-intel/validator.sh ]; then + . /usr/lib/p2p-intel/validator.sh + + # Validate IOC with ZKP-enhanced trust + if _is_source_trusted "$origin"; then + # Update reputation for valid IOC + if [ -f /usr/lib/mirrornet/reputation.sh ]; then + . /usr/lib/mirrornet/reputation.sh + reputation_valid_ioc "$origin" + fi + + # Queue for application + if [ -f /usr/lib/p2p-intel/applier.sh ]; then + . /usr/lib/p2p-intel/applier.sh + queue_pending "$ioc_data" "$origin" + fi + + # Track IOC source for feedback attribution + if [ -f /usr/lib/p2p-intel/feedback.sh ]; then + . /usr/lib/p2p-intel/feedback.sh + local ioc_value ioc_type + ioc_value=$(echo "$ioc_data" | jsonfilter -e '@.value' 2>/dev/null) + ioc_type=$(echo "$ioc_data" | jsonfilter -e '@.type' 2>/dev/null) + [ -n "$ioc_value" ] && feedback_track_ioc "$ioc_value" "$ioc_type" "$origin" + fi + + logger -t mirrornet "Gossip: valid IOC from ZKP-trusted $origin" + else + # Untrusted source + if [ -f /usr/lib/mirrornet/reputation.sh ]; then + . /usr/lib/mirrornet/reputation.sh + reputation_invalid_ioc "$origin" + fi + logger -t mirrornet "Gossip: rejected IOC from untrusted $origin" + fi + else + # Fallback to legacy threat-intel.sh + if [ -f /usr/lib/secubox/threat-intel.sh ]; then + . /usr/lib/secubox/threat-intel.sh + threat_intel_receive "$ioc_data" "$origin" + fi fi ;; peer_status) diff --git a/package/secubox/secubox-mirrornet/files/usr/lib/mirrornet/reputation.sh b/package/secubox/secubox-mirrornet/files/usr/lib/mirrornet/reputation.sh index c87d8a57..3a7fdef1 100644 --- a/package/secubox/secubox-mirrornet/files/usr/lib/mirrornet/reputation.sh +++ b/package/secubox/secubox-mirrornet/files/usr/lib/mirrornet/reputation.sh @@ -22,6 +22,10 @@ SCORE_VALID_BLOCK=2 SCORE_INVALID_BLOCK=-15 SCORE_SPAM=-20 +# IOC effectiveness feedback scores +SCORE_IOC_EFFECTIVE=5 +SCORE_IOC_FALSE_POSITIVE=-8 + # Initialize reputation storage reputation_init() { mkdir -p "$REPUTATION_DIR" diff --git a/package/secubox/secubox-p2p-intel/files/etc/config/p2p-intel b/package/secubox/secubox-p2p-intel/files/etc/config/p2p-intel index f00c9517..73bad506 100644 --- a/package/secubox/secubox-p2p-intel/files/etc/config/p2p-intel +++ b/package/secubox/secubox-p2p-intel/files/etc/config/p2p-intel @@ -17,6 +17,10 @@ config validation 'validation' option require_signature '1' option min_source_trust '40' # Minimum trust score to accept IOCs + option zkp_trust_bonus '20' + # Extra trust for ZKP-verified peers + option zkp_require_for_critical '1' + # Require ZKP verification for critical severity IOCs option verify_transitive '1' # Verify IOCs from peers-of-peers option max_age_hours '168' @@ -38,3 +42,12 @@ config application 'application' # 24 hours default option whitelist_local '1' # Never block local subnets + +config feedback 'feedback' + option enabled '1' + option track_effectiveness '1' + # Track if IOCs actually blocked attacks + option reputation_update '1' + # Update peer reputation on feedback (+5/-8) + option blockchain_record '1' + # Record feedback to blockchain audit trail diff --git a/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/blockchain.sh b/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/blockchain.sh new file mode 100644 index 00000000..e6cd624c --- /dev/null +++ b/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/blockchain.sh @@ -0,0 +1,175 @@ +#!/bin/sh +# P2P Intel Blockchain - Permanent IOC recording on mesh blockchain +# Records threat_ioc and ioc_feedback blocks for audit trail + +. /usr/lib/secubox/p2p-mesh.sh 2>/dev/null + +CHAIN_FILE="/srv/secubox/mesh/chain.json" +INTEL_DIR="/var/lib/p2p-intel" +PROCESSED_BLOCKS="$INTEL_DIR/processed-blocks.list" + +# Initialize blockchain integration +blockchain_init() { + mkdir -p "$INTEL_DIR" + [ -f "$PROCESSED_BLOCKS" ] || touch "$PROCESSED_BLOCKS" +} + +# Record IOC batch to blockchain +# Usage: blockchain_record_iocs '' '' +blockchain_record_iocs() { + local iocs_json="$1" + local source_did="$2" + + [ -z "$iocs_json" ] && return 1 + [ "$iocs_json" = "[]" ] && return 0 + + local timestamp=$(date +%s) + local node_id=$(cat /srv/secubox/mesh/node.id 2>/dev/null || echo "unknown") + local ioc_count=$(echo "$iocs_json" | jsonfilter -e '@[*]' 2>/dev/null | wc -l) + + [ "$ioc_count" -eq 0 ] && return 0 + + # Build block data + local block_data="{\"version\":1,\"source\":\"$source_did\",\"count\":$ioc_count,\"iocs\":$iocs_json}" + local block_hash=$(echo "${block_data}${timestamp}${node_id}" | sha256sum | cut -d' ' -f1) + + # Add to blockchain + if type chain_add_block >/dev/null 2>&1; then + chain_add_block "threat_ioc" "$block_data" "$block_hash" + logger -t p2p-intel "Recorded $ioc_count IOCs to blockchain (hash: ${block_hash:0:16})" + echo "$block_hash" + return 0 + else + logger -t p2p-intel "Warning: chain_add_block not available" + return 1 + fi +} + +# Scan chain for unprocessed threat_ioc blocks from other nodes +# Returns: IOCs as JSON lines (one per line) +blockchain_scan_iocs() { + [ -f "$CHAIN_FILE" ] || return 0 + [ -f "$PROCESSED_BLOCKS" ] || touch "$PROCESSED_BLOCKS" + + local my_node=$(cat /srv/secubox/mesh/node.id 2>/dev/null) + + jsonfilter -i "$CHAIN_FILE" -e '@.blocks[*]' 2>/dev/null | while read -r block; do + local btype=$(echo "$block" | jsonfilter -e '@.type' 2>/dev/null) + [ "$btype" = "threat_ioc" ] || continue + + local bhash=$(echo "$block" | jsonfilter -e '@.hash' 2>/dev/null) + local bnode=$(echo "$block" | jsonfilter -e '@.node' 2>/dev/null) + + # Skip own blocks + [ "$bnode" = "$my_node" ] && continue + + # Skip already processed + grep -q "$bhash" "$PROCESSED_BLOCKS" 2>/dev/null && continue + + # Extract source for trust checking + local source=$(echo "$block" | jsonfilter -e '@.data.source' 2>/dev/null) + + # Output each IOC with source attribution + echo "$block" | jsonfilter -e '@.data.iocs[*]' 2>/dev/null | while read -r ioc; do + # Add source_node to IOC for trust tracking + echo "$ioc" | sed "s/}$/,\"source_node\":\"$source\"}/g" + done + + # Mark as processed + echo "$bhash" >> "$PROCESSED_BLOCKS" + done +} + +# Count unprocessed threat_ioc blocks +blockchain_pending_count() { + [ -f "$CHAIN_FILE" ] || { echo "0"; return; } + [ -f "$PROCESSED_BLOCKS" ] || touch "$PROCESSED_BLOCKS" + + local my_node=$(cat /srv/secubox/mesh/node.id 2>/dev/null) + local count=0 + + jsonfilter -i "$CHAIN_FILE" -e '@.blocks[*]' 2>/dev/null | while read -r block; do + local btype=$(echo "$block" | jsonfilter -e '@.type' 2>/dev/null) + [ "$btype" = "threat_ioc" ] || continue + + local bhash=$(echo "$block" | jsonfilter -e '@.hash' 2>/dev/null) + local bnode=$(echo "$block" | jsonfilter -e '@.node' 2>/dev/null) + + [ "$bnode" = "$my_node" ] && continue + grep -q "$bhash" "$PROCESSED_BLOCKS" 2>/dev/null && continue + + count=$((count + 1)) + done + + echo "$count" +} + +# Record IOC feedback to chain (effectiveness tracking) +# Usage: blockchain_record_feedback '' '' '
' +# feedback_type: "effective" or "false_positive" +blockchain_record_feedback() { + local ioc_hash="$1" + local feedback_type="$2" + local details="${3:-}" + + [ -z "$ioc_hash" ] || [ -z "$feedback_type" ] && return 1 + + local timestamp=$(date +%s) + local node_id=$(cat /srv/secubox/mesh/node.id 2>/dev/null || echo "unknown") + + local block_data="{\"ioc_hash\":\"$ioc_hash\",\"feedback\":\"$feedback_type\",\"reporter\":\"$node_id\",\"details\":\"$details\",\"ts\":$timestamp}" + local block_hash=$(echo "${block_data}${timestamp}" | sha256sum | cut -d' ' -f1) + + if type chain_add_block >/dev/null 2>&1; then + chain_add_block "ioc_feedback" "$block_data" "$block_hash" + logger -t p2p-intel "Recorded IOC feedback: $ioc_hash -> $feedback_type" + echo "$block_hash" + return 0 + else + logger -t p2p-intel "Warning: chain_add_block not available" + return 1 + fi +} + +# Get feedback statistics from blockchain +blockchain_feedback_stats() { + [ -f "$CHAIN_FILE" ] || { echo '{"effective":0,"false_positive":0}'; return; } + + local effective=0 + local false_positive=0 + + jsonfilter -i "$CHAIN_FILE" -e '@.blocks[*]' 2>/dev/null | while read -r block; do + local btype=$(echo "$block" | jsonfilter -e '@.type' 2>/dev/null) + [ "$btype" = "ioc_feedback" ] || continue + + local feedback=$(echo "$block" | jsonfilter -e '@.data.feedback' 2>/dev/null) + case "$feedback" in + effective) effective=$((effective + 1)) ;; + false_positive) false_positive=$((false_positive + 1)) ;; + esac + done + + echo "{\"effective\":$effective,\"false_positive\":$false_positive}" +} + +# Get threat_ioc block count +blockchain_ioc_block_count() { + [ -f "$CHAIN_FILE" ] || { echo "0"; return; } + + jsonfilter -i "$CHAIN_FILE" -e '@.blocks[*].type' 2>/dev/null | grep -c "threat_ioc" || echo "0" +} + +# Clean old processed blocks list (keep last 1000) +blockchain_cleanup() { + [ -f "$PROCESSED_BLOCKS" ] || return 0 + + local lines=$(wc -l < "$PROCESSED_BLOCKS") + if [ "$lines" -gt 1000 ]; then + tail -n 1000 "$PROCESSED_BLOCKS" > "$PROCESSED_BLOCKS.tmp" + mv "$PROCESSED_BLOCKS.tmp" "$PROCESSED_BLOCKS" + logger -t p2p-intel "Cleaned processed blocks list (kept last 1000)" + fi +} + +# Initialize on source +blockchain_init diff --git a/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/feedback.sh b/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/feedback.sh new file mode 100644 index 00000000..808b3ed4 --- /dev/null +++ b/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/feedback.sh @@ -0,0 +1,282 @@ +#!/bin/sh +# P2P Intel Feedback - Track IOC effectiveness and update peer reputation +# Records effectiveness tracking for audit trail and reputation updates + +. /usr/lib/p2p-intel/blockchain.sh 2>/dev/null + +FEEDBACK_DIR="/var/lib/p2p-intel/feedback" +EFFECTIVENESS_LOG="$FEEDBACK_DIR/effectiveness.json" +IOC_TRACKING_FILE="$FEEDBACK_DIR/ioc-tracking.json" + +# Reputation score adjustments for IOC feedback +SCORE_IOC_EFFECTIVE=5 +SCORE_IOC_FALSE_POSITIVE=-8 + +# Initialize feedback storage +feedback_init() { + mkdir -p "$FEEDBACK_DIR" + [ -f "$EFFECTIVENESS_LOG" ] || echo '[]' > "$EFFECTIVENESS_LOG" + [ -f "$IOC_TRACKING_FILE" ] || echo '{}' > "$IOC_TRACKING_FILE" +} + +# Generate IOC hash for tracking +_ioc_hash() { + local ioc_value="$1" + echo "$ioc_value" | sha256sum | cut -c1-16 +} + +# Track IOC source for later feedback attribution +feedback_track_ioc() { + local ioc_value="$1" + local ioc_type="$2" + local source_node="$3" + local timestamp + timestamp=$(date +%s) + + local ioc_hash + ioc_hash=$(_ioc_hash "$ioc_value") + + local entry="{\"hash\":\"$ioc_hash\",\"value\":\"$ioc_value\",\"type\":\"$ioc_type\",\"source\":\"$source_node\",\"received_at\":$timestamp}" + + local tmp_file="/tmp/ioc_tracking_$$.json" + + if [ -s "$IOC_TRACKING_FILE" ] && [ "$(cat "$IOC_TRACKING_FILE")" != "{}" ]; then + # Add or update entry + if grep -q "\"$ioc_hash\"" "$IOC_TRACKING_FILE"; then + # Already tracked + return 0 + fi + # Add new entry + sed "s/^{/{\"$ioc_hash\":$entry,/" "$IOC_TRACKING_FILE" > "$tmp_file" + else + echo "{\"$ioc_hash\":$entry}" > "$tmp_file" + fi + + mv "$tmp_file" "$IOC_TRACKING_FILE" +} + +# Get source node for an IOC +_get_ioc_source() { + local ioc_value="$1" + local ioc_hash + ioc_hash=$(_ioc_hash "$ioc_value") + + jsonfilter -i "$IOC_TRACKING_FILE" -e "@[\"$ioc_hash\"].source" 2>/dev/null +} + +# Record effective IOC (blocked an attack) +# Usage: feedback_ioc_effective '' [source_node] +feedback_ioc_effective() { + local ioc_value="$1" + local source_node="${2:-}" + local timestamp + timestamp=$(date +%s) + + # Get source from tracking if not provided + if [ -z "$source_node" ]; then + source_node=$(_get_ioc_source "$ioc_value") + fi + + [ -z "$source_node" ] && { + logger -t p2p-intel "Warning: Cannot attribute effectiveness - no source for $ioc_value" + return 1 + } + + local ioc_hash + ioc_hash=$(_ioc_hash "$ioc_value") + + # Record to blockchain for permanent audit trail + if type blockchain_record_feedback >/dev/null 2>&1; then + blockchain_record_feedback "$ioc_hash" "effective" "blocked_attack" + fi + + # Log locally + local entry="{\"type\":\"effective\",\"ioc_hash\":\"$ioc_hash\",\"ioc_value\":\"$ioc_value\",\"source\":\"$source_node\",\"timestamp\":$timestamp}" + _append_effectiveness "$entry" + + # Update peer reputation (+5) + if [ -f /usr/lib/mirrornet/reputation.sh ]; then + . /usr/lib/mirrornet/reputation.sh + reputation_adjust "$source_node" "$SCORE_IOC_EFFECTIVE" "ioc_effective" + fi + + logger -t p2p-intel "IOC effective: $ioc_value from $source_node (+$SCORE_IOC_EFFECTIVE rep)" +} + +# Mark IOC as false positive +# Usage: feedback_false_positive '' [source_node] [reason] +feedback_false_positive() { + local ioc_value="$1" + local source_node="${2:-}" + local reason="${3:-manual_override}" + local timestamp + timestamp=$(date +%s) + + # Get source from tracking if not provided + if [ -z "$source_node" ]; then + source_node=$(_get_ioc_source "$ioc_value") + fi + + [ -z "$source_node" ] && { + logger -t p2p-intel "Warning: Cannot attribute false positive - no source for $ioc_value" + return 1 + } + + local ioc_hash + ioc_hash=$(_ioc_hash "$ioc_value") + + # Record to blockchain for permanent audit trail + if type blockchain_record_feedback >/dev/null 2>&1; then + blockchain_record_feedback "$ioc_hash" "false_positive" "$reason" + fi + + # Log locally + local entry="{\"type\":\"false_positive\",\"ioc_hash\":\"$ioc_hash\",\"ioc_value\":\"$ioc_value\",\"source\":\"$source_node\",\"reason\":\"$reason\",\"timestamp\":$timestamp}" + _append_effectiveness "$entry" + + # Update peer reputation (-8) + if [ -f /usr/lib/mirrornet/reputation.sh ]; then + . /usr/lib/mirrornet/reputation.sh + reputation_adjust "$source_node" "$SCORE_IOC_FALSE_POSITIVE" "ioc_false_positive" + fi + + logger -t p2p-intel "IOC false positive: $ioc_value from $source_node ($SCORE_IOC_FALSE_POSITIVE rep) - $reason" +} + +# Append to effectiveness log +_append_effectiveness() { + local entry="$1" + local tmp_file="/tmp/effectiveness_$$.json" + + if [ -s "$EFFECTIVENESS_LOG" ] && [ "$(cat "$EFFECTIVENESS_LOG")" != "[]" ]; then + sed 's/]$//' "$EFFECTIVENESS_LOG" > "$tmp_file" + echo ",$entry]" >> "$tmp_file" + else + echo "[$entry]" > "$tmp_file" + fi + + mv "$tmp_file" "$EFFECTIVENESS_LOG" +} + +# Get effectiveness stats for a peer +feedback_peer_stats() { + local peer_id="$1" + + [ -f "$EFFECTIVENESS_LOG" ] || { echo '{"effective":0,"false_positive":0,"ratio":0}'; return; } + + local effective=0 + local false_positive=0 + + # Count from effectiveness log + effective=$(grep -c "\"source\":\"$peer_id\".*\"type\":\"effective\"" "$EFFECTIVENESS_LOG" 2>/dev/null || echo 0) + false_positive=$(grep -c "\"source\":\"$peer_id\".*\"type\":\"false_positive\"" "$EFFECTIVENESS_LOG" 2>/dev/null || echo 0) + + # Calculate ratio (effectiveness percentage) + local total=$((effective + false_positive)) + local ratio=0 + if [ "$total" -gt 0 ]; then + ratio=$((effective * 100 / total)) + fi + + echo "{\"effective\":$effective,\"false_positive\":$false_positive,\"total\":$total,\"ratio\":$ratio}" +} + +# Get global effectiveness stats +feedback_global_stats() { + [ -f "$EFFECTIVENESS_LOG" ] || { echo '{"effective":0,"false_positive":0,"total":0}'; return; } + + local effective=0 + local false_positive=0 + + effective=$(grep -c '"type":"effective"' "$EFFECTIVENESS_LOG" 2>/dev/null || echo 0) + false_positive=$(grep -c '"type":"false_positive"' "$EFFECTIVENESS_LOG" 2>/dev/null || echo 0) + + local total=$((effective + false_positive)) + + echo "{\"effective\":$effective,\"false_positive\":$false_positive,\"total\":$total}" +} + +# Get recent feedback events +feedback_recent() { + local count="${1:-20}" + + [ -f "$EFFECTIVENESS_LOG" ] || { echo '[]'; return; } + + # Get last N entries (simple tail approximation) + local total + total=$(grep -c '"type":' "$EFFECTIVENESS_LOG" 2>/dev/null || echo 0) + + if [ "$total" -le "$count" ]; then + cat "$EFFECTIVENESS_LOG" + else + # Return last N entries using jsonfilter + jsonfilter -i "$EFFECTIVENESS_LOG" -e "@[-$count:]" 2>/dev/null || cat "$EFFECTIVENESS_LOG" + fi +} + +# Check if peer has poor effectiveness (for trust decisions) +feedback_peer_reliability() { + local peer_id="$1" + local min_samples="${2:-5}" + local min_ratio="${3:-60}" + + local stats + stats=$(feedback_peer_stats "$peer_id") + + local total ratio + total=$(echo "$stats" | jsonfilter -e '@.total' 2>/dev/null || echo 0) + ratio=$(echo "$stats" | jsonfilter -e '@.ratio' 2>/dev/null || echo 100) + + # Not enough samples = assume good + if [ "$total" -lt "$min_samples" ]; then + echo "unknown" + return 0 + fi + + if [ "$ratio" -ge "$min_ratio" ]; then + echo "reliable" + return 0 + else + echo "unreliable" + return 1 + fi +} + +# Cleanup old tracking data +feedback_cleanup() { + local max_entries="${1:-10000}" + local max_age_days="${2:-30}" + + # Clean effectiveness log if too large + if [ -f "$EFFECTIVENESS_LOG" ]; then + local count + count=$(grep -c '"type":' "$EFFECTIVENESS_LOG" 2>/dev/null || echo 0) + + if [ "$count" -gt "$max_entries" ]; then + local keep=$((max_entries / 2)) + local tmp_file="/tmp/effectiveness_$$.json" + jsonfilter -i "$EFFECTIVENESS_LOG" -e "@[-$keep:]" > "$tmp_file" 2>/dev/null || echo "[]" > "$tmp_file" + mv "$tmp_file" "$EFFECTIVENESS_LOG" + logger -t p2p-intel "Cleaned effectiveness log (kept last $keep entries)" + fi + fi + + # Clean IOC tracking (remove entries older than max_age_days) + if [ -f "$IOC_TRACKING_FILE" ]; then + local current_time cutoff_time + current_time=$(date +%s) + cutoff_time=$((current_time - max_age_days * 86400)) + + # Simple size-based cleanup for now + local file_size + file_size=$(stat -f%z "$IOC_TRACKING_FILE" 2>/dev/null || stat -c%s "$IOC_TRACKING_FILE" 2>/dev/null || echo 0) + + if [ "$file_size" -gt 1048576 ]; then # 1MB + echo '{}' > "$IOC_TRACKING_FILE" + logger -t p2p-intel "Reset IOC tracking file (size limit)" + fi + fi +} + +# Initialize on source +feedback_init diff --git a/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/validator.sh b/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/validator.sh index 4d2c5a68..7b3a34e1 100644 --- a/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/validator.sh +++ b/package/secubox/secubox-p2p-intel/files/usr/lib/p2p-intel/validator.sh @@ -27,21 +27,56 @@ _is_too_old() { [ "$age" -gt "$max_age_seconds" ] } -# Check if source is trusted +# Check if peer has ZKP verification on blockchain +_check_zkp_verified() { + local peer_id="$1" + local chain_file="/srv/secubox/mesh/chain.json" + + [ -f "$chain_file" ] || { echo "0"; return 1; } + + # Search for peer_zkp_verified block with matching peer_fp + local found=0 + jsonfilter -i "$chain_file" -e '@.blocks[*]' 2>/dev/null | while read -r block; do + local btype=$(echo "$block" | jsonfilter -e '@.type' 2>/dev/null) + [ "$btype" = "peer_zkp_verified" ] || continue + + local peer_fp=$(echo "$block" | jsonfilter -e '@.data.peer_fp' 2>/dev/null) + local result=$(echo "$block" | jsonfilter -e '@.data.result' 2>/dev/null) + + # Match peer_id (could be ZKP fingerprint or node ID) + if [ "$peer_fp" = "$peer_id" ] && [ "$result" = "ACCEPT" ]; then + echo "1" + return 0 + fi + done + + echo "0" +} + +# Check if source is trusted (with ZKP bonus) _is_source_trusted() { local source_did="$1" local min_trust min_trust=$(uci -q get p2p-intel.validation.min_source_trust || echo "40") + local zkp_bonus + zkp_bonus=$(uci -q get p2p-intel.validation.zkp_trust_bonus || echo "20") + local base_score=50 # Default for new/unknown peers + + # Get score from identity trust system if available if [ -f /usr/lib/secubox-identity/trust.sh ]; then . /usr/lib/secubox-identity/trust.sh - local score - score=$(trust_get_score "$source_did") - [ "$score" -ge "$min_trust" ] - else - # No trust system, accept all - return 0 + base_score=$(trust_get_score "$source_did" 2>/dev/null || echo "50") fi + + # Add ZKP bonus if peer is ZKP-verified on blockchain + local zkp_verified=$(_check_zkp_verified "$source_did") + if [ "$zkp_verified" = "1" ]; then + base_score=$((base_score + zkp_bonus)) + logger -t p2p-intel "ZKP trust bonus applied for $source_did (score: $base_score)" + fi + + [ "$base_score" -ge "$min_trust" ] } # Check if IP is in local subnet (whitelist)