Phase 1 implementation of Vortex DNS Firewall - SecuBox's first line of defense blocking threats at DNS level BEFORE any connection is established. Features: - Threat intel aggregator (URLhaus, OpenPhish, Malware Domains) - SQLite-based blocklist database with domain deduplication - dnsmasq integration via sinkhole hosts file - x47 vitality multiplier concept (each DNS block prevents ~47 connections) - RPCD handler for LuCI integration with 8 methods - CLI tool: vortex-firewall intel/stats/start/stop Tested with 765 blocked domains across 3 threat feeds. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
571 lines
18 KiB
Bash
Executable File
571 lines
18 KiB
Bash
Executable File
#!/bin/sh
|
||
#
|
||
# vortex-firewall - DNS-level threat blocking with ×47 impact
|
||
#
|
||
# Block threats at DNS resolution BEFORE any connection is established.
|
||
# Each DNS block prevents ~47 malicious connections (C2 beacon rate × window).
|
||
#
|
||
# Usage:
|
||
# vortex-firewall intel <command> Threat intelligence management
|
||
# vortex-firewall stats Show blocking statistics
|
||
# vortex-firewall sinkhole <command> Sinkhole server management
|
||
# vortex-firewall mesh <command> Mesh threat sharing
|
||
# vortex-firewall start|stop|status Service control
|
||
#
|
||
|
||
VERSION="1.0.0"
|
||
NAME="vortex-firewall"
|
||
|
||
# Directories
|
||
VAR_DIR="/var/lib/vortex-firewall"
|
||
CACHE_DIR="/tmp/vortex-firewall"
|
||
FEEDS_DIR="$VAR_DIR/feeds"
|
||
BLOCKLIST_DB="$VAR_DIR/blocklist.db"
|
||
BLOCKLIST_HOSTS="$VAR_DIR/sinkhole.hosts"
|
||
DNSMASQ_CONF="/etc/dnsmasq.d/vortex-firewall.conf"
|
||
STATS_FILE="$VAR_DIR/stats.json"
|
||
CONFIG_FILE="/etc/config/vortex-firewall"
|
||
|
||
# Sinkhole IP (internal, not routed)
|
||
SINKHOLE_IP="192.168.255.253"
|
||
|
||
# Feed URLs
|
||
FEED_URLHAUS="https://urlhaus.abuse.ch/downloads/hostfile/"
|
||
FEED_FEODO="https://feodotracker.abuse.ch/downloads/ipblocklist.txt"
|
||
FEED_PHISHTANK="http://data.phishtank.com/data/online-valid.csv"
|
||
FEED_OPENPHISH="https://openphish.com/feed.txt"
|
||
FEED_MALWAREDOMAINS="https://mirror1.malwaredomains.com/files/justdomains"
|
||
|
||
# Colors
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
CYAN='\033[0;36m'
|
||
BOLD='\033[1m'
|
||
NC='\033[0m'
|
||
|
||
log() { echo -e "${GREEN}[VORTEX]${NC} $1"; }
|
||
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||
error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
|
||
|
||
# ============================================================================
|
||
# Initialization
|
||
# ============================================================================
|
||
|
||
init_dirs() {
|
||
mkdir -p "$VAR_DIR" "$CACHE_DIR" "$FEEDS_DIR"
|
||
[ -f "$STATS_FILE" ] || echo '{"blocks":0,"queries":0,"domains":0,"last_update":""}' > "$STATS_FILE"
|
||
}
|
||
|
||
init_db() {
|
||
if [ ! -f "$BLOCKLIST_DB" ]; then
|
||
log "Initializing blocklist database..."
|
||
sqlite3 "$BLOCKLIST_DB" <<EOF
|
||
CREATE TABLE IF NOT EXISTS domains (
|
||
domain TEXT PRIMARY KEY,
|
||
threat_type TEXT,
|
||
confidence INTEGER DEFAULT 80,
|
||
source TEXT,
|
||
first_seen TEXT,
|
||
last_seen TEXT,
|
||
hit_count INTEGER DEFAULT 0,
|
||
blocked INTEGER DEFAULT 1
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS feeds (
|
||
name TEXT PRIMARY KEY,
|
||
url TEXT,
|
||
last_update TEXT,
|
||
domain_count INTEGER DEFAULT 0,
|
||
enabled INTEGER DEFAULT 1
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS events (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
timestamp TEXT,
|
||
domain TEXT,
|
||
client_ip TEXT,
|
||
event_type TEXT,
|
||
details TEXT
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_domain ON domains(domain);
|
||
CREATE INDEX IF NOT EXISTS idx_threat ON domains(threat_type);
|
||
CREATE INDEX IF NOT EXISTS idx_events_ts ON events(timestamp);
|
||
EOF
|
||
log "Database initialized: $BLOCKLIST_DB"
|
||
fi
|
||
}
|
||
|
||
# ============================================================================
|
||
# Feed Management
|
||
# ============================================================================
|
||
|
||
feed_update_urlhaus() {
|
||
local feed_file="$FEEDS_DIR/urlhaus.txt"
|
||
log "Updating URLhaus feed..."
|
||
|
||
if curl -sL --connect-timeout 10 --max-time 60 "$FEED_URLHAUS" -o "$feed_file.tmp" 2>/dev/null; then
|
||
# Extract domains from hosts file format (127.0.0.1 domain)
|
||
grep -v '^#' "$feed_file.tmp" 2>/dev/null | awk '{print $2}' | grep -v '^$' | sort -u > "$feed_file"
|
||
local count=$(wc -l < "$feed_file")
|
||
rm -f "$feed_file.tmp"
|
||
|
||
sqlite3 "$BLOCKLIST_DB" "INSERT OR REPLACE INTO feeds VALUES ('urlhaus', '$FEED_URLHAUS', datetime('now'), $count, 1);"
|
||
log "URLhaus: $count domains"
|
||
return 0
|
||
else
|
||
warn "Failed to update URLhaus feed"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
feed_update_openphish() {
|
||
local feed_file="$FEEDS_DIR/openphish.txt"
|
||
log "Updating OpenPhish feed..."
|
||
|
||
if curl -sL --connect-timeout 10 --max-time 30 "$FEED_OPENPHISH" -o "$feed_file.tmp" 2>/dev/null; then
|
||
# Extract domains from URLs
|
||
grep -v '^#' "$feed_file.tmp" 2>/dev/null | sed 's|https\?://||' | cut -d'/' -f1 | sort -u > "$feed_file"
|
||
local count=$(wc -l < "$feed_file")
|
||
rm -f "$feed_file.tmp"
|
||
|
||
sqlite3 "$BLOCKLIST_DB" "INSERT OR REPLACE INTO feeds VALUES ('openphish', '$FEED_OPENPHISH', datetime('now'), $count, 1);"
|
||
log "OpenPhish: $count domains"
|
||
return 0
|
||
else
|
||
warn "Failed to update OpenPhish feed"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
feed_update_malwaredomains() {
|
||
local feed_file="$FEEDS_DIR/malwaredomains.txt"
|
||
log "Updating Malware Domains feed..."
|
||
|
||
if curl -sL --connect-timeout 10 --max-time 60 "$FEED_MALWAREDOMAINS" -o "$feed_file.tmp" 2>/dev/null; then
|
||
grep -v '^#' "$feed_file.tmp" 2>/dev/null | grep -v '^$' | sort -u > "$feed_file"
|
||
local count=$(wc -l < "$feed_file")
|
||
rm -f "$feed_file.tmp"
|
||
|
||
sqlite3 "$BLOCKLIST_DB" "INSERT OR REPLACE INTO feeds VALUES ('malwaredomains', '$FEED_MALWAREDOMAINS', datetime('now'), $count, 1);"
|
||
log "Malware Domains: $count domains"
|
||
return 0
|
||
else
|
||
warn "Failed to update Malware Domains feed"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
feed_import_dnsguard() {
|
||
local dnsguard_list="/var/lib/dns-guard/threat_domains.txt"
|
||
local feed_file="$FEEDS_DIR/dnsguard.txt"
|
||
|
||
if [ -f "$dnsguard_list" ]; then
|
||
log "Importing DNS Guard detections..."
|
||
cp "$dnsguard_list" "$feed_file"
|
||
local count=$(wc -l < "$feed_file")
|
||
sqlite3 "$BLOCKLIST_DB" "INSERT OR REPLACE INTO feeds VALUES ('dnsguard', 'local', datetime('now'), $count, 1);"
|
||
log "DNS Guard: $count domains"
|
||
return 0
|
||
else
|
||
info "No DNS Guard detections found"
|
||
return 0
|
||
fi
|
||
}
|
||
|
||
intel_update() {
|
||
init_dirs
|
||
init_db
|
||
|
||
log "Updating threat intelligence feeds..."
|
||
echo ""
|
||
|
||
local total=0
|
||
|
||
# Update each feed
|
||
feed_update_urlhaus && total=$((total + 1))
|
||
feed_update_openphish && total=$((total + 1))
|
||
feed_update_malwaredomains && total=$((total + 1))
|
||
feed_import_dnsguard && total=$((total + 1))
|
||
|
||
echo ""
|
||
log "Updated $total feeds"
|
||
|
||
# Merge feeds into database
|
||
intel_merge
|
||
|
||
# Generate dnsmasq blocklist
|
||
generate_blocklist
|
||
}
|
||
|
||
intel_merge() {
|
||
log "Merging feeds into blocklist..."
|
||
|
||
local now=$(date -Iseconds)
|
||
|
||
# Import from each feed file
|
||
for feed_file in "$FEEDS_DIR"/*.txt; do
|
||
[ -f "$feed_file" ] || continue
|
||
local feed_name=$(basename "$feed_file" .txt)
|
||
local threat_type="malware"
|
||
|
||
case "$feed_name" in
|
||
openphish|phishtank) threat_type="phishing" ;;
|
||
urlhaus) threat_type="malware" ;;
|
||
dnsguard) threat_type="ai_detected" ;;
|
||
feodo) threat_type="c2" ;;
|
||
esac
|
||
|
||
while read -r domain; do
|
||
[ -z "$domain" ] && continue
|
||
[ "${domain:0:1}" = "#" ] && continue
|
||
|
||
# Clean domain
|
||
domain=$(echo "$domain" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9.-]//g')
|
||
[ -z "$domain" ] && continue
|
||
|
||
sqlite3 "$BLOCKLIST_DB" "INSERT OR IGNORE INTO domains (domain, threat_type, source, first_seen, last_seen)
|
||
VALUES ('$domain', '$threat_type', '$feed_name', '$now', '$now');"
|
||
sqlite3 "$BLOCKLIST_DB" "UPDATE domains SET last_seen='$now', source='$feed_name' WHERE domain='$domain';"
|
||
done < "$feed_file"
|
||
done
|
||
|
||
local total=$(sqlite3 "$BLOCKLIST_DB" "SELECT COUNT(*) FROM domains WHERE blocked=1;")
|
||
log "Total blocked domains: $total"
|
||
}
|
||
|
||
generate_blocklist() {
|
||
log "Generating dnsmasq blocklist..."
|
||
|
||
# Generate hosts file for sinkhole
|
||
echo "# Vortex DNS Firewall - Generated $(date)" > "$BLOCKLIST_HOSTS"
|
||
echo "# Sinkhole IP: $SINKHOLE_IP" >> "$BLOCKLIST_HOSTS"
|
||
echo "" >> "$BLOCKLIST_HOSTS"
|
||
|
||
sqlite3 -separator ' ' "$BLOCKLIST_DB" \
|
||
"SELECT '$SINKHOLE_IP', domain FROM domains WHERE blocked=1;" >> "$BLOCKLIST_HOSTS"
|
||
|
||
local count=$(grep -c "^$SINKHOLE_IP" "$BLOCKLIST_HOSTS")
|
||
log "Generated $count sinkhole entries"
|
||
|
||
# Generate dnsmasq config
|
||
cat > "$DNSMASQ_CONF" <<EOF
|
||
# Vortex DNS Firewall Configuration
|
||
# Generated: $(date)
|
||
# Block count: $count
|
||
|
||
# Load sinkhole hosts
|
||
addn-hosts=$BLOCKLIST_HOSTS
|
||
|
||
# Log queries for analysis
|
||
log-queries
|
||
log-facility=/var/log/dnsmasq.log
|
||
EOF
|
||
|
||
log "dnsmasq config written: $DNSMASQ_CONF"
|
||
|
||
# Reload dnsmasq
|
||
if [ -x /etc/init.d/dnsmasq ]; then
|
||
/etc/init.d/dnsmasq restart 2>/dev/null
|
||
log "dnsmasq restarted"
|
||
fi
|
||
|
||
# Update stats
|
||
local now=$(date -Iseconds)
|
||
echo "{\"domains\":$count,\"last_update\":\"$now\",\"blocks\":0,\"queries\":0}" > "$STATS_FILE"
|
||
}
|
||
|
||
intel_status() {
|
||
init_dirs
|
||
init_db
|
||
|
||
echo ""
|
||
echo -e "${BOLD}Vortex DNS Firewall - Threat Intelligence${NC}"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo ""
|
||
|
||
echo -e "${BOLD}Feed Status:${NC}"
|
||
sqlite3 -column -header "$BLOCKLIST_DB" \
|
||
"SELECT name, domain_count as domains, last_update, CASE enabled WHEN 1 THEN 'Active' ELSE 'Disabled' END as status FROM feeds;"
|
||
|
||
echo ""
|
||
echo -e "${BOLD}Threat Categories:${NC}"
|
||
sqlite3 -column -header "$BLOCKLIST_DB" \
|
||
"SELECT threat_type, COUNT(*) as count FROM domains WHERE blocked=1 GROUP BY threat_type ORDER BY count DESC;"
|
||
|
||
echo ""
|
||
local total=$(sqlite3 "$BLOCKLIST_DB" "SELECT COUNT(*) FROM domains WHERE blocked=1;")
|
||
echo -e "${BOLD}Total Blocked Domains:${NC} $total"
|
||
echo ""
|
||
}
|
||
|
||
intel_search() {
|
||
local domain="$1"
|
||
[ -z "$domain" ] && { error "Usage: vortex-firewall intel search <domain>"; return 1; }
|
||
|
||
init_db
|
||
|
||
local result=$(sqlite3 -column -header "$BLOCKLIST_DB" \
|
||
"SELECT domain, threat_type, confidence, source, first_seen, hit_count FROM domains WHERE domain LIKE '%$domain%' LIMIT 20;")
|
||
|
||
if [ -n "$result" ]; then
|
||
echo ""
|
||
echo -e "${RED}BLOCKED${NC} - Domain found in blocklist:"
|
||
echo "$result"
|
||
else
|
||
echo -e "${GREEN}CLEAN${NC} - Domain not in blocklist: $domain"
|
||
fi
|
||
}
|
||
|
||
intel_add() {
|
||
local domain="$1"
|
||
local reason="${2:-manual}"
|
||
[ -z "$domain" ] && { error "Usage: vortex-firewall intel add <domain> [reason]"; return 1; }
|
||
|
||
init_db
|
||
|
||
domain=$(echo "$domain" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9.-]//g')
|
||
local now=$(date -Iseconds)
|
||
|
||
sqlite3 "$BLOCKLIST_DB" \
|
||
"INSERT OR REPLACE INTO domains (domain, threat_type, confidence, source, first_seen, last_seen, blocked)
|
||
VALUES ('$domain', '$reason', 100, 'manual', '$now', '$now', 1);"
|
||
|
||
# Add to hosts file immediately
|
||
echo "$SINKHOLE_IP $domain" >> "$BLOCKLIST_HOSTS"
|
||
|
||
log "Blocked: $domain (reason: $reason)"
|
||
|
||
# Reload dnsmasq
|
||
killall -HUP dnsmasq 2>/dev/null
|
||
}
|
||
|
||
intel_remove() {
|
||
local domain="$1"
|
||
[ -z "$domain" ] && { error "Usage: vortex-firewall intel remove <domain>"; return 1; }
|
||
|
||
init_db
|
||
|
||
sqlite3 "$BLOCKLIST_DB" "UPDATE domains SET blocked=0 WHERE domain='$domain';"
|
||
|
||
# Regenerate blocklist
|
||
generate_blocklist
|
||
|
||
log "Unblocked: $domain"
|
||
}
|
||
|
||
# ============================================================================
|
||
# Statistics
|
||
# ============================================================================
|
||
|
||
show_stats() {
|
||
init_dirs
|
||
init_db
|
||
|
||
echo ""
|
||
echo -e "${BOLD}Vortex DNS Firewall - Statistics${NC}"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo ""
|
||
|
||
local total_domains=$(sqlite3 "$BLOCKLIST_DB" "SELECT COUNT(*) FROM domains WHERE blocked=1;" 2>/dev/null || echo 0)
|
||
local total_hits=$(sqlite3 "$BLOCKLIST_DB" "SELECT COALESCE(SUM(hit_count),0) FROM domains;" 2>/dev/null || echo 0)
|
||
local total_events=$(sqlite3 "$BLOCKLIST_DB" "SELECT COUNT(*) FROM events;" 2>/dev/null || echo 0)
|
||
|
||
# ×47 Impact calculation
|
||
local x47_impact=$((total_hits * 47))
|
||
|
||
echo -e "${BOLD}Blocking Summary:${NC}"
|
||
echo " Blocked Domains: $total_domains"
|
||
echo " Total Hits: $total_hits"
|
||
echo " Sinkhole Events: $total_events"
|
||
echo ""
|
||
echo -e "${BOLD}×47 Impact Score:${NC}"
|
||
echo -e " ${CYAN}$x47_impact${NC} connections prevented"
|
||
echo " (Each DNS block prevents ~47 malicious connections)"
|
||
echo ""
|
||
|
||
echo -e "${BOLD}Top Blocked Domains:${NC}"
|
||
sqlite3 -column "$BLOCKLIST_DB" \
|
||
"SELECT domain, hit_count, threat_type FROM domains WHERE hit_count > 0 ORDER BY hit_count DESC LIMIT 10;" 2>/dev/null
|
||
|
||
echo ""
|
||
echo -e "${BOLD}Threat Distribution:${NC}"
|
||
sqlite3 "$BLOCKLIST_DB" \
|
||
"SELECT threat_type || ': ' || COUNT(*) FROM domains WHERE blocked=1 GROUP BY threat_type ORDER BY COUNT(*) DESC;" 2>/dev/null
|
||
echo ""
|
||
}
|
||
|
||
show_x47() {
|
||
init_db
|
||
|
||
local total_hits=$(sqlite3 "$BLOCKLIST_DB" "SELECT COALESCE(SUM(hit_count),0) FROM domains;" 2>/dev/null || echo 0)
|
||
local x47_impact=$((total_hits * 47))
|
||
local total_domains=$(sqlite3 "$BLOCKLIST_DB" "SELECT COUNT(*) FROM domains WHERE blocked=1;" 2>/dev/null || echo 0)
|
||
|
||
echo ""
|
||
echo -e "${BOLD}╔══════════════════════════════════════════════════╗${NC}"
|
||
echo -e "${BOLD}║ ×47 VITALITY IMPACT SCORE ║${NC}"
|
||
echo -e "${BOLD}╠══════════════════════════════════════════════════╣${NC}"
|
||
echo -e "${BOLD}║${NC} Blocked Domains: ${CYAN}$total_domains${NC}"
|
||
echo -e "${BOLD}║${NC} DNS Blocks: ${CYAN}$total_hits${NC}"
|
||
echo -e "${BOLD}║${NC} Connections Prevented: ${GREEN}$x47_impact${NC}"
|
||
echo -e "${BOLD}║${NC}"
|
||
echo -e "${BOLD}║${NC} ${YELLOW}Each DNS block = 47 connections stopped${NC}"
|
||
echo -e "${BOLD}║${NC} ${YELLOW}(C2 beacon rate × infection window)${NC}"
|
||
echo -e "${BOLD}╚══════════════════════════════════════════════════╝${NC}"
|
||
echo ""
|
||
}
|
||
|
||
# ============================================================================
|
||
# Service Control
|
||
# ============================================================================
|
||
|
||
service_start() {
|
||
log "Starting Vortex DNS Firewall..."
|
||
|
||
init_dirs
|
||
init_db
|
||
|
||
# Initial feed update if no blocklist exists
|
||
if [ ! -f "$BLOCKLIST_HOSTS" ] || [ $(wc -l < "$BLOCKLIST_HOSTS" 2>/dev/null || echo 0) -lt 10 ]; then
|
||
intel_update
|
||
fi
|
||
|
||
log "Vortex DNS Firewall active"
|
||
log "Sinkhole IP: $SINKHOLE_IP"
|
||
log "Blocked domains: $(sqlite3 "$BLOCKLIST_DB" "SELECT COUNT(*) FROM domains WHERE blocked=1;")"
|
||
}
|
||
|
||
service_stop() {
|
||
log "Stopping Vortex DNS Firewall..."
|
||
|
||
# Remove dnsmasq config
|
||
rm -f "$DNSMASQ_CONF"
|
||
|
||
# Reload dnsmasq
|
||
/etc/init.d/dnsmasq restart 2>/dev/null
|
||
|
||
log "Vortex DNS Firewall stopped"
|
||
}
|
||
|
||
service_status() {
|
||
echo ""
|
||
echo -e "${BOLD}Vortex DNS Firewall v$VERSION${NC}"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
if [ -f "$DNSMASQ_CONF" ]; then
|
||
echo -e "Status: ${GREEN}Active${NC}"
|
||
else
|
||
echo -e "Status: ${RED}Inactive${NC}"
|
||
fi
|
||
|
||
echo "Sinkhole IP: $SINKHOLE_IP"
|
||
|
||
if [ -f "$BLOCKLIST_DB" ]; then
|
||
local count=$(sqlite3 "$BLOCKLIST_DB" "SELECT COUNT(*) FROM domains WHERE blocked=1;" 2>/dev/null || echo 0)
|
||
echo "Blocked: $count domains"
|
||
else
|
||
echo "Blocked: (no database)"
|
||
fi
|
||
|
||
if [ -f "$STATS_FILE" ]; then
|
||
local last=$(jsonfilter -i "$STATS_FILE" -e '@.last_update' 2>/dev/null || echo "never")
|
||
echo "Last Update: $last"
|
||
fi
|
||
|
||
echo ""
|
||
}
|
||
|
||
# ============================================================================
|
||
# Usage
|
||
# ============================================================================
|
||
|
||
usage() {
|
||
cat <<'EOF'
|
||
Vortex DNS Firewall - Block threats at DNS level
|
||
|
||
Usage: vortex-firewall <command> [options]
|
||
|
||
Intel Commands:
|
||
intel update Update all threat feeds
|
||
intel status Show feed status and stats
|
||
intel search <domain> Check if domain is blocked
|
||
intel add <domain> Manually block a domain
|
||
intel remove <domain> Unblock a domain
|
||
|
||
Statistics:
|
||
stats Show blocking statistics
|
||
stats --x47 Show ×47 impact score
|
||
stats --top-blocked Top blocked domains
|
||
|
||
Service:
|
||
start Start firewall
|
||
stop Stop firewall
|
||
status Show service status
|
||
|
||
The ×47 multiplier: Each DNS block prevents ~47 malicious connections
|
||
(based on typical C2 beacon rate × average infection detection window)
|
||
|
||
Examples:
|
||
vortex-firewall intel update
|
||
vortex-firewall intel search evil.com
|
||
vortex-firewall intel add malware.example.com c2
|
||
vortex-firewall stats --x47
|
||
EOF
|
||
}
|
||
|
||
# ============================================================================
|
||
# Main
|
||
# ============================================================================
|
||
|
||
case "${1:-}" in
|
||
intel)
|
||
shift
|
||
case "${1:-}" in
|
||
update) intel_update ;;
|
||
status) intel_status ;;
|
||
search) shift; intel_search "$@" ;;
|
||
add) shift; intel_add "$@" ;;
|
||
remove) shift; intel_remove "$@" ;;
|
||
*) error "Unknown intel command. Use: update, status, search, add, remove" ;;
|
||
esac
|
||
;;
|
||
|
||
stats)
|
||
shift
|
||
case "${1:-}" in
|
||
--x47|-x) show_x47 ;;
|
||
--top*) show_stats ;;
|
||
*) show_stats ;;
|
||
esac
|
||
;;
|
||
|
||
start)
|
||
service_start
|
||
;;
|
||
|
||
stop)
|
||
service_stop
|
||
;;
|
||
|
||
status)
|
||
service_status
|
||
;;
|
||
|
||
help|--help|-h)
|
||
usage
|
||
;;
|
||
|
||
"")
|
||
service_status
|
||
;;
|
||
|
||
*)
|
||
error "Unknown command: $1"
|
||
usage >&2
|
||
exit 1
|
||
;;
|
||
esac
|