Torrent Blocker: добавить rate limit или возможность отключить log в правиле дропа

Плагин torrentBlocker генерирует в таблице ip remnanode (и в ip6 remnanode6) правила вида

ip saddr @torrent-blocker log prefix "torrent-blocker: " counter name "torrent-blocker" drop

в цепочках input и forward. Каждый дропнутый пакет даёт строку в логе ядра. Одного забаненного клиента, который продолжает переподключаться, хватает, чтобы устроить лог-шторм на всех нодах, где он забанен. Опции, чтобы ограничить частоту или отключить этот лог, в конфиге плагина нет.

Что наблюдали

  • Забаненный клиент продолжал слать SYN на все ноды сквода, порядка сотен пакетов в секунду на каждую, весь blockDuration. По истечении бана переподключался, снова ловил бан, и цикл повторялся.
  • Каждая нода писала десятки тысяч строк torrent-blocker: в минуту в kmsg. На нодах с 2 vCPU это стоило:
    • systemd-journald: ~10% CPU, ротация журнала каждые несколько минут
    • rsyslog: ~10% CPU, syslog и kern.log росли на гигабайты в сутки
    • promtail (читает journald): до 30% CPU и лишний исходящий трафик в Loki
    • load average стабильно выше числа ядер при в основном простаивающем CPU
  • Заглушить это снаружи плагина не получается:
    • RateLimit* у journald на сообщения ядра не действует (у kmsg нет юнита-отправителя).
    • sysctl net.netfilter.nf_log.2 = NONE не помогает: nft log передаёт свой nf_loginfo, и nf_log_packet() берёт логгер из глобальной таблицы loggers[pf][type], а не из per-netns default (см. net/netfilter/nf_log.c и nft_log.c).
    • Править таблицу ip remnanode руками бесполезно, она пересоздаётся при рестарте ноды.
    • Остаётся только резать последствия в rsyslog и promtail, но пакеты в ядро всё равно приходят.

Предложение

Любой из вариантов, а лучше оба:

  1. Разнести log и drop на два правила и ограничить первое:
ip saddr @torrent-blocker limit rate 10/minute burst 20 packets log prefix "torrent-blocker: "
ip saddr @torrent-blocker counter name "torrent-blocker" drop

Бан работает как раньше, счётчик считает все пакеты, а в логе остаётся достаточно строк, чтобы видеть, кто и когда заблокирован.

  1. Добавить в конфиг плагина ключ, например logBlocked: true|false или logRateLimit: "10/minute", с текущим поведением по умолчанию, чтобы ничего не сломать у тех, кто на лог полагается.

То же имеет смысл сделать для ingress-filter-ip: у него та же конструкция log ... drop без лимита. Egress-правила логов не пишут, их это не касается.

Почему это важно

Забаненный клиент по определению ведёт себя плохо и будет ломиться. Сейчас стоимость одного такого клиента для оператора это загрузка CPU и диска на всех нодах, пропорциональная его настойчивости, и с этим ничего нельзя сделать со стороны ноды.

NFTABLES_LOGGING=false