#regex #logging #cakephp #filter #fail2ban
#регулярное выражение #ведение журнала #cakephp #Фильтр #fail2ban
Вопрос:
я хотел бы создать фильтр в fail2ban для поиска и блокировки неверного запроса, например «Класс контроллера * не найден». Для решения этой проблемы я создал файл cakephp.conf в каталоге filter.d в fail2ban. Содержимое:
[Definition]
failregex = ^[0-9]{4}-[0-9]{2}-[0-9]{2}.*Error:.*nStack Trace:n(-.*|n)*n.*n.*nClient IP: <HOST>n$
ignoreregex =
Мой пример журнала ошибок выглядит следующим образом:
...
2020-10-08 19:59:46 Error: [CakeHttpExceptionMissingControllerException] Controller class Webfig could not be found. in /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Controller/ControllerFactory.php on line 158
Stack Trace:
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Controller/ControllerFactory.php:46
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/BaseApplication.php:249
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:77
- /home/myapplication/htdocs/vendor/cakephp/authentication/src/Middleware/AuthenticationMiddleware.php:122
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:77
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php:146
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:58
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Routing/Middleware/RoutingMiddleware.php:172
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Routing/Middleware/AssetMiddleware.php:68
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php:121
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Runner.php:58
- /home/myapplication/htdocs/vendor/cakephp/cakephp/src/Http/Server.php:90
- /home/myapplication/htdocs/webroot/index.php:40
Request URL: /webfig/
Referer URL: http://X.X.X.X/webfig/
Client IP: X.X.X.X
...
- X.X.X заменяются
Но я не могу сопоставить какие-либо IP-адреса. Тестер fail2ban говорит:
root@test:~# fail2ban-regex /home/myapplication/htdocs/logs/error.log /etc/fail2ban/filter.d/cakephp.conf
Running tests
=============
Use failregex filter file : cakephp, basedir: /etc/fail2ban
Use log file : /home/myapplication/htdocs/logs/error.log
Use encoding : UTF-8
Results
=======
Failregex: 0 total
Ignoreregex: 0 total
Date template hits:
|- [# of hits] date format
| [719] {^LN-BEG}ExYear(?P<_sep>[-/.])Month(?P=_sep)Day(?:T| ?)24hour:Minute:Second(?:[.,]Microseconds)?(?:s*Zone offset)?
`-
Lines: 15447 lines, 0 ignored, 0 matched, 15447 missed
[processed in 10.02 sec]
Missed line(s): too many to print. Use --print-all-missed to print all 15447 lines
я не вижу никаких проблем. Вы можете мне помочь? 🙂
Спасибо
Ответ №1:
Проблема в том, что ваш журнал плохо подходит для анализа — это многострочный лог-файл (IP-адрес указывается в другой строке в качестве сообщения об ошибке). Не говоря уже о том, что строка с IP не имеет никакого идентификатора (общая информация со строкой сбоя), может быть еще хуже, если несколько сообщений пересекаются (таким образом, IP-адрес клиента из другого сообщения, которое не является сбоем, приходит после сообщения об ошибке).
Если вы можете изменить формат журнала, лучше сделайте это (чтобы дата, IP и знак сбоя были в одной строке), например, если вы используете nginx, организуйте условное ведение журнала доступа из php-location в случае ошибки, как это. Для получения дополнительной информации см. Fail2ban :: wiki :: Best practice .
Если вы не можете этого сделать (лучше было бы его изменить), вы можете использовать многострочную буферизацию и синтаксический анализ с использованием maxlines
параметра и <SKIPLINES>
регулярного выражения.
Ваш фильтр будет примерно таким:
[Definition]
# we ignore stack trace, so don't need to hold buffer window too large,
# 5 would be enough, but to be sure (if some log-messages crossing):
maxlines = 10
ignoreregex = ^(?:Stack |- /)
failregex = ^s Error: [[^]] ] Controller class S could not be found..*<SKIPLINES>^((?:Request|Referer) URL:.*<SKIPLINES>)*^Client IP: <HOST>
Чтобы протестировать его напрямую, используйте:
fail2ban-regex --maxlines=5 /path/to/log '^s Error: [[^]] ] Controller class S could not be found..*<SKIPLINES>^((?:Request|Referer) URL:.*<SKIPLINES>)*^Client IP: <HOST>' '^(?:Stack |- /)'
Но, как уже было сказано, это действительно некрасиво — лучше найти способ записать все в одну строку.