mysql企业版防火墙需先注册用户并完成recording模式训练生成白名单,再切protecting模式生效;未注册用户或白名单不全会导致sql被拒,且规则不继承、不共享,新增业务须重新录制。

mysql_firewall 插件不是开箱即用的安全补丁,它依赖严格的手动训练和模式识别。没完成录制就切 PROTECTING 模式,所有 SQL 都会被拒绝——这不是漏洞,是设计使然。
确认你用的是 MySQL 企业版并已安装插件
社区版不带 mysql_firewall.so,强行执行 INSTALL PLUGIN mysql_firewall SONAME 'mysql_firewall.so' 会报错 Plugin 'mysql_firewall' is not supported by this MySQL version。检查方式很简单:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'mysql_firewall';
返回空行?说明没装或不是企业版。企业版安装通常需运行 mysql_firewall.sql 脚本(位于 share/ 目录),且重启 mysqld 后才生效。
必须先注册账号再设模式,否则规则不生效
防火墙只对显式注册的账号起作用。哪怕插件已启用,sp_set_firewall_mode('user@host', 'RECORDING') 这一步不能跳过——它本质是向 mysql.firewall_users 表插入记录,并初始化该用户的白名单表项。
常见错误现象:
- 执行了
SET SESSION mysql_firewall_mode = 'PROTECTING',但 SQL 仍能执行 → 因为当前会话用户未注册,防火墙直接忽略 - 用 root 执行
sp_set_firewall_mode成功,但应用连app_user@%时被拒 → 注册时写的是app_user@localhost,而应用连接 Host 是%,匹配不上
务必用完整 USERHOST 字符串注册,大小写和通配符要和实际连接完全一致。
RECORDING 模式下要注意 SQL 指纹生成逻辑
防火墙不是记录原始 SQL,而是提取“指纹”:常量值被替换为 ?,空白标准化,关键字转大写。例如:
SELECT id FROM users WHERE name = 'alice' AND status = 1; → 指纹是 SELECT id FROM users WHERE name = ? AND status = ?
这意味着以下几点必须注意:
- 业务中所有参数化查询变体(不同值、不同字段顺序、JOIN 写法差异)都要在 RECORDING 期间真实跑一遍,否则保护模式下会拦截
- 超长 SQL(如大批量 INSERT)可能被截断,需调大
max_digest_length(默认 1024),否则指纹失真 -
DETECTING模式适合灰度验证:SQL 不被阻断,但非法语句会写入mysql.firewall_whitelist的SQL_TEXT字段(含原始语句),方便人工复核
PROTECTING 模式下被拦截的 SQL 不会留详细日志
默认情况下,被拒语句只记一条警告到错误日志,内容类似:Access denied for user 'app_user'@'10.0.1.5': statement violates firewall policy。想定位具体哪条 SQL 触发拦截,得提前开启:
SET GLOBAL mysql_firewall_trace = ON;
此时被拒语句会写入 mysql.firewall_whitelist 表(SQL_TEXT 列存原始语句,MODE 列为 PROTECTING),但注意:该表仅记录首次匹配失败的指纹,重复失败不追加。
真正容易被忽略的点是:白名单规则不继承、不共享、不自动更新。上线后新增业务逻辑,必须重新进 RECORDING 模式补录,否则用户直接报错——这不是配置问题,是模型生命周期管理的一部分。











