Monitoring page: - Move Current Statistics card above histogram charts - Replace Network Throughput with System Load chart - Fix API field mapping (usage_percent vs percent) - Parse load from cpu.load string format nDPId app: - Add get_detailed_flows and get_categories RPCD methods - Fix subshell variable scope bug in RPCD script - Add interface scanning from /sys/class/net - Update ACL permissions for new methods - Enhance flows.js with Array.isArray data handling Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
162 lines
4.0 KiB
Bash
Executable File
162 lines
4.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# nDPId Flow Actions Handler
|
|
# Processes flow events and updates ipsets/nftables
|
|
# Copyright (C) 2025 CyberMind.fr
|
|
|
|
. /lib/functions.sh
|
|
. /usr/share/ndpid/functions.sh 2>/dev/null || true
|
|
|
|
DISTRIBUTOR_SOCK="/var/run/ndpid/distributor.sock"
|
|
CONFIG_FILE="/etc/config/ndpid"
|
|
|
|
# Load configuration
|
|
load_config() {
|
|
config_load ndpid
|
|
|
|
config_get_bool ACTIONS_ENABLED actions enabled 0
|
|
config_get BITTORRENT_IPSET actions bittorrent_ipset "secubox-bittorrent"
|
|
config_get BITTORRENT_TIMEOUT actions bittorrent_timeout 900
|
|
config_get STREAMING_IPSET actions streaming_ipset "secubox-streaming"
|
|
config_get STREAMING_TIMEOUT actions streaming_timeout 1800
|
|
config_get BLOCKED_IPSET actions blocked_ipset "secubox-blocked"
|
|
config_get BLOCKED_TIMEOUT actions blocked_timeout 3600
|
|
|
|
# Get blocked applications
|
|
BLOCKED_APPS=""
|
|
config_list_foreach actions blocked_app append_blocked_app
|
|
}
|
|
|
|
append_blocked_app() {
|
|
BLOCKED_APPS="$BLOCKED_APPS $1"
|
|
}
|
|
|
|
# Normalize application name from nDPI format
|
|
normalize_app() {
|
|
echo "$1" | tr '.' '\n' | tail -1 | tr '[:upper:]' '[:lower:]'
|
|
}
|
|
|
|
# Check if app is in blocked list
|
|
is_blocked_app() {
|
|
local app="$1"
|
|
for blocked in $BLOCKED_APPS; do
|
|
[ "$app" = "$blocked" ] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Check if app is streaming service
|
|
is_streaming_app() {
|
|
local app="$1"
|
|
case "$app" in
|
|
netflix|youtube|spotify|twitch|disney|amazon_video|hulu|hbo|apple_tv|peacock)
|
|
return 0
|
|
;;
|
|
esac
|
|
return 1
|
|
}
|
|
|
|
# Process a flow detection event
|
|
process_detection() {
|
|
local json="$1"
|
|
|
|
# Extract fields
|
|
local src_ip=$(echo "$json" | jsonfilter -e '@.src_ip' 2>/dev/null)
|
|
local dst_ip=$(echo "$json" | jsonfilter -e '@.dst_ip' 2>/dev/null)
|
|
local ndpi_proto=$(echo "$json" | jsonfilter -e '@.ndpi.proto' 2>/dev/null)
|
|
|
|
[ -z "$ndpi_proto" ] && return
|
|
|
|
local app=$(normalize_app "$ndpi_proto")
|
|
|
|
# BitTorrent detection
|
|
if [ "$app" = "bittorrent" ]; then
|
|
logger -t ndpid-actions "BitTorrent detected: $src_ip -> $dst_ip"
|
|
ipset add "$BITTORRENT_IPSET" "$src_ip" timeout "$BITTORRENT_TIMEOUT" 2>/dev/null
|
|
ipset add "$BITTORRENT_IPSET" "$dst_ip" timeout "$BITTORRENT_TIMEOUT" 2>/dev/null
|
|
fi
|
|
|
|
# Streaming services detection
|
|
if is_streaming_app "$app"; then
|
|
ipset add "$STREAMING_IPSET" "$dst_ip" timeout "$STREAMING_TIMEOUT" 2>/dev/null
|
|
fi
|
|
|
|
# Blocked applications
|
|
if is_blocked_app "$app"; then
|
|
logger -t ndpid-actions "Blocked app detected: $app from $src_ip"
|
|
ipset add "$BLOCKED_IPSET" "$src_ip" timeout "$BLOCKED_TIMEOUT" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
# Main event processing loop
|
|
process_events() {
|
|
while IFS= read -r line; do
|
|
# Strip 5-digit length prefix
|
|
local json="${line:5}"
|
|
|
|
# Get event type
|
|
local event=$(echo "$json" | jsonfilter -e '@.flow_event_name' 2>/dev/null)
|
|
|
|
case "$event" in
|
|
detected|guessed)
|
|
process_detection "$json"
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Create ipsets if they don't exist
|
|
setup_ipsets() {
|
|
ipset list "$BITTORRENT_IPSET" >/dev/null 2>&1 || \
|
|
ipset create "$BITTORRENT_IPSET" hash:ip timeout "$BITTORRENT_TIMEOUT"
|
|
|
|
ipset list "$STREAMING_IPSET" >/dev/null 2>&1 || \
|
|
ipset create "$STREAMING_IPSET" hash:ip timeout "$STREAMING_TIMEOUT"
|
|
|
|
ipset list "$BLOCKED_IPSET" >/dev/null 2>&1 || \
|
|
ipset create "$BLOCKED_IPSET" hash:ip timeout "$BLOCKED_TIMEOUT"
|
|
}
|
|
|
|
# Main
|
|
main() {
|
|
load_config
|
|
|
|
if [ "$ACTIONS_ENABLED" -ne 1 ]; then
|
|
logger -t ndpid-actions "Flow actions disabled in config"
|
|
exit 0
|
|
fi
|
|
|
|
logger -t ndpid-actions "Starting flow actions handler"
|
|
|
|
# Setup ipsets
|
|
setup_ipsets
|
|
|
|
# Wait for socket
|
|
local wait_count=0
|
|
while [ ! -S "$DISTRIBUTOR_SOCK" ] && [ $wait_count -lt 30 ]; do
|
|
sleep 1
|
|
wait_count=$((wait_count + 1))
|
|
done
|
|
|
|
if [ ! -S "$DISTRIBUTOR_SOCK" ]; then
|
|
logger -t ndpid-actions "ERROR: Distributor socket not found"
|
|
exit 1
|
|
fi
|
|
|
|
# Connect and process events
|
|
if command -v socat >/dev/null 2>&1; then
|
|
socat -u UNIX-CONNECT:"$DISTRIBUTOR_SOCK" - | process_events
|
|
else
|
|
nc -U "$DISTRIBUTOR_SOCK" | process_events
|
|
fi
|
|
}
|
|
|
|
case "$1" in
|
|
-d|--daemon)
|
|
main &
|
|
echo $! > /var/run/ndpid-flow-actions.pid
|
|
;;
|
|
*)
|
|
main
|
|
;;
|
|
esac
|