为 fail2ban 创建一个 cakephp 过滤器

Create a cakephp filter for fail2ban

我想在 fail2ban 中创建一个过滤器来搜索和阻止错误的请求,例如“找不到控制器 class *。” 对于这个问题,我在 fail2ban 的 filter.d 目录中创建了一个 cakephp.conf 文件。内容:

[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: [Cake\Http\Exception\MissingControllerException] 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
...

但是我无法匹配任何 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

我看不出有什么问题。你能帮助我吗? :) 谢谢

问题是您的日志不适合解析 - 它是一个多行日志文件(IP 作为失败消息出现在其他行)。 更不用说带有 IP 的线路没有任何 ID(线路故障的常见信息),如果有几条消息交叉,情况可能会更糟(因此来自其他不是故障的消息的客户端 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 |- /)'

但如前所述,它真的很难看 - 最好找到在一行中记录所有内容的方法。