failed_login_attempts仅锁定账号,不封ip;需结合fail2ban解析错误日志、proxysql双维度限流或防火墙实现真实ip拦截。

MySQL 本身不直接提供“按 IP 封禁”或“自动踢出爆破连接”的能力,FAILED_LOGIN_ATTEMPTS 只能锁定用户账号,且必须搭配 caching_sha2_password 和 validate_password 插件才生效——它不记录、不区分来源 IP,更不会主动封禁网络层。真要拦住恶意爆破,得靠组合手段。
为什么 FAILED_LOGIN_ATTEMPTS 不拦 IP?
这个参数只作用于单个 MySQL 用户账户,触发条件是「该用户在同一个连接上下文中连续输错密码」。但攻击者通常用不同 IP 或脚本轮询多个用户,FAILED_LOGIN_ATTEMPTS 对这种场景完全无效。而且:
- 它不写入任何日志字段供外部程序提取 IP
- mysql.user 表里没有 failed_login_ip 或类似列
- 错误提示统一为 Access denied for user 'x'@'y',y 是账号定义的 host(比如 '%'),不是真实连接 IP
connection_control 插件能延迟,但不能封 IP
connection_control 插件的作用是给失败连接加延迟(如第 3 次失败后强制等 1 秒再响应),它不拒绝连接、不记录源 IP、也不调用防火墙。关键限制:
- connection_control_failed_connections_threshold 是全局阈值,对所有用户共用,无法按 IP 或用户单独设限
- 延迟时间单位是毫秒,但实际效果取决于客户端是否遵守 TCP 重试逻辑,很多爆破工具根本不 care
- 必须同时加载两个组件:INSTALL PLUGIN connection_control SONAME 'connection_control.so'; 和 INSTALL PLUGIN connection_control_failed_login_attempts SONAME 'connection_control.so';,漏一个就静默失效
- 配置项如 connection-control-min-connection-delay 必须写在 my.cnf 里并重启 mysqld,运行时 SET GLOBAL 不生效
真正能封 IP 的只有 fail2ban + 日志解析
这是生产环境最可靠、落地最简单的方案,依赖 MySQL 错误日志中真实的失败记录。前提是:
- 在 my.cnf 中启用详细错误日志:log_error_verbosity = 3(MySQL 8.0.13+)
- 确保日志包含类似这样的行:[Warning] [MY-010054] [Server] Access denied for user 'root'@'192.168.1.100' (using password: YES)
- fail2ban 的 jail.local 需配 [mysqld-auth] 段,正则匹配 Access denied.*@'(?P<host>\S+)'</host>
- 封禁动作调用 iptables 或 ufw,例如:action = %(action_)s iptables-multiport[name=mysqld, port="3306", protocol=tcp]
- 注意:MySQL 默认不记录失败尝试的客户端端口,所以 fail2ban 只能按 IP 封,不能区分同一 IP 下不同用户的尝试
ProxySQL 是唯一能做 IP+用户双维度限流的代理层
如果你已在架构中使用 ProxySQL(或有能力引入),它是目前唯一支持滑动窗口计数、按 username + src_ip 组合限流的方案:
- 在 mysql_users 表中设置 max_connections 控制并发,但这不是防爆破
- 真正要用的是自定义监控脚本 + stats_mysql_connection_pool 表,定期查 ConnUsed 和 ConnErr 字段,识别异常模式
- 更推荐做法:在 ProxySQL 的 query rules 中插入 Lua 脚本,对每个 user@ip 维护内存计数器,超阈值返回 OK 但不转发到后端(模拟成功避免暴露逻辑)
- 缺点:增加了链路复杂度;Lua 脚本需手动维护;计数器不持久,ProxySQL 重启即清零
别指望 MySQL 自身完成网络层防护。FAILED_LOGIN_ATTEMPTS 是账号级兜底,connection_control 是体验层减速,而真实拦截必须交由操作系统(fail2ban)、网络设备(WAF/安全组)或前置代理(ProxySQL)来执行——它们才能看到原始 IP 并做出动作。











