首先给出明确结论:要为 MySQL 配置防暴力破解机制,并非简单设置几个参数就能生效。**FAILED_LOGIN_ATTEMPTS** 和 **PASSWORD_LOCK_TIME** 这两个参数必须成对使用,并且依赖 `validate_password` 插件处于启用状态。此外,它们仅对采用 `caching_sha2_password` 或 `mysql_native_password` 认证插件的用户有效;单独配置其中一个参数等同于未设。参数单位是天,锁定到期后不会自动解除,必须有一次成功的登录才能重置失败计数。

FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME 必须成对设置
如果单独执行 ALTER USER 'u'@'%' FAILED_LOGIN_ATTEMPTS 3,MySQL 会直接忽略该指令,不会产生任何效果。这两个参数是硬性捆绑的——缺一不可,排列顺序无关紧要,但缺少任意一个就会完全失效。
- 新建用户时,必须一次性完整书写:
CREATE USER 'api'@'%' IDENTIFIED WITH caching_sha2_password BY 'pwd' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 0.04167(锁定1小时) - 对已有用户进行修改时,连认证插件也必须一同更换:
ALTER USER 'api'@'%' IDENTIFIED WITH caching_sha2_password BY 'newpwd' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 0.04167 PASSWORD_LOCK_TIME的单位为"天",因此锁定5分钟需要写成0.00347(5 ÷ 1440)。如果设为0,表示永久锁定,而非"不锁定"- 锁定期满后,不会自动解锁——必须有一次成功的登录才能重置失败计数,同时清除
account_locked = 'Y'的状态
validate_password 插件不是可选,而是必需
即使参数书写完整、认证插件也匹配,但如果 `validate_password` 未被启用,失败登录根本不会累积计数。你在 `mysql.user` 表中永远看不到 `account_locked = 'Y'`,错误日志中也无法搜索到 `Too many failed login attempts` 这条信息。
- 检查是否激活:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'validate_password',状态必须为 `ACTIVE` - 启用方式有两种:在配置文件中添加
plugin_load_add = validate_password.so后重启;或者直接执行INSTALL PLUGIN validate_password SONAME 'validate_password.so' - 启用后会自动激活密码强度策略(例如 `validate_password.length`),这可能会影响已有的创建用户脚本,建议提前做好验证
connection_control 插件必须安装两个组件才生效
只安装 `CONNECTION_CONTROL` 并不足够——它负责延时逻辑,但失败计数依赖于配套组件 `CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS`。如果后者未安装,执行 `SHOW VARIABLES LIKE '%connection_control%'` 将无法看到任何相关变量,所有配置均无效。
- 必须按顺序执行:先执行
INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so',再执行INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so' connection_control_failed_connections_threshold参数如果不写入 `my.cnf` 则不会持久化——通过 `SET GLOBAL` 设置后,重启即失效- 注意单位:
connection_control_min_connection_delay的单位是毫秒,而非秒;`max` 值设置过高(例如 60000)可能会卡死连接池,引发 `Too many connections` 'root'@'localhost'和所有本地连接默认被绕过,这是设计的正常行为,并非漏洞
别信“%”通配符,IP 白名单才是第一道墙
只要 `3306` 端口对公网开放,并且用户的 Host 设置为 `'%'`,暴力破解的风险就始终真实存在。MySQL 自身的账户锁定仅仅是最外层防线,不能替代网络隔离。
- 禁止远程 root 登录:
DELETE FROM mysql.user WHERE user='root' AND host!='localhost',然后执行FLUSH PRIVILEGES - 业务账号必须绑定具体的 IP 或内网段:
CREATE USER 'webapp'@'192.168.10.50' IDENTIFIED BY 'strong_pwd' - 云环境务必在安全组层面只放行应用服务器的内网 IP;物理机使用 `iptables` 或 `ufw` 严格限制源地址
bind-address绝不可设为 `0.0.0.0`,应优先设为 `127.0.0.1` 或内网地址
