MySQL本身不支持直接配置IP白名单,其白名单机制由bind-address、防火墙规则和mysql.user表中用户Host字段三层叠加构成;必须显式创建带指定IP或网段(如'10.0.2.%')的用户,GRANT须与CREATE USER的Host完全一致,且需确保外层网络控制同步生效。

MySQL 本身不支持“配置IP白名单”这个操作——你不能在配置文件里写 ip-whitelist=...,也不能用一条 SQL 启用白名单开关。所谓白名单,是用户账号的 Host 字段 + 外层网络控制共同构成的分层机制,缺一不可。
CREATE USER 的 Host 字段才是真正的白名单入口
MySQL 认证时只看 User@Host 这一对组合,Host 不匹配,直接报 Access denied for user 'xxx'@'yyy',连密码都不校验。
- 必须显式创建带目标 IP 或网段的用户:
CREATE USER 'app'@'10.0.2.50' IDENTIFIED BY 'pwd';或CREATE USER 'app'@'10.0.2.%' IDENTIFIED BY 'pwd'; -
Host不支持 CIDR(如'10.0.2.0/24'是非法语法),也不支持正则;%和_是仅有的通配符 -
'app'@'localhost'和'app'@'127.0.0.1'是两个独立账号,Unix socket 和 TCP 连接走不同路径,需分别授权 - 8.0+ 版本中,
UPDATE mysql.user SET Host='new'会破坏权限缓存和密码哈希,必须用DROP USER 'app'@'old_host';+ 重建
GRANT 必须与 CREATE USER 的 Host 完全一致
GRANT 不会自动创建用户(8.0+ 默认关闭 NO_AUTO_CREATE_USER),它只授予权限。Host 不一致会导致静默失败或报错 ERROR 1410 (42000)。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 错误写法:
CREATE USER 'app'@'10.0.2.50';,却执行GRANT SELECT ON *.* TO 'app'@'%';→ 权限不会生效 - 正确顺序:先
CREATE USER 'app'@'10.0.2.50';,再GRANT SELECT ON mydb.* TO 'app'@'10.0.2.50';,最后FLUSH PRIVILEGES; - 检查是否生效:
SELECT User, Host FROM mysql.user WHERE User = 'app';,确认输出中存在且 Host 精确匹配
bind-address 和防火墙才是第一道拦截线
如果客户端连不上,90% 不是 Host 配置问题,而是更外层被拦住了。报 Connection refused 或超时,基本可排除 MySQL 权限层。
-
bind-address = 127.0.0.1→ MySQL 只监听本地回环,外部 IP 根本发不出 SYN 包,Host再精确也无意义 - 云数据库(如阿里云 RDS)默认忽略
mysql.user中的Host,白名单必须在控制台安全组里配 - iptables 规则必须按“先 ACCEPT 白名单,再 DROP 其他”的顺序添加,否则
-j DROP会提前终止匹配流程 - iptables 规则重启即失效,Ubuntu 要
iptables-save > /etc/iptables/rules.v4,CentOS 7+ 要iptables-save > /etc/sysconfig/iptables
为什么不能靠 MySQL 日志实时拦截可疑 IP
MySQL 的 general_log 或错误日志里出现 Access denied,说明连接已完成三次握手、MySQL 已分配线程、验证已执行——资源已被消耗,攻击者可能已发起慢速连接洪水。
- 日志是事后记录,默认关闭,写入有延迟,无法毫秒级响应
- 封禁动作必须在系统层做:
ufw insert 1 deny from 203.0.113.45 to any port 3306(Ubuntu)或firewall-cmd --add-rich-rule='rule family="ipv4" source address="203.0.113.45" reject'(RHEL/CentOS) -
DROP USER 'xxx'@'203.0.113.45'没有意义——如果该 IP 本来就没对应用户,这条语句什么都不会阻止
真正起作用的不是某一个配置项,而是 bind-address → 防火墙规则 → mysql.user.Host 这三层叠加。最容易被忽略的是:防火墙规则没保存、bind-address 没改对、以及把 GRANT 当成建用户的替代品。这三处任一出错,白名单就形同虚设。

















