Отчёт о ходе разработки f2b

Sep  9 23:06:55 f2b[10753]: jail 'asterisk': new ip found -- 89.163.146.93
Sep  9 23:09:50 f2b[10753]: jail 'asterisk': new ip match -- 89.163.146.93 (2/3)
Sep  9 23:12:43 f2b[10753]: jail 'asterisk': new ip match -- 89.163.146.93 (2/3)
Sep  9 23:15:35 f2b[10753]: jail 'asterisk': new ip match -- 89.163.146.93 (2/3)
Sep  9 23:18:40 f2b[10753]: jail 'asterisk': banned ip 89.163.146.93 for 1.0hrs
# ... попался, ублюдок!

Продолжаем неспешно пилить чудо-программу.

С момента анонса темпы пиления упали, т.к. сказывается "эффект УМВР", но тем не менее сделано следующее:


Control socket для демона

Над реализацией пришлось изрядно посидеть и поэкспериментировать.

Изначально я хотел использовать SOCK_STREAM и обычный текстовый протокол. Посидел, написал свою реализацию getline для сокета, простенький аналог bison'а для разбора команд и стало мне грустно от осознания объёма кода, который будет это всё обслуживать.

Плюсы:

Минусы, навскидку:

...ну и не стоит забывать, что ломание кривонаписанного парсера текстового протокола - это старая-добрая традиция, ещё начиная со времён sendmail'а и irc. А уж как народ с самой почтой развлекается, это просто песня.

Поэтому плюнул я на это дело и взял SOCK_DGRAM.

Минусы:

Но плюсов в моём случае - много:

Простенький клиент

Появился в силу предыдущего пункта.

Сейчас он умеет все базовые операции: показать статистику, забанить/разбанить, перечитать конфиг, завершиться.

Есть задел и на больше - точная настройка конкретного jail'а, добавление регэкспов "на лету".

redis-backend

Написан черновик, но пока не тестировался: чтобы его использовать, нужен парный ему source, а source у нас сейчас прибит гвоздями к файлам.

Растущее время поиска/бана для конкретного ip

Думаю, кто пробовал настроить fail2ban видел в логах "умных" ботов, после первого бана подстраивающих частоту запросов так, чтоб не попасть под раздачу.

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

На примере: допустим у нас настроено ограничение 5 неправильных запросов в 5 минут. При фиксированном времени обнаружения бот может сделать 4 запроса, и пойти покурить, передав эстафету другому боту.

При динамическом времени обнаружения, на эти 4 запроса в первый раз боту придётся так же подождать 5 минут, а вот в следующий раз - уже 5,5 минут, и т.д.

Вторая идея, логически продолжающая первую - увеличение времени бана при рецидивах. Это тоже сделано, потому что важно не просто забанить бота, но и порвать ему шаблон.

Третья идея в этом плане - смотреть на "соседей" забаненного ip, и расширять бан до подсети при необходимости. Этого у меня пока не реализовано.

CMake

Багфиксы

Без них - никуда. Исправлена пара сегфолтов в коде фильтров. После этого были сделаны оргвыводы, и притащен strlcpy() на замену snprintf()/strncpy() из директории уровнем выше.

Обеспечена сборка и работа под бзд. Там же был пойман забавный баг:

fgets(buf, bufsize, file->fd);

...это не работает, если у file->fd выставлен EOF, даже если файл после этого прибавил пару гигабайт. Решение - сбрасывать руками перед каждым вызовом через clearerr(). Допускаю, что это implementation-defined поведение.

Ну и кое-что по мелочи, типа выключения буферизации у логфайла.


  1. Это планируется, пока играюсь с point-to-point через unix-сокет. ↩