Repository navigation
Description
Симптом
na-diagnose показывает адреса в наборах автобана и наблюдения, когда наборы пустые, и завышает счёт на единицу, когда они непустые.
Пустые наборы, а счётчики ненулевые (три ноды OVH, свежий ребут):
# na-diagnose | grep -E 'autoban|suspect'
[*] autoban: v4=3 v6=1
[*] ban-once: suspect (наблюдение) v4=1
# nft list set inet na_filter suspect_v4
table inet na_filter {
set suspect_v4 {
type ipv4_addr
flags dynamic,timeout
timeout 30m
}
}В suspect_v4 нет ни одного элемента, но диагностика печатает v4=1. То же с autoban_v6 — v6=1 при пустом наборе.
Непустой набор считается неверно: на одной ноде autoban_v4 содержит 2 адреса, na-diagnose печатает v4=3; на другой 4 адреса → v4=5.
Причина
scripts/diagnose.sh:484-486 и :517-519:
AB4=$(nft list set inet na_filter autoban_v4 2>/dev/null | grep -c 'timeout\|expires')
AB6=$(nft list set inet na_filter autoban_v6 2>/dev/null | grep -c 'timeout\|expires')
...
SUSP=$(nft list set inet na_filter suspect_v4 2>/dev/null | grep -c timeout)Считаются строки вывода, а не адреса. Две ошибки складываются:
- В заголовке любого динамического набора всегда есть строки
flags dynamic,timeoutиtimeout 30m— они матчатся всегда, отсюда постоянная единица на пустом наборе (grep -c 'timeout\|expires'даёт 1, потому что-cсчитает совпавшие строки, аflags dynamic,timeout— одна из них). nftпечатает элементы по несколько в строке и переносит длинные списки, так что соответствие «строка = адрес» не выполняется и на непустых наборах.
Рядом, в той же функции, аналогичный счётчик сделан правильно (:487):
WLN=$(nft list set inet na_filter whitelist_v4 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | wc -l | tr -d ' ')Почему это стоит чинить
Автобан — единственное место, где видно, кого нода забанила сама. Вечная единица приучает считать строку шумом, и настоящий первый бан (в том числе собственного адреса оператора или адреса панели) теряется на её фоне. Цифра уходит и в --json (scripts/diagnose.sh:151), то есть попадает во флот-мониторинг — Zabbix/Prometheus получают ненулевой ряд там, где банов нет.
Предложение
Считать адреса тем же способом, что и в соседнем WLN, например:
count_set_elems() { # $1 — имя набора, $2 — regex адреса
nft list set inet na_filter "$1" 2>/dev/null | sed -n '/elements = {/,/}/p' \
| grep -oE "$2" | sort -u | wc -l | tr -d ' '
}
AB4=$(count_set_elems autoban_v4 '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')Либо, надёжнее и без разбора текста, — nft -j list set … и подсчёт .nftables[].set.elem | length через jq (в v4 jq уже используется в PRE-шагах). Заодно имеет смысл печатать сами адреса при ненулевом счёте: оператору важно не «сколько», а «кто».
Окружение
node-accelerator 4.0.0 (по исходникам v4.0.1 код не менялся), Debian 12/13, XanMod 6.18.47, FW_MODE=strict, ENABLE_BANONCE=1, ENABLE_PORTSCAN_BAN=1. Проверено на 7 нодах.
Activity
jestivald commentedon Sep 2, 2026
Добавляю ещё два места с тем же корнем — «
grep -cпо выводу утилиты, где есть строка-заголовок». Нашлись при аудите того же флота (14 нод), стоит чинить одним заходом.1.
CrowdSec decisions (активные баны)тоже завышен на 1 —scripts/diagnose.sh:601:DEC="$(cscli decisions list -o raw 2>/dev/null | grep -vc '^$')"cscli decisions list -o rawпечатает CSV с заголовком, и он попадает в счёт. Замер на четырёх нодах: диагностика показывает1 / 4 / 2 / 7, фактических решений0 / 3 / 1 / 6. Особенно неудачен случай пустого списка:decisions: 1читается как «один бан есть», хотя банов нет.Лечится либо
tail -n +2, либо переходом наcscli decisions list -o json | jq length.2. В JSON-ветке та же ошибка, причём без варианта
expires—scripts/diagnose.sh:62-64:Это тот путь, который читает флот-мониторинг, так что ненулевой ряд там, где банов нет, приезжает прямо в Zabbix/Prometheus. Если делать общий хелпер подсчёта элементов набора (предложение из тела issue), он закроет и человекочитаемую ветку, и JSON разом.
Мелочь рядом, на усмотрение:
na-reportмолча оставляет колонку ASN как?на боксах, где нетdig/whois(у нас — на 2 нодах из 4 в одной группе, на остальных колонка заполнена). В шапкеna-report.sh:6это описано как осознанный best-effort, так что не баг, но одна строка вида «ASN не обогащён: нетdig/whois» избавила бы от догадок, почему у соседних нод отчёты выглядят по-разному.jestivald commentedon Sep 2, 2026
Исправлено в v4.1 (PR #42, merge 427b13f): https://github.com/jestivald/node-accelerator/releases/tag/v4.1 — разбор в CHANGELOG, секция v4.1.
protect: счётчики наборов, рейт лога анти-скана, гигиена whitelist (#…
merge v4.1-protect: #32 #35 #38 — счётчики наборов, PORTSCAN_LOG_RATE…
diagnose: датчики меряют тот же срез, что и правила + честный --json …
merge v4.1-diagnose: #27 #30 #31 #32 #34 #35 #37 #38 #39 — датчики ме…