feat(firewall): add packet statistics tracking for firewall clients
CI / changes (push) Successful in 11s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 29s
CI / web (push) Successful in 1m6s
CI / go (push) Successful in 1m23s
CI / bird2 (push) Successful in 17s
CI / release (push) Successful in 4m42s
CI / changes (push) Successful in 11s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 29s
CI / web (push) Successful in 1m6s
CI / go (push) Successful in 1m23s
CI / bird2 (push) Successful in 17s
CI / release (push) Successful in 4m42s
Enhanced the firewall client functionality by introducing packet statistics tracking, including the cumulative count of packets dropped and accepted. Updated the API to support these new fields and modified the database schema accordingly. Improved the firewall scripts to collect and report packet statistics, ensuring better visibility into client performance. Adjusted the UI components to display packet counts in the clients table, enhancing user experience and monitoring capabilities.
This commit is contained in:
@@ -147,8 +147,119 @@ if [[ -z "${TOTAL// }" ]]; then
|
||||
TOTAL=${#PREFIXES[@]}
|
||||
fi
|
||||
|
||||
PACKETS_DROPPED=0
|
||||
PACKETS_ACCEPTED=0
|
||||
KERNEL_METHOD=""
|
||||
APPLIED_V4=0
|
||||
|
||||
count_ipv4_prefixes() {
|
||||
local n=0 p
|
||||
for p in "${PREFIXES[@]}"; do
|
||||
[[ "$p" == *:* ]] && continue
|
||||
n=$((n + 1))
|
||||
done
|
||||
APPLIED_V4=$n
|
||||
}
|
||||
|
||||
nft_rule_packets() {
|
||||
local line=$1
|
||||
if [[ "$line" =~ counter[[:space:]]+packets[[:space:]]+([0-9]+) ]]; then
|
||||
echo "${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_nft_counters() {
|
||||
local table=inet name=evobgp_blocklist
|
||||
nft list chain "$table" "$name" input >/dev/null 2>&1 || return 0
|
||||
local drop_line
|
||||
drop_line=$(nft -a list chain "$table" "$name" input 2>/dev/null | grep 'ip saddr @v4' | grep drop | head -1 || true)
|
||||
if [[ -n "$drop_line" && "$drop_line" != *counter* ]]; then
|
||||
local handle
|
||||
handle=$(echo "$drop_line" | sed -n 's/.*# handle \([0-9]\+\).*/\1/p')
|
||||
if [[ -n "$handle" ]]; then
|
||||
nft delete rule "$table" "$name" input handle "$handle" 2>>"$LOG_FILE" || true
|
||||
drop_line=""
|
||||
fi
|
||||
fi
|
||||
if [[ -z "$drop_line" ]]; then
|
||||
nft add rule "$table" "$name" input ip saddr @v4 counter drop
|
||||
fi
|
||||
if ! nft list chain "$table" "$name" input 2>/dev/null | grep -qE '[[:space:]]counter[[:space:]]+accept'; then
|
||||
nft add rule "$table" "$name" input counter accept
|
||||
fi
|
||||
}
|
||||
|
||||
collect_nft_packet_stats() {
|
||||
PACKETS_DROPPED=0
|
||||
PACKETS_ACCEPTED=0
|
||||
local line pkts
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == *"ip saddr @v4"* && "$line" == *drop* ]]; then
|
||||
pkts=$(nft_rule_packets "$line")
|
||||
[[ -n "$pkts" ]] && PACKETS_DROPPED=$pkts
|
||||
elif [[ "$line" == *counter* && "$line" == *accept* && "$line" != *@v4* ]]; then
|
||||
pkts=$(nft_rule_packets "$line")
|
||||
[[ -n "$pkts" ]] && PACKETS_ACCEPTED=$pkts
|
||||
fi
|
||||
done < <(nft list chain inet evobgp_blocklist input 2>/dev/null || true)
|
||||
}
|
||||
|
||||
collect_ipset_packet_stats() {
|
||||
PACKETS_DROPPED=0
|
||||
PACKETS_ACCEPTED=0
|
||||
local pkts
|
||||
pkts=$(iptables -L INPUT -v -n -x 2>/dev/null | awk '/match-set evobgp_blocklist_v4/ {print $1; exit}')
|
||||
[[ "$pkts" =~ ^[0-9]+$ ]] && PACKETS_DROPPED=$pkts
|
||||
}
|
||||
|
||||
collect_packet_stats() {
|
||||
case "${KERNEL_METHOD:-$BACKEND}" in
|
||||
nft)
|
||||
ensure_nft_counters
|
||||
collect_nft_packet_stats
|
||||
;;
|
||||
ipset)
|
||||
collect_ipset_packet_stats
|
||||
;;
|
||||
iptables)
|
||||
PACKETS_DROPPED=$(iptables -L INPUT -v -n -x 2>/dev/null | awk '/DROP/ {s+=$1} END {print s+0}')
|
||||
PACKETS_ACCEPTED=0
|
||||
;;
|
||||
*)
|
||||
if command -v nft >/dev/null 2>&1 && nft list chain inet evobgp_blocklist input >/dev/null 2>&1; then
|
||||
KERNEL_METHOD=nft
|
||||
ensure_nft_counters
|
||||
collect_nft_packet_stats
|
||||
elif iptables -L INPUT -v -n -x 2>/dev/null | grep -q 'evobgp_blocklist_v4'; then
|
||||
KERNEL_METHOD=ipset
|
||||
collect_ipset_packet_stats
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
send_client_reports() {
|
||||
collect_packet_stats
|
||||
local km="${KERNEL_METHOD:-$BACKEND}"
|
||||
local report
|
||||
report=$(printf '{"status":"ok","prefix_count":%s,"ip_count":%s,"packets_dropped":%s,"packets_accepted":%s,"source":"cp","kernel_method":"%s"}' \
|
||||
"${TOTAL:-0}" "${APPLIED_V4:-0}" "${PACKETS_DROPPED:-0}" "${PACKETS_ACCEPTED:-0}" "$km")
|
||||
curl -fsS -X POST "${EVOBGP_CP_URL%/}/v1/firewall/apply-report" \
|
||||
-H "Authorization: Bearer ${CLIENT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$report" >/dev/null 2>&1 || true
|
||||
curl -fsS -X POST "${EVOBGP_CP_URL%/}/v1/firewall/heartbeat" \
|
||||
-H "Authorization: Bearer ${CLIENT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"source":"cp"}' >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
if [[ -f "$HASH_FILE" && "$(tr -d '\r\n' <"$HASH_FILE")" == "$HASH" && -n "$HASH" ]]; then
|
||||
log "unchanged hash $HASH — skip kernel apply"
|
||||
count_ipv4_prefixes
|
||||
log "unchanged hash $HASH — skip kernel apply (ipv4=${APPLIED_V4})"
|
||||
send_client_reports
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -184,8 +295,11 @@ apply_nft() {
|
||||
|
||||
nft list chain "$table" "$name" input >/dev/null 2>&1 || {
|
||||
nft add chain "$table" "$name" input '{ type filter hook input priority 0; policy accept; }'
|
||||
nft add rule "$table" "$name" input ip saddr @v4 drop
|
||||
nft add rule "$table" "$name" input ip saddr @v4 counter drop
|
||||
nft add rule "$table" "$name" input counter accept
|
||||
}
|
||||
ensure_nft_counters
|
||||
KERNEL_METHOD=nft
|
||||
APPLIED_V4=${#v4[@]}
|
||||
}
|
||||
|
||||
@@ -202,6 +316,7 @@ apply_ipset() {
|
||||
done
|
||||
iptables -C INPUT -m set --match-set "$set" src -j DROP 2>/dev/null || \
|
||||
iptables -I INPUT -m set --match-set "$set" src -j DROP
|
||||
KERNEL_METHOD=ipset
|
||||
APPLIED_V4=$n
|
||||
}
|
||||
|
||||
@@ -214,6 +329,7 @@ apply_iptables_only() {
|
||||
iptables -C INPUT -s "$p" -j DROP 2>/dev/null || iptables -A INPUT -s "$p" -j DROP
|
||||
n=$((n + 1))
|
||||
done
|
||||
KERNEL_METHOD=iptables
|
||||
APPLIED_V4=$n
|
||||
}
|
||||
|
||||
@@ -227,9 +343,11 @@ clear_block() {
|
||||
iptables) iptables -S INPUT | grep -i evobgp | sed 's/^-A /-D /' | while read -r line; do iptables $line 2>/dev/null || true; done ;;
|
||||
esac
|
||||
APPLIED_V4=0
|
||||
KERNEL_METHOD="${BACKEND:-auto}"
|
||||
}
|
||||
|
||||
APPLIED_V4=0
|
||||
KERNEL_METHOD=""
|
||||
if [[ "${TOTAL:-0}" == "0" || ${#PREFIXES[@]} -eq 0 ]]; then
|
||||
clear_block
|
||||
log "cleared blocklist (api total=${TOTAL:-0}) backend=$BACKEND"
|
||||
@@ -244,14 +362,4 @@ else
|
||||
fi
|
||||
|
||||
echo "$HASH" >"$HASH_FILE"
|
||||
|
||||
REPORT=$(printf '{"status":"ok","prefix_count":%s,"ip_count":%s,"source":"cp"}' "${TOTAL:-0}" "${APPLIED_V4:-0}")
|
||||
curl -fsS -X POST "${EVOBGP_CP_URL%/}/v1/firewall/apply-report" \
|
||||
-H "Authorization: Bearer ${CLIENT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$REPORT" >/dev/null 2>&1 || true
|
||||
|
||||
curl -fsS -X POST "${EVOBGP_CP_URL%/}/v1/firewall/heartbeat" \
|
||||
-H "Authorization: Bearer ${CLIENT_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"source":"cp"}' >/dev/null 2>&1 || true
|
||||
send_client_reports
|
||||
|
||||
Reference in New Issue
Block a user