Fail2ban通过自定义filter匹配MySQL错误日志中的“Access denied for user 'u'@'ip'”行,结合log_error_verbosity=3开启记录、正确配置logpath路径、failregex提取、jail绑定firewallcmd-rich-rules动作,并验证SELinux与firewalld zone设置,实现IP封禁。

Fail2ban怎么识别MySQL的登录失败日志
Fail2ban 默认不监控 MySQL 日志,因为 MySQL 的错误日志格式和位置与 SSH、Apache 等服务不同,必须手动指定日志路径和匹配规则。关键点在于:MySQL 本身默认不记录连接失败详情到系统日志(/var/log/messages 或 /var/log/secure),而是写入自己的错误日志(如 /var/log/mysqld.log 或 /var/lib/mysql/hostname.err),且需开启 log_warnings = 2 才会记录拒绝连接(如密码错误、用户不存在)。
实操建议:
- 确认 MySQL 已启用警告日志:检查
my.cnf中是否含log_warnings = 2(RHEL/CentOS 7 上通常在/etc/my.cnf或/etc/my.cnf.d/server.cnf),修改后重启mysqld - 找到真实日志路径:运行
mysql -e "SHOW VARIABLES LIKE 'log_error';",输出值即为日志文件路径(常见为/var/log/mariadb/mariadb.log或/var/log/mysqld.log) - 确保 Fail2ban 能读取该文件:该日志文件属主通常是
mysql:mysql,而fail2ban进程以root运行,但日志轮转后可能权限异常;建议用setfacl -m u:fail2ban:r /var/log/mariadb/mariadb.log显式授权(比改 chmod 更安全)
怎么写MySQL专用的failregex正则表达式
MySQL 错误日志中暴力破解的典型线索是「Access denied for user」,但原始日志行不含 IP 地址——它只记录客户端 socket 或 host 名,而 Fail2ban 必须提取 IP 才能封禁。实际日志样例如下:
2026-09-30T14:22:03.123456Z 123 [Warning] Access denied for user 'admin'@'192.168.5.22' (using password: YES)
这个格式里 IP 在单引号内、紧跟 @ 符号,所以正则不能只匹配文字,还得捕获 IP 段。官方 jail.conf 不提供 MySQL 模板,得自建 filter。
实操建议:
- 新建
/etc/fail2ban/filter.d/mysqld-auth.conf,内容包含:[Definition]<br>failregex = ^.*Access denied for user .*@'<host>' \(using password: .*\)$<br>ignoreregex =</host>
-
是 Fail2ban 内置宏,自动匹配 IPv4/IPv6,比手写(?:::f{4,6}:)?(?P更可靠\S+) - 测试正则是否生效:
fail2ban-regex /var/log/mariadb/mariadb.log /etc/fail2ban/filter.d/mysqld-auth.conf,看 “Lines matched” 是否 > 0 - 避免误匹配:如果日志含本地 socket(如
'localhost'或'127.0.0.1'),可在ignoreregex加localhost|127\.0\.0\.1
怎么配置jail让Fail2ban联动firewalld或iptables
RHEL/CentOS 7 默认用 firewalld,而 Fail2ban 的 action_ 配置决定了封禁方式。直接写 iptables 规则虽快,但会绕过 firewalld 管理,导致重启 firewalld 后规则丢失;正确做法是调用 firewallcmd-rich-rules 动作。
实操建议:
- 编辑
/etc/fail2ban/jail.local(不要改jail.conf),添加:[mysqld-auth]<br>enabled = true<br>filter = mysqld-auth<br>logpath = /var/log/mariadb/mariadb.log<br>maxretry = 3<br>findtime = 600<br>bantime = 3600<br>action = %(action_firewallcmd-rich-rules)s
-
action_firewallcmd-rich-rules会调用firewall-cmd --add-rich-rule=...,兼容 firewalld 的 zone 和持久化设置 - 若坚持用 iptables(如已停 firewalld),改用
action_iptables,但需确认iptables-services已安装并启用:yum install iptables-services && systemctl enable iptables - 启动前务必执行
fail2ban-client reload,而非仅 restart —— reload 可热加载新 jail,避免中断其他防护
为什么封了IP却还能连上MySQL
最常被忽略的点:Fail2ban 封的是**入向连接**,但 MySQL 默认监听 127.0.0.1 或 0.0.0.0,而 firewalld 的 rich rule 默认作用于 public zone;如果 MySQL 客户端走的是内网、容器网络或 localhost,封禁可能完全不生效。
排查要点:
- 确认 MySQL 绑定地址:检查
my.cnf中bind-address值,若为127.0.0.1,外部根本连不上,Fail2ban 就无意义;应设为0.0.0.0或具体业务网段 IP - 检查 firewalld zone:运行
firewall-cmd --get-active-zones,再查对应 zone 是否启用了mysql服务或开放了 3306 端口:firewall-cmd --zone=public --list-ports - 验证封禁是否落地:触发一次失败登录后,执行
fail2ban-client status mysqld-auth查 banned IP 列表,再运行firewall-cmd --list-rich-rules | grep reject看规则是否存在 - 注意 SELinux 干扰:RHEL 7 默认启用 SELinux,若
fail2ban-server无法读日志或调用 firewall-cmd,检查ausearch -m avc -ts recent | audit2why,必要时临时设setsebool -P fail2ban_read_log on
Fail2ban 对 MySQL 的防护效果高度依赖日志粒度、正则精度和防火墙上下文一致性;三者中任意一环松动,就会出现“看着封了,其实没用”的情况。尤其 RHEL 7 环境下,firewalld + SELinux + MariaDB 日志路径分散,必须逐层验证,不能只靠配置完就认为万事大吉。











