поэтому из-за некоторых спамовых атак и прочего я решил включить modsecurity на своем веб-сервере. Я установил Fail2Ban и настроил его так:
выдержка из jail.local:
#
# Custom modsecurity
#
[modsec]
enabled = true
filter = modsec
action = iptables-multiport[name=ModSec, port="http,https"]
sendmail-buffered[name=ModSec, lines=5, dest=user@googlemail.com]
logpath = /var/log/apache2/modsec_audit.log
bantime = 86400
maxretry = 1
И фильтр modsec:
# Fail2Ban configuration file
#
# Author: Florian Roth
[Definition]
failregex = \[.*?\]\s[\w-]*\s<HOST>\s
ignoreregex =
Сам Modsecurity настроен следующим образом (довольно стандартно, за исключением того, что он также должен блокировать доступ при срабатывании правила):
#SecRuleEngine DetectionOnly
SecRuleEngine On
Include /usr/share/modsecurity-crs/*.conf
Include /usr/share/modsecurity-crs/base_rules/*.conf
Include /usr/share/modsecurity-crs/optional_rules/*.conf
SecRequestBodyAccess On
SecRule REQUEST_HEADERS:Content-Type "text/xml" \
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" \
"id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
#SecRequestBodyLimit 13107200
#SecRequestBodyNoFilesLimit 131072
#SecRequestBodyInMemoryLimit 131072
SecRequestBodyLimitAction Reject
#
SecRule REQBODY_ERROR "!@eq 0" \
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
#
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
"id:'200003',phase:2,t:none,log,deny,status:400, \
msg:'Multipart request body failed strict validation: \
PE %{REQBODY_PROCESSOR_ERROR}, \
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
DB %{MULTIPART_DATA_BEFORE}, \
DA %{MULTIPART_DATA_AFTER}, \
HF %{MULTIPART_HEADER_FOLDING}, \
LF %{MULTIPART_LF_LINE}, \
SM %{MULTIPART_MISSING_SEMICOLON}, \
IQ %{MULTIPART_INVALID_QUOTING}, \
IP %{MULTIPART_INVALID_PART}, \
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
SecPcreMatchLimit 1000
SecPcreMatchLimitRecursion 1000
SecRule TX:/^MSC_/ "!@streq 0" \
"id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
SecResponseBodyAccess off
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/
#SecUploadDir /opt/modsecurity/var/upload/
#SecUploadKeepFiles RelevantOnly
#SecUploadFileMode 0600
#SecDebugLog /opt/modsecurity/var/log/debug.log
#SecDebugLogLevel 3
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log
#SecAuditLogStorageDir /opt/modsecurity/var/audit/
SecArgumentSeparator &
SecCookieFormat 0
SecUnicodeMapFile unicode.mapping 20127
SecStatusEngine On
Теперь проблема в том, что fail2ban никогда не блокирует IP, который вызвал нарушение modsecurity. Журнал Fail2ban также не сообщает ничего интересного, только сообщения о запуске и создание тюрьмы. Если происходит нарушение modsecurity, в журнале fail2ban.log ничего не появляется.
Modsecurity работает хорошо, .. любой обход каталога или SQL-инъекции получают ошибку 403. Но никакого тюремного заключения (запрета IP) не происходит.
Что я сделал не так?
TL; DR. Формат журнала изменился, и вам нужен дополнительный \[client [\d\.:]+\])?
:
failregex = ^%(_apache_error_client)s(?: \[client [\d\.:]+\])? ModSecurity:\s+(?:\[(?:\w+ \"[^\"]*\"|[^\]]*)\]\s*)*Access denied with code [45]\d\d (?:.*)$
Формат журнала для libapache2-mod-security2 был изменен, чтобы иметь клиентский дважды.
[client 198.51.100.10:62741] [client 198.51.100.10] ModSecurity: Access denied...
В %(_apache_error_client)s
в filter.d/apache-common.conf
получает IP-адрес из первого.
\[\] \[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[client <HOST>(:\d{1,5})?\]
Как замечает Шон Оуэн, второй нужно добавить к failregex
регулярное выражение, но простое .*
может быть использован, так как соответствует любому количеству символов. \[client [\d\.:]+\])?
более конкретно.
Подробное решение: Обновление фильтра Fail2Ban apache-security.conf для модуля security2 по Kazimer Corp. В этой статье добавлен новый пользовательский filter.d/apache-security2.conf
чтобы избежать его перезаписи дистрибутивом.
У меня тоже была эта проблема, и я обнаружил одну ошибку в apache-modsecurity.conf, которая исправила ее для меня. Может это тебе поможет.
По умолчанию Fail2Ban apache-modsecurity.conf failregex выглядит так:
failregex = ^%(_apache_error_client)s ModSecurity: etc...
Мой журнал ошибок apache выглядит так:
[...time stamp...] [:error] [pid #####] [client ###.###.###.###:#####] [client ###.###.###.###] ModSecurity: etc...
Обратите внимание на 2 клиентских утверждения в журнале apache. Я считаю, что Fail2Ban ищет только одно клиентское заявление. Итак, добавив .*
перед ModSecurity позволяет любому количеству любых символов предшествовать ModSecurity после первого клиентского оператора. Мне любопытно, есть ли лучшее решение проблемы, но это быстрое решение решило его для меня.
Новое регулярное выражение Fail2Ban:
failregex = ^%(_apache_error_client)s .*ModSecurity: etc...
Fail2Ban теперь находит записи журнала modsecurity в журналах apache и соответствующим образом блокирует их.
Надеюсь, это тебе поможет.