Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
+249
-211
@@ -1,12 +1,29 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Script Name: iptables-blocklist-metrics.sh
|
||||
# Version: 2.0
|
||||
# Version: 2.03
|
||||
# Description: Prometheus exporter for iptables threat feed blocking metrics
|
||||
# Author: Phil Connor
|
||||
# Contact: contact@mylinux.work
|
||||
# Website: https://mylinux.work
|
||||
# License: MIT
|
||||
#
|
||||
# Changes in v2.03:
|
||||
# - Fixed blocked_total metric type from counter to gauge (rolling window)
|
||||
# - Fixed HTTP response headers (printf with proper \r\n termination)
|
||||
# - Fixed rule-stats grep prefix-matching wrong feed (word-boundary match)
|
||||
# - Cached iptables -L INPUT output once per scrape instead of per-feed
|
||||
# - Removed unused get_iptables_rule_stats helper function
|
||||
# - Used FEEDS_ARRAY instead of grep on config file for ipset status check
|
||||
# - Removed unnecessary sync call in textfile output path
|
||||
#
|
||||
# Changes in v2.02:
|
||||
# - Added journal data caching (single journalctl call instead of per-feed)
|
||||
# - Added feeds config caching into array
|
||||
# - Fixed ipset member counting to use Members: section
|
||||
# - Added SCRIPT_VERSION variable for version strings
|
||||
# - Added scrape timestamp metric
|
||||
# - Fixed hardcoded version in info metric and HTML page
|
||||
################################################################################
|
||||
|
||||
# Ensure PATH includes sbin (for ipset/iptables when run from cron)
|
||||
@@ -38,14 +55,18 @@ FEEDS_CONFIG="$CONFIG_DIR/feeds.conf"
|
||||
IPSET_PREFIX="iptables-feed"
|
||||
WHITELIST_IPSET="iptables-whitelist"
|
||||
WHITELIST_IPSET_V6="iptables-whitelist-v6"
|
||||
LOG_FILE="/var/log/iptables-threats.log"
|
||||
|
||||
TEXTFILE_DIR="/var/lib/node_exporter"
|
||||
OUTPUT_FILE=""
|
||||
HTTP_MODE=false
|
||||
HTTP_PORT=9419
|
||||
SCRIPT_START_TIME=$(date +%s)
|
||||
LOCK_FILE="/var/run/iptables-blocklist-metrics.lock"
|
||||
SCRIPT_VERSION="2.03"
|
||||
|
||||
# Global cache variables
|
||||
JOURNAL_1H=""
|
||||
JOURNAL_24H=""
|
||||
FEEDS_ARRAY=()
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF
|
||||
@@ -89,26 +110,62 @@ parse_args() {
|
||||
done
|
||||
}
|
||||
|
||||
# Load all journal data ONCE at startup
|
||||
cache_journal_data() {
|
||||
JOURNAL_1H=$(timeout 10 journalctl -k --since "1 hour ago" 2>/dev/null | grep '\[THREAT' || echo "")
|
||||
JOURNAL_24H=$(timeout 30 journalctl -k --since "24 hours ago" 2>/dev/null | grep '\[THREAT' || echo "")
|
||||
}
|
||||
|
||||
# Parse feeds config ONCE into array
|
||||
cache_feeds_config() {
|
||||
FEEDS_ARRAY=()
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
FEEDS_ARRAY+=("$enabled|$name|$url|$type|$description")
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
}
|
||||
|
||||
get_ipset_size() {
|
||||
local ipset_name="$1"
|
||||
local size
|
||||
size=$(ipset list "$ipset_name" 2>/dev/null | grep '^[0-9a-fA-F.:]' | wc -l 2>/dev/null)
|
||||
echo "${size:-0}"
|
||||
local count
|
||||
count=$(ipset list "$ipset_name" 2>/dev/null | sed -n '/^Members:$/,$p' | tail -n +2 | wc -l)
|
||||
echo "${count:-0}"
|
||||
}
|
||||
|
||||
get_feed_blocks() {
|
||||
local feed="$1"
|
||||
local period="$2"
|
||||
local data
|
||||
|
||||
case "$period" in
|
||||
"1 hour ago") data="$JOURNAL_1H" ;;
|
||||
"24 hours ago") data="$JOURNAL_24H" ;;
|
||||
*) echo 0; return ;;
|
||||
esac
|
||||
|
||||
if [ -z "$data" ]; then echo 0; return; fi
|
||||
local count
|
||||
count=$(journalctl -k --since "$period" 2>/dev/null | grep "\[THREAT:${feed}\]" | wc -l 2>/dev/null)
|
||||
count=$(printf '%s' "$data" | grep -c "\[THREAT:${feed}\]" 2>/dev/null)
|
||||
echo "${count:-0}"
|
||||
}
|
||||
|
||||
get_feed_blocks_v6() {
|
||||
local feed="$1"
|
||||
local period="$2"
|
||||
local data
|
||||
|
||||
case "$period" in
|
||||
"1 hour ago") data="$JOURNAL_1H" ;;
|
||||
"24 hours ago") data="$JOURNAL_24H" ;;
|
||||
*) echo 0; return ;;
|
||||
esac
|
||||
|
||||
if [ -z "$data" ]; then echo 0; return; fi
|
||||
local count
|
||||
count=$(journalctl -k --since "$period" 2>/dev/null | grep "\[THREAT-v6:${feed}\]" | wc -l 2>/dev/null)
|
||||
count=$(printf '%s' "$data" | grep -c "\[THREAT-v6:${feed}\]" 2>/dev/null)
|
||||
echo "${count:-0}"
|
||||
}
|
||||
|
||||
@@ -128,13 +185,6 @@ get_cache_age() {
|
||||
fi
|
||||
}
|
||||
|
||||
get_iptables_rule_stats() {
|
||||
local chain="$1"
|
||||
local feed="$2"
|
||||
# Extract packet and byte counts from iptables -L -v -n -x (exact numbers, no human-readable K/M/G)
|
||||
iptables -L "$chain" -v -n -x 2>/dev/null | grep "${IPSET_PREFIX}-${feed}" | head -1 | awk '{print $1"|"$2}'
|
||||
}
|
||||
|
||||
get_total_unique_ips() {
|
||||
local ip_version="$1"
|
||||
local count=0
|
||||
@@ -189,7 +239,8 @@ get_total_cache_size() {
|
||||
|
||||
acquire_lock() {
|
||||
if [ -f "$LOCK_FILE" ]; then
|
||||
local pid=$(cat "$LOCK_FILE" 2>/dev/null)
|
||||
local pid
|
||||
pid=$(cat "$LOCK_FILE" 2>/dev/null)
|
||||
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
||||
echo "ERROR: Another instance is already running (PID: $pid)" >&2
|
||||
exit 1
|
||||
@@ -207,17 +258,20 @@ cleanup() {
|
||||
}
|
||||
|
||||
generate_metrics() {
|
||||
local start_time=$(date +%s)
|
||||
local current_time=$(date +%s)
|
||||
local start_time
|
||||
start_time=$(date +%s)
|
||||
|
||||
local iptables_input_stats
|
||||
iptables_input_stats=$(iptables -L INPUT -v -n -x 2>/dev/null)
|
||||
|
||||
cat <<EOF
|
||||
# HELP iptables_blocklist_info Per-feed iptables threat blocking info
|
||||
# TYPE iptables_blocklist_info gauge
|
||||
iptables_blocklist_info{mode="per-feed",version="2.0"} 1
|
||||
iptables_blocklist_info{mode="per-feed",version="${SCRIPT_VERSION}"} 1
|
||||
|
||||
# HELP iptables_blocklist_enabled_feeds Total enabled feeds
|
||||
# TYPE iptables_blocklist_enabled_feeds gauge
|
||||
iptables_blocklist_enabled_feeds $(grep -c '^1|' "$FEEDS_CONFIG" 2>/dev/null || echo 0)
|
||||
iptables_blocklist_enabled_feeds $(printf '%s\n' "${FEEDS_ARRAY[@]}" | grep -c '^1|')
|
||||
|
||||
# HELP iptables_blocklist_ipset_size Number of IPs per feed ipset
|
||||
# TYPE iptables_blocklist_ipset_size gauge
|
||||
@@ -226,7 +280,7 @@ EOF
|
||||
# Only export metrics for ipsets that actually exist
|
||||
for ipset_name in $(ipset list -n 2>/dev/null | grep "^${IPSET_PREFIX}-"); do
|
||||
# Extract feed name and IP version
|
||||
local feed_name="${ipset_name#${IPSET_PREFIX}-}"
|
||||
local feed_name="${ipset_name#"${IPSET_PREFIX}"-}"
|
||||
local ip_version="4"
|
||||
|
||||
if [[ "$feed_name" =~ -v6$ ]]; then
|
||||
@@ -236,39 +290,37 @@ EOF
|
||||
|
||||
# Get status from config
|
||||
local status="disabled"
|
||||
if grep -q "^1|${feed_name}|" "$FEEDS_CONFIG" 2>/dev/null; then
|
||||
if printf '%s\n' "${FEEDS_ARRAY[@]}" | grep -q "^1|${feed_name}|" 2>/dev/null; then
|
||||
status="enabled"
|
||||
fi
|
||||
|
||||
local size=$(get_ipset_size "$ipset_name")
|
||||
local size
|
||||
size=$(get_ipset_size "$ipset_name")
|
||||
echo "iptables_blocklist_ipset_size{feed=\"$feed_name\",ip_version=\"$ip_version\",status=\"$status\"} $size"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP iptables_blocklist_blocked_total Blocked attempts per feed
|
||||
# TYPE iptables_blocklist_blocked_total counter
|
||||
# TYPE iptables_blocklist_blocked_total gauge
|
||||
EOF
|
||||
|
||||
# Per-feed block counts (IPv4 and IPv6)
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
[ "$enabled" != "1" ] && continue
|
||||
|
||||
local blocks_1h_v4 blocks_24h_v4 blocks_1h_v6 blocks_24h_v6
|
||||
blocks_1h_v4=$(get_feed_blocks "$name" "1 hour ago")
|
||||
blocks_24h_v4=$(get_feed_blocks "$name" "24 hours ago")
|
||||
blocks_1h_v6=$(get_feed_blocks_v6 "$name" "1 hour ago")
|
||||
blocks_24h_v6=$(get_feed_blocks_v6 "$name" "24 hours ago")
|
||||
|
||||
echo "iptables_blocklist_blocked_total{feed=\"$name\",ip_version=\"4\",period=\"1h\"} $blocks_1h_v4"
|
||||
echo "iptables_blocklist_blocked_total{feed=\"$name\",ip_version=\"4\",period=\"24h\"} $blocks_24h_v4"
|
||||
echo "iptables_blocklist_blocked_total{feed=\"$name\",ip_version=\"6\",period=\"1h\"} $blocks_1h_v6"
|
||||
echo "iptables_blocklist_blocked_total{feed=\"$name\",ip_version=\"6\",period=\"24h\"} $blocks_24h_v6"
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
[ "$enabled" != "1" ] && continue
|
||||
|
||||
local blocks_1h_v4 blocks_24h_v4 blocks_1h_v6 blocks_24h_v6
|
||||
blocks_1h_v4=$(get_feed_blocks "$name" "1 hour ago")
|
||||
blocks_24h_v4=$(get_feed_blocks "$name" "24 hours ago")
|
||||
blocks_1h_v6=$(get_feed_blocks_v6 "$name" "1 hour ago")
|
||||
blocks_24h_v6=$(get_feed_blocks_v6 "$name" "24 hours ago")
|
||||
|
||||
echo "iptables_blocklist_blocked_total{feed=\"$name\",ip_version=\"4\",period=\"1h\"} $blocks_1h_v4"
|
||||
echo "iptables_blocklist_blocked_total{feed=\"$name\",ip_version=\"4\",period=\"24h\"} $blocks_24h_v4"
|
||||
echo "iptables_blocklist_blocked_total{feed=\"$name\",ip_version=\"6\",period=\"1h\"} $blocks_1h_v6"
|
||||
echo "iptables_blocklist_blocked_total{feed=\"$name\",ip_version=\"6\",period=\"24h\"} $blocks_24h_v6"
|
||||
done
|
||||
|
||||
# Feed effectiveness (blocks per 1000 IPs)
|
||||
cat <<EOF
|
||||
@@ -277,37 +329,34 @@ EOF
|
||||
# TYPE iptables_blocklist_effectiveness gauge
|
||||
EOF
|
||||
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
[ "$enabled" != "1" ] && continue
|
||||
|
||||
local ipset_size blocks_v4 blocks_v6 effectiveness_v4 effectiveness_v6
|
||||
ipset_size=$(get_ipset_size "${IPSET_PREFIX}-${name}")
|
||||
blocks_v4=$(get_feed_blocks "$name" "24 hours ago")
|
||||
blocks_v6=$(get_feed_blocks_v6 "$name" "24 hours ago")
|
||||
|
||||
# Strip whitespace and ensure integers
|
||||
ipset_size=$(echo "$ipset_size" | tr -d '\n' | tr -d ' ')
|
||||
blocks_v4=$(echo "$blocks_v4" | tr -d '\n' | tr -d ' ')
|
||||
blocks_v6=$(echo "$blocks_v6" | tr -d '\n' | tr -d ' ')
|
||||
ipset_size=${ipset_size:-0}
|
||||
blocks_v4=${blocks_v4:-0}
|
||||
blocks_v6=${blocks_v6:-0}
|
||||
|
||||
if [ "$ipset_size" -gt 0 ] 2>/dev/null; then
|
||||
effectiveness_v4=$(awk "BEGIN {printf \"%.2f\", ($blocks_v4 / $ipset_size) * 1000}" 2>/dev/null || echo "0")
|
||||
effectiveness_v6=$(awk "BEGIN {printf \"%.2f\", ($blocks_v6 / $ipset_size) * 1000}" 2>/dev/null || echo "0")
|
||||
else
|
||||
effectiveness_v4="0"
|
||||
effectiveness_v6="0"
|
||||
fi
|
||||
|
||||
echo "iptables_blocklist_effectiveness{feed=\"$name\",ip_version=\"4\"} $effectiveness_v4"
|
||||
echo "iptables_blocklist_effectiveness{feed=\"$name\",ip_version=\"6\"} $effectiveness_v6"
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
[ "$enabled" != "1" ] && continue
|
||||
|
||||
local ipset_size blocks_v4 blocks_v6 effectiveness_v4 effectiveness_v6
|
||||
ipset_size=$(get_ipset_size "${IPSET_PREFIX}-${name}")
|
||||
blocks_v4=$(get_feed_blocks "$name" "24 hours ago")
|
||||
blocks_v6=$(get_feed_blocks_v6 "$name" "24 hours ago")
|
||||
|
||||
# Strip whitespace and ensure integers
|
||||
ipset_size=$(echo "$ipset_size" | tr -d '\n' | tr -d ' ')
|
||||
blocks_v4=$(echo "$blocks_v4" | tr -d '\n' | tr -d ' ')
|
||||
blocks_v6=$(echo "$blocks_v6" | tr -d '\n' | tr -d ' ')
|
||||
ipset_size=${ipset_size:-0}
|
||||
blocks_v4=${blocks_v4:-0}
|
||||
blocks_v6=${blocks_v6:-0}
|
||||
|
||||
if [ "$ipset_size" -gt 0 ] 2>/dev/null; then
|
||||
effectiveness_v4=$(awk "BEGIN {printf \"%.2f\", ($blocks_v4 / $ipset_size) * 1000}" 2>/dev/null || echo "0")
|
||||
effectiveness_v6=$(awk "BEGIN {printf \"%.2f\", ($blocks_v6 / $ipset_size) * 1000}" 2>/dev/null || echo "0")
|
||||
else
|
||||
effectiveness_v4="0"
|
||||
effectiveness_v6="0"
|
||||
fi
|
||||
|
||||
echo "iptables_blocklist_effectiveness{feed=\"$name\",ip_version=\"4\"} $effectiveness_v4"
|
||||
echo "iptables_blocklist_effectiveness{feed=\"$name\",ip_version=\"6\"} $effectiveness_v6"
|
||||
done
|
||||
|
||||
# Feed update/cache metrics
|
||||
cat <<EOF
|
||||
@@ -316,21 +365,18 @@ EOF
|
||||
# TYPE iptables_blocklist_last_update_timestamp gauge
|
||||
EOF
|
||||
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
|
||||
local v4_file="${CACHE_DIR}/${name}-v4.parsed"
|
||||
local v6_file="${CACHE_DIR}/${name}-v6.parsed"
|
||||
local v4_ts v6_ts
|
||||
v4_ts=$(get_file_timestamp "$v4_file")
|
||||
v6_ts=$(get_file_timestamp "$v6_file")
|
||||
|
||||
echo "iptables_blocklist_last_update_timestamp{feed=\"$name\",ip_version=\"4\"} $v4_ts"
|
||||
echo "iptables_blocklist_last_update_timestamp{feed=\"$name\",ip_version=\"6\"} $v6_ts"
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
|
||||
local v4_file="${CACHE_DIR}/${name}-v4.parsed"
|
||||
local v6_file="${CACHE_DIR}/${name}-v6.parsed"
|
||||
local v4_ts v6_ts
|
||||
v4_ts=$(get_file_timestamp "$v4_file")
|
||||
v6_ts=$(get_file_timestamp "$v6_file")
|
||||
|
||||
echo "iptables_blocklist_last_update_timestamp{feed=\"$name\",ip_version=\"4\"} $v4_ts"
|
||||
echo "iptables_blocklist_last_update_timestamp{feed=\"$name\",ip_version=\"6\"} $v6_ts"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
@@ -338,21 +384,18 @@ EOF
|
||||
# TYPE iptables_blocklist_cache_age_seconds gauge
|
||||
EOF
|
||||
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
|
||||
local v4_file="${CACHE_DIR}/${name}-v4.parsed"
|
||||
local v6_file="${CACHE_DIR}/${name}-v6.parsed"
|
||||
local v4_age v6_age
|
||||
v4_age=$(get_cache_age "$v4_file")
|
||||
v6_age=$(get_cache_age "$v6_file")
|
||||
|
||||
echo "iptables_blocklist_cache_age_seconds{feed=\"$name\",ip_version=\"4\"} $v4_age"
|
||||
echo "iptables_blocklist_cache_age_seconds{feed=\"$name\",ip_version=\"6\"} $v6_age"
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
|
||||
local v4_file="${CACHE_DIR}/${name}-v4.parsed"
|
||||
local v6_file="${CACHE_DIR}/${name}-v6.parsed"
|
||||
local v4_age v6_age
|
||||
v4_age=$(get_cache_age "$v4_file")
|
||||
v6_age=$(get_cache_age "$v6_file")
|
||||
|
||||
echo "iptables_blocklist_cache_age_seconds{feed=\"$name\",ip_version=\"4\"} $v4_age"
|
||||
echo "iptables_blocklist_cache_age_seconds{feed=\"$name\",ip_version=\"6\"} $v6_age"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
@@ -360,21 +403,18 @@ EOF
|
||||
# TYPE iptables_blocklist_file_size_bytes gauge
|
||||
EOF
|
||||
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
|
||||
local v4_file="${CACHE_DIR}/${name}-v4.parsed"
|
||||
local v6_file="${CACHE_DIR}/${name}-v6.parsed"
|
||||
local v4_size v6_size
|
||||
v4_size=$(get_file_size "$v4_file")
|
||||
v6_size=$(get_file_size "$v6_file")
|
||||
|
||||
echo "iptables_blocklist_file_size_bytes{feed=\"$name\",ip_version=\"4\",type=\"parsed\"} $v4_size"
|
||||
echo "iptables_blocklist_file_size_bytes{feed=\"$name\",ip_version=\"6\",type=\"parsed\"} $v6_size"
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
|
||||
local v4_file="${CACHE_DIR}/${name}-v4.parsed"
|
||||
local v6_file="${CACHE_DIR}/${name}-v6.parsed"
|
||||
local v4_size v6_size
|
||||
v4_size=$(get_file_size "$v4_file")
|
||||
v6_size=$(get_file_size "$v6_file")
|
||||
|
||||
echo "iptables_blocklist_file_size_bytes{feed=\"$name\",ip_version=\"4\",type=\"parsed\"} $v4_size"
|
||||
echo "iptables_blocklist_file_size_bytes{feed=\"$name\",ip_version=\"6\",type=\"parsed\"} $v6_size"
|
||||
done
|
||||
|
||||
# IP version distribution ratio
|
||||
cat <<EOF
|
||||
@@ -383,31 +423,28 @@ EOF
|
||||
# TYPE iptables_blocklist_ip_version_ratio gauge
|
||||
EOF
|
||||
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
|
||||
local v4_size v6_size total ratio_v4 ratio_v6
|
||||
v4_size=$(get_ipset_size "${IPSET_PREFIX}-${name}")
|
||||
v6_size=$(get_ipset_size "${IPSET_PREFIX}-${name}-v6")
|
||||
|
||||
v4_size=${v4_size:-0}
|
||||
v6_size=${v6_size:-0}
|
||||
total=$((v4_size + v6_size))
|
||||
|
||||
if [ "$total" -gt 0 ] 2>/dev/null; then
|
||||
ratio_v4=$(awk "BEGIN {printf \"%.4f\", $v4_size / $total}" 2>/dev/null || echo "0")
|
||||
ratio_v6=$(awk "BEGIN {printf \"%.4f\", $v6_size / $total}" 2>/dev/null || echo "0")
|
||||
else
|
||||
ratio_v4="0"
|
||||
ratio_v6="0"
|
||||
fi
|
||||
|
||||
echo "iptables_blocklist_ip_version_ratio{feed=\"$name\",version=\"4\"} $ratio_v4"
|
||||
echo "iptables_blocklist_ip_version_ratio{feed=\"$name\",version=\"6\"} $ratio_v6"
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
|
||||
local v4_size v6_size total ratio_v4 ratio_v6
|
||||
v4_size=$(get_ipset_size "${IPSET_PREFIX}-${name}")
|
||||
v6_size=$(get_ipset_size "${IPSET_PREFIX}-${name}-v6")
|
||||
|
||||
v4_size=${v4_size:-0}
|
||||
v6_size=${v6_size:-0}
|
||||
total=$((v4_size + v6_size))
|
||||
|
||||
if [ "$total" -gt 0 ] 2>/dev/null; then
|
||||
ratio_v4=$(awk "BEGIN {printf \"%.4f\", $v4_size / $total}" 2>/dev/null || echo "0")
|
||||
ratio_v6=$(awk "BEGIN {printf \"%.4f\", $v6_size / $total}" 2>/dev/null || echo "0")
|
||||
else
|
||||
ratio_v4="0"
|
||||
ratio_v6="0"
|
||||
fi
|
||||
|
||||
echo "iptables_blocklist_ip_version_ratio{feed=\"$name\",version=\"4\"} $ratio_v4"
|
||||
echo "iptables_blocklist_ip_version_ratio{feed=\"$name\",version=\"6\"} $ratio_v6"
|
||||
done
|
||||
|
||||
# Total metrics
|
||||
cat <<EOF
|
||||
@@ -425,30 +462,27 @@ iptables_blocklist_total_rules $(iptables -S 2>/dev/null | wc -l)
|
||||
# TYPE iptables_blocklist_rule_packets counter
|
||||
EOF
|
||||
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
[ "$enabled" != "1" ] && continue
|
||||
|
||||
local stats_log stats_drop packets_log bytes_log packets_drop bytes_drop
|
||||
|
||||
stats_log=$(iptables -L INPUT -v -n -x 2>/dev/null | grep "${IPSET_PREFIX}-${name}" | grep LOG | head -1 | awk '{print $1"|"$2}')
|
||||
stats_drop=$(iptables -L INPUT -v -n -x 2>/dev/null | grep "${IPSET_PREFIX}-${name}" | grep DROP | head -1 | awk '{print $1"|"$2}')
|
||||
|
||||
if [ -n "$stats_log" ]; then
|
||||
packets_log=$(echo "$stats_log" | cut -d'|' -f1)
|
||||
bytes_log=$(echo "$stats_log" | cut -d'|' -f2)
|
||||
echo "iptables_blocklist_rule_packets{feed=\"$name\",ip_version=\"4\",action=\"log\"} ${packets_log:-0}"
|
||||
fi
|
||||
|
||||
if [ -n "$stats_drop" ]; then
|
||||
packets_drop=$(echo "$stats_drop" | cut -d'|' -f1)
|
||||
bytes_drop=$(echo "$stats_drop" | cut -d'|' -f2)
|
||||
echo "iptables_blocklist_rule_packets{feed=\"$name\",ip_version=\"4\",action=\"drop\"} ${packets_drop:-0}"
|
||||
fi
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
[ "$enabled" != "1" ] && continue
|
||||
|
||||
local stats_log stats_drop packets_log bytes_log packets_drop bytes_drop
|
||||
|
||||
stats_log=$(echo "$iptables_input_stats" | grep " ${IPSET_PREFIX}-${name} " | grep LOG | head -1 | awk '{print $1"|"$2}')
|
||||
stats_drop=$(echo "$iptables_input_stats" | grep " ${IPSET_PREFIX}-${name} " | grep DROP | head -1 | awk '{print $1"|"$2}')
|
||||
|
||||
if [ -n "$stats_log" ]; then
|
||||
packets_log=$(echo "$stats_log" | cut -d'|' -f1)
|
||||
bytes_log=$(echo "$stats_log" | cut -d'|' -f2)
|
||||
echo "iptables_blocklist_rule_packets{feed=\"$name\",ip_version=\"4\",action=\"log\"} ${packets_log:-0}"
|
||||
fi
|
||||
|
||||
if [ -n "$stats_drop" ]; then
|
||||
packets_drop=$(echo "$stats_drop" | cut -d'|' -f1)
|
||||
bytes_drop=$(echo "$stats_drop" | cut -d'|' -f2)
|
||||
echo "iptables_blocklist_rule_packets{feed=\"$name\",ip_version=\"4\",action=\"drop\"} ${packets_drop:-0}"
|
||||
fi
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
@@ -456,30 +490,27 @@ EOF
|
||||
# TYPE iptables_blocklist_rule_bytes counter
|
||||
EOF
|
||||
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
[ "$enabled" != "1" ] && continue
|
||||
|
||||
local stats_log stats_drop packets_log bytes_log packets_drop bytes_drop
|
||||
|
||||
stats_log=$(iptables -L INPUT -v -n -x 2>/dev/null | grep "${IPSET_PREFIX}-${name}" | grep LOG | head -1 | awk '{print $1"|"$2}')
|
||||
stats_drop=$(iptables -L INPUT -v -n -x 2>/dev/null | grep "${IPSET_PREFIX}-${name}" | grep DROP | head -1 | awk '{print $1"|"$2}')
|
||||
|
||||
if [ -n "$stats_log" ]; then
|
||||
packets_log=$(echo "$stats_log" | cut -d'|' -f1)
|
||||
bytes_log=$(echo "$stats_log" | cut -d'|' -f2)
|
||||
echo "iptables_blocklist_rule_bytes{feed=\"$name\",ip_version=\"4\",action=\"log\"} ${bytes_log:-0}"
|
||||
fi
|
||||
|
||||
if [ -n "$stats_drop" ]; then
|
||||
packets_drop=$(echo "$stats_drop" | cut -d'|' -f1)
|
||||
bytes_drop=$(echo "$stats_drop" | cut -d'|' -f2)
|
||||
echo "iptables_blocklist_rule_bytes{feed=\"$name\",ip_version=\"4\",action=\"drop\"} ${bytes_drop:-0}"
|
||||
fi
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
[ "$enabled" != "1" ] && continue
|
||||
|
||||
local stats_log stats_drop packets_log bytes_log packets_drop bytes_drop
|
||||
|
||||
stats_log=$(echo "$iptables_input_stats" | grep " ${IPSET_PREFIX}-${name} " | grep LOG | head -1 | awk '{print $1"|"$2}')
|
||||
stats_drop=$(echo "$iptables_input_stats" | grep " ${IPSET_PREFIX}-${name} " | grep DROP | head -1 | awk '{print $1"|"$2}')
|
||||
|
||||
if [ -n "$stats_log" ]; then
|
||||
packets_log=$(echo "$stats_log" | cut -d'|' -f1)
|
||||
bytes_log=$(echo "$stats_log" | cut -d'|' -f2)
|
||||
echo "iptables_blocklist_rule_bytes{feed=\"$name\",ip_version=\"4\",action=\"log\"} ${bytes_log:-0}"
|
||||
fi
|
||||
|
||||
if [ -n "$stats_drop" ]; then
|
||||
packets_drop=$(echo "$stats_drop" | cut -d'|' -f1)
|
||||
bytes_drop=$(echo "$stats_drop" | cut -d'|' -f2)
|
||||
echo "iptables_blocklist_rule_bytes{feed=\"$name\",ip_version=\"4\",action=\"drop\"} ${bytes_drop:-0}"
|
||||
fi
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
@@ -487,18 +518,15 @@ EOF
|
||||
# TYPE iptables_blocklist_ipset_memory_bytes gauge
|
||||
EOF
|
||||
|
||||
if [ -f "$FEEDS_CONFIG" ]; then
|
||||
while IFS='|' read -r enabled name url type description; do
|
||||
[[ "$enabled" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$enabled" ]] && continue
|
||||
|
||||
mem_v4=$(get_ipset_memory "${IPSET_PREFIX}-${name}")
|
||||
mem_v6=$(get_ipset_memory "${IPSET_PREFIX}-${name}-v6")
|
||||
|
||||
echo "iptables_blocklist_ipset_memory_bytes{feed=\"$name\",ip_version=\"4\"} $mem_v4"
|
||||
echo "iptables_blocklist_ipset_memory_bytes{feed=\"$name\",ip_version=\"6\"} $mem_v6"
|
||||
done < "$FEEDS_CONFIG"
|
||||
fi
|
||||
for feed_line in "${FEEDS_ARRAY[@]}"; do
|
||||
IFS='|' read -r enabled name url type description <<< "$feed_line"
|
||||
|
||||
mem_v4=$(get_ipset_memory "${IPSET_PREFIX}-${name}")
|
||||
mem_v6=$(get_ipset_memory "${IPSET_PREFIX}-${name}-v6")
|
||||
|
||||
echo "iptables_blocklist_ipset_memory_bytes{feed=\"$name\",ip_version=\"4\"} $mem_v4"
|
||||
echo "iptables_blocklist_ipset_memory_bytes{feed=\"$name\",ip_version=\"6\"} $mem_v6"
|
||||
done
|
||||
|
||||
# Conntrack metrics
|
||||
local conntrack_count conntrack_max conntrack_usage
|
||||
@@ -554,9 +582,13 @@ iptables_blocklist_cache_total_size_bytes $cache_size
|
||||
iptables_blocklist_whitelist_size{ip_version="4"} $(get_ipset_size "$WHITELIST_IPSET")
|
||||
iptables_blocklist_whitelist_size{ip_version="6"} $(get_ipset_size "$WHITELIST_IPSET_V6")
|
||||
|
||||
# HELP iptables_blocklist_scrape_timestamp_seconds Unix timestamp of metric generation
|
||||
# TYPE iptables_blocklist_scrape_timestamp_seconds gauge
|
||||
iptables_blocklist_scrape_timestamp_seconds $(date +%s)
|
||||
|
||||
# HELP iptables_blocklist_exporter_runtime_seconds Exporter runtime in seconds
|
||||
# TYPE iptables_blocklist_exporter_runtime_seconds gauge
|
||||
iptables_blocklist_exporter_runtime_seconds $((current_time - start_time))
|
||||
iptables_blocklist_exporter_runtime_seconds $(($(date +%s) - start_time))
|
||||
EOF
|
||||
echo ""
|
||||
}
|
||||
@@ -575,11 +607,13 @@ run_http_server() {
|
||||
{
|
||||
read -r request
|
||||
if [[ "$request" =~ ^GET\ /metrics ]]; then
|
||||
echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain; version=0.0.4\r\n\r"
|
||||
printf "HTTP/1.1 200 OK\r\nContent-Type: text/plain; version=0.0.4; charset=utf-8\r\n\r\n"
|
||||
cache_journal_data
|
||||
cache_feeds_config
|
||||
generate_metrics
|
||||
else
|
||||
echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r"
|
||||
echo "<h1>iptables Blocklist Metrics Exporter</h1>"
|
||||
printf "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n"
|
||||
echo "<h1>iptables Blocklist Metrics Exporter v${SCRIPT_VERSION}</h1>"
|
||||
echo "<p>Per-feed threat blocking statistics</p>"
|
||||
echo "<p><a href='/metrics'>Metrics</a></p>"
|
||||
fi
|
||||
@@ -598,12 +632,17 @@ main() {
|
||||
if [ "$HTTP_MODE" = true ]; then
|
||||
run_http_server
|
||||
elif [ -n "$OUTPUT_FILE" ]; then
|
||||
# Cache data before generating metrics
|
||||
cache_journal_data
|
||||
cache_feeds_config
|
||||
|
||||
# Ensure output directory exists
|
||||
mkdir -p "$(dirname "$OUTPUT_FILE")"
|
||||
|
||||
# Create temp file in /tmp (not in node_exporter directory!)
|
||||
# This prevents node_exporter from seeing partial writes
|
||||
local temp_file=$(mktemp /tmp/iptables_metrics.XXXXXX)
|
||||
local temp_file
|
||||
temp_file=$(mktemp /tmp/iptables_metrics.XXXXXX)
|
||||
|
||||
# Generate metrics to temp file
|
||||
generate_metrics > "$temp_file"
|
||||
@@ -617,10 +656,9 @@ main() {
|
||||
|
||||
# Ensure node_exporter user can read it
|
||||
chmod 644 "$OUTPUT_FILE"
|
||||
|
||||
# Force filesystem sync (optional but helps)
|
||||
sync
|
||||
else
|
||||
cache_journal_data
|
||||
cache_feeds_config
|
||||
generate_metrics
|
||||
fi
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user