diff --git a/projects/f2b/2016-09-11/index.markdown b/projects/f2b/2016-09-11/index.markdown new file mode 100644 index 0000000..5f3eb93 --- /dev/null +++ b/projects/f2b/2016-09-11/index.markdown @@ -0,0 +1,128 @@ +--- +title: Отчёт о ходе разработки f2b +tags: devel, 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 + # ... попался, ублюдок! + +Продолжаем неспешно пилить чудо-программу. + +С момента [предыдущего](/blog/2016/03/17/f2b/) поста темпы пиления упали, т.к. сказывается "эффект УМВР", +но тем не менее сделано следующее: + +--- + +Control socket для демона +------------------------- + +Над реализацией пришлось изрядно посидеть и поэкспериментировать. + +Изначально я хотел использовать ``SOCK_STREAM`` и обычный текстовый протокол. +Посидел, написал свою реализацию getline для сокета, +простенький аналог bison'а для разбора команд +и стало мне грустно от осознания объёма кода, который будет это всё обслуживать. + +Плюсы: + +* с этим может работать любая утилита с помощью netcat/telnet + +Минусы, навскидку: + +* разбор текстовых команд в виде нескольких токенов - достаточно сложное занятие. +Нужно вычленить строку (в экстремальном случае она может приходить по байту за раз), +побить её на токены, проверить синтаксис, количество аргументов. +Нужно достаточно сложное управление входным буфером: +если не распарсилось полностью - дождаться недостающего, осталось лишнее - хранить. +* перечисленное выше - работает с недоверенными данными из сети -> всё это надо выписывать с упором на безопасность. +* открывается дорога всем нашим любимым сетевым шалостям: +типа открытия 500 соединенений разом и заливки в каждое из них мегабайтной строки, +без малейших признаков "\r" или "\n" -> скажите "здравствуй" исчерпанию памяти или fd. +* ну и такой мелкий штрих: если мы хотим встроенный хелп - из-за тупости клиента, +будьте любезны тащить описание команд на серверную сторону. + +...ну и не стоит забывать, что ломание кривонаписанного парсера текстового протокола - это +старая-добрая традиция, ещё начиная со времён sendmail'а и irc. +А уж как народ с самой почтой развлекается, это просто песня. + +Поэтому плюнул я на это дело и взял ``SOCK_DGRAM``. + +Минусы: + +* нужен спецклиент +* негарантированная доставка + +Но плюсов в моём случае - много: + +* разом снимется проблема с разбором сообщений: readv + проверка длинны пакета. +* никаких висящих соединений: пришёл пакет - обработал, опционально ответил. +* бесплатно получаем управление несколькими инстансами в пределах локальной сети (udp+igmp)[^fn1]. +* возможность использовать тот же код в качестве source/backend: +если один хост в сети засёк пидараса - делается рассылка через тот же igmp и все остальные его дружно банят +ещё до того, как он полезет сканить порты на следующий узел. + +Простенький клиент +------------------ + +Появился в силу предыдущего пункта. + +Сейчас он умеет все базовые операции: показать статистику, забанить/разбанить, перечитать конфиг, завершиться. + +Есть задел и на больше - точная настройка конкретного jail'а, добавление регэкспов "на лету". + +redis-backend +------------- + +Написан черновик, но пока не тестировался: чтобы его использовать, нужен парный ему source, +а source у нас сейчас прибит гвоздями к файлам. + +Растущее время поиска/бана для конкретного ip +--------------------------------------------- + +Думаю, кто пробовал настроить fail2ban видел в логах "умных" ботов, +после первого бана подстраивающих частоту запросов так, чтоб не попасть под раздачу. + +Это работает, но только до той поры, пока период обнаружения фиксирован. +Если он уменьшается по мере того, как растёт число запросов - к ним приходит песец. + +На примере: допустим у нас настроено ограничение 5 неправильных запросов в 5 минут. +При фиксированном времени обнаружения бот может сделать 4 запроса, и пойти покурить, +передав эстафету другому боту. + +При динамическом времени обнаружения, на эти 4 запроса в первый раз боту придётся +так же подождать 5 минут, а вот в следующий раз - уже 5,5 минут, и т.д. + +Вторая идея, логически продолжающая первую - увеличение времени бана при рецидивах. +Это тоже сделано, потому что важно не просто забанить бота, но и порвать ему шаблон. + +Третья идея в этом плане - смотреть на "соседей" забаненного ip, +и расширять бан до подсети при необходимости. Этого у меня пока не реализовано. + +CMake +----- + +* добавлена поддержка GNUInstallDirs +* наведён порядок с путями конфигов, постараюсь больше не менять. + +Багфиксы +-------- + +Без них - никуда. Исправлена пара сегфолтов в коде фильтров. +После этого были сделаны оргвыводы, и притащен strlcpy() +на замену snprintf()/strncpy() из директории уровнем выше. + +Обеспечена сборка и работа под бзд. Там же был пойман забавный баг: + + fgets(buf, bufsize, file->fd); + +...это не работает, если у ``file->fd`` выставлен EOF, даже если файл после этого прибавил пару гигабайт. +Решение - сбрасывать руками перед каждым вызовом через clearerr(). +Допускаю, что это ``implementation-defined`` поведение. + +Ну и кое-что по мелочи, типа выключения буферизации у логфайла. + +[^fn1]: Это планируется, пока играюсь с point-to-point через unix-сокет. diff --git a/projects/f2b/2017-01-04/index.markdown b/projects/f2b/2017-01-04/index.markdown new file mode 100644 index 0000000..a11a4e6 --- /dev/null +++ b/projects/f2b/2017-01-04/index.markdown @@ -0,0 +1,105 @@ +--- +title: Отчёт о ходе разработки f2b +tags: devel, f2b +--- + + Jan 4 19:52:33 f2b[4090]: jail 'portknock': restored ban of ip 85.121.165.15 (23.9hrs remain) + Jan 4 19:52:33 f2b[4090]: jail 'portknock': restored ban of ip 95.154.82.19 (23.9hrs remain) + Jan 4 19:52:33 f2b[4090]: jail 'portknock': restored ban of ip 78.171.148.130 (24.0hrs remain) + Jan 4 19:52:33 f2b[4090]: jail 'portknock': restored ban of ip 221.194.47.224 (24.0hrs remain) + # ... сидеть, обезьяны, срок ещё не вышел! + +С момента предыдущего [отчёта](/blog/2016/09/11/f2b-devel-status/) сделано следующее: + +--- + +source сделан загружаемым модулем +---------------------------------- + +... по аналогии с фильтром и бакендом. Ранее было прибито к файлам. + +Тоже через libdl, интерфейс смотреть в sources/source.h, примеры реализации - в том же каталоге, любой /*.c/ + +redis source/backend +-------------------- + +Предыдущий пункт позволил реализовать source для redis. + +Это позволило "делиться" банами с другими хостами. +Сейчас оно работает уже пару месяцев без перерыва, 4 хоста с f2b + 1 redis-сервер. + +mcast source/backend +-------------------- + +Также добавлен аналог предыдущего модуля, но работающий через multicast, +что позволяет обойтись без redis-сервера, но ограничивает расположение +хостов одним multicast-доменом (т.е. одна и та же сеть, если не применять +костыль в виде igmpproxy и подобного). + +Пока недостаточно оттестировано. + +portknock source +---------------- + +Для выявления заведомых ботов. Позволяет повесить, например, /типа/ открытый telnet, +а по коннекту -- банить подключившегося, ибо нехер. + +Если скомбинировать с вышеупомянутым redis'ом - получим распределённый honeypot. +Любой пидорас, спаленный за сканированием этого "telnet"'а будет немедленно забанен на всех хостах с f2b +(а то и во всей защищаемой сети в случае граничного роутера). + +Приготовьтесь сразу юзать ipset или нечто подобное, хостов будет много. +За три часа часа работы в таком режиме набегает под две сотни, а за сутки - тысяча-полторы хостов (при бане на сутки). + +doxygen и прочая документация +----------------------------- + +В всех заголовках добавлены doxygen'овы комментарии для структур, дефайнов и функций. +Вобщем, задокументировано всё, на что оно ругалось при генерации доков. + +Также, существенно расширены доки по установке и настройке, добавлены примеры конфигов. + +state +----- + +Добавлена возможность хранить и восстанавливать список банов при рестарте. +Сделано тупо через файлик с записямии, когда какой ip был забанен и когда его выпускать. + +Особой производительности там не требуется, файлик переписывается только при очередном бане. +Если будет тормозить - тогда будем думать. + +Клиент / управление +------------------- + +Реализована команда set для jail'ов. Теперь порог срабатывания и прочие параметры можно поменять без рестарта. +Реализована перезагрузка списка regexp'ов для фильтра (аналогично). + +Для пришедшего пакета теперь проверяется количество аргументов. +Сделано с прицелом на будущую реализацию управления по igmp. + +Утилиты +------- + +Переработаны утилитки для тестов различных компонентов. +Также, они переименованы для приведения к одному виду /f2b-*-test/. +Все утилиты сейчас могут использовать тот же кусок конфига, +что и сам демон (с минимальными исправлениями, вроде пути к библиотеке). + +Переименованы некоторые команды, в частности: + +* ban -> ip ban +* show -> ip status +* release -> ip release +* regex stats -> filter stats +* regex add -> regex reload + +TODO +---- + +Что ещё надо будет в ближайшее время. + +* select() вместо sleep() -- при большом списке файлов плывёт время обработки. +* белый список для подсетей (реализация ipv4-only сложности не представляет, но хотелось бы её сделать и для ipv6 тоже) +* реорганизовать имена загружаемых модулей (сложности с cmake, оно очень сильно хочет сделать именование вида libFOO.so) +* reload для конкретного jail'а +* добавить возможность использовать как просто udp, так и udp multicast для клиента (сейчас - только unix-сокет) diff --git a/projects/index.markdown b/projects/index.markdown index 01e5232..af7b09b 100644 --- a/projects/index.markdown +++ b/projects/index.markdown @@ -8,4 +8,8 @@ title: Проекты * [SMS Notification System (SNS)](/projects/sns/) * [Редактирование торрент-файлов](/projects/torrents_editor/) -* [f2b, легковесная замена fail2ban](/articles/2016/03/17/f2b/) + +* f2b, легковесная замена fail2ban + * [анонс, 2016-03-17](/articles/2016/03/17/f2b/) + * [отчёт о разработке, 2016-09-11](/projects/f2b/2016-09-11/) + * [отчёт о разработке, 2017-01-04](/projects/f2b/2017-01-04/)