secubox-openwrt/package/secubox/secubox-dpi-dual/files/usr/sbin/dpi-flow-collector
CyberMind-FR 58a51eb271 feat(dpi): Implement Phase 1 of Dual-Stream DPI architecture
- secubox-dpi-dual package with parallel MITM + Passive TAP analysis
- TAP stream: tc mirred port mirroring to dummy interface for netifyd
- Flow collector: Stats aggregation from netifyd, cleanup, JSON output
- Correlation engine: Matches MITM WAF events with TAP flow data
- Watches CrowdSec decisions and WAF alerts for threat enrichment
- CLI: dpi-dualctl with start/stop/status/flows/threats/mirror commands
- Procd service: manages flow-collector + correlator instances
- MITM double buffer: dpi_buffer.py mitmproxy addon (Phase 2 prep)
- UCI config: dual/mitm-only/tap-only mode selection

Architecture: package/secubox/DUAL-STREAM-DPI.md

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

112 lines
2.8 KiB
Bash

#!/bin/sh
# DPI Flow Collector - Aggregates netifyd flow statistics
# Part of secubox-dpi-dual package
. /lib/functions.sh
config_load dpi-dual
FLOW_DIR=""
STATS_DIR=""
RETENTION=""
load_config() {
config_get FLOW_DIR settings flow_dir "/tmp/dpi-flows"
config_get STATS_DIR settings stats_dir "/tmp/secubox"
config_get RETENTION tap flow_retention "300"
}
init_dirs() {
mkdir -p "$FLOW_DIR"
mkdir -p "$STATS_DIR"
}
collect_flows() {
local stats_file="$STATS_DIR/dpi-flows.json"
local netifyd_socket="/var/run/netifyd/netifyd.sock"
# Count recent flow files
local total_flows=0
if [ -d "$FLOW_DIR" ]; then
total_flows=$(find "$FLOW_DIR" -name "*.json" -mmin -1 2>/dev/null | wc -l)
fi
# Get protocol distribution from netifyd status
local protocols="{}"
if [ -S "$netifyd_socket" ]; then
# Try to get stats from netifyd socket
local proto_data
proto_data=$(echo '{"type":"get_stats"}' | nc -U "$netifyd_socket" 2>/dev/null | head -1)
if [ -n "$proto_data" ]; then
protocols=$(echo "$proto_data" | jsonfilter -e '@.protocols' 2>/dev/null || echo '{}')
fi
fi
# Get interface stats from /proc
local tap_if
config_get tap_if tap interface "tap0"
local rx_bytes=0 tx_bytes=0 rx_packets=0 tx_packets=0
if [ -d "/sys/class/net/$tap_if/statistics" ]; then
rx_bytes=$(cat "/sys/class/net/$tap_if/statistics/rx_bytes" 2>/dev/null || echo 0)
tx_bytes=$(cat "/sys/class/net/$tap_if/statistics/tx_bytes" 2>/dev/null || echo 0)
rx_packets=$(cat "/sys/class/net/$tap_if/statistics/rx_packets" 2>/dev/null || echo 0)
tx_packets=$(cat "/sys/class/net/$tap_if/statistics/tx_packets" 2>/dev/null || echo 0)
fi
# Write stats JSON
cat > "$stats_file" << EOF
{
"timestamp": "$(date -Iseconds)",
"flows_1min": $total_flows,
"tap_interface": "$tap_if",
"rx_bytes": $rx_bytes,
"tx_bytes": $tx_bytes,
"rx_packets": $rx_packets,
"tx_packets": $tx_packets,
"protocols": $protocols,
"mode": "passive_tap"
}
EOF
}
cleanup_old_flows() {
# Remove flow files older than retention period
local retention_min=$((RETENTION / 60))
[ "$retention_min" -lt 1 ] && retention_min=1
find "$FLOW_DIR" -name "*.json" -mmin +"$retention_min" -delete 2>/dev/null
}
run_collector() {
load_config
init_dirs
echo "DPI Flow Collector started"
echo " Flow dir: $FLOW_DIR"
echo " Stats dir: $STATS_DIR"
echo " Retention: ${RETENTION}s"
while true; do
collect_flows
cleanup_old_flows
sleep 10
done
}
case "$1" in
start)
run_collector
;;
once)
load_config
init_dirs
collect_flows
cleanup_old_flows
;;
*)
echo "Usage: $0 {start|once}"
exit 1
;;
esac