MySQL IP白名单本质是用户Host字段精确匹配,需CREATE USER时显式指定IP或网段(如'10.0.2.50'或'10.0.2.%'),不支持CIDR;GRANT必须与Host完全一致,且须配合bind-address和防火墙分层防护。

MySQL 没有“开启白名单”的开关,所谓 IP 白名单,就是创建用户时把 Host 字段写成具体 IP 或网段——它不是附加配置,而是账号身份的一部分。
CREATE USER 时必须显式指定 Host
你不能先建一个 'app'@'%',再指望通过某条命令把它变成白名单。Host 是账号不可分割的标识,建错就得删了重来。
- 正确写法:
CREATE USER 'app'@'10.0.2.50' IDENTIFIED BY 'pwd';(单 IP) - 允许子网:
CREATE USER 'app'@'10.0.2.%' IDENTIFIED BY 'pwd';(% 只匹配 IPv4 段,不支持 CIDR 如10.0.2.0/24) - IPv6 必须写全:
CREATE USER 'app'@'2001:db8::1' IDENTIFIED BY 'pwd';(%不匹配 IPv6) -
'app'@'localhost'和'app'@'127.0.0.1'是两个独立账号,Unix socket 和 TCP 连接走不同路径
GRANT 必须与 CREATE USER 的 Host 完全一致
执行 GRANT 时如果 Host 不对,MySQL 不会提示“用户不存在”,而是直接报错 ERROR 1410 (42000): You are not allowed to create a user with GRANT——这是最常见的权限配置失败原因。
- 错误示例:
CREATE USER 'app'@'10.0.2.50',却执行GRANT ... TO 'app'@'10.0.2.%' - 正确顺序:建用户 → 授权 → 刷新:
GRANT SELECT ON mydb.* TO 'app'@'10.0.2.50'; FLUSH PRIVILEGES; - 想改已有账号的 Host?别 UPDATE
mysql.user表——8.0+ 版本会破坏密码哈希和权限缓存;应DROP USER 'app'@'old_host';后重建
bind-address 和防火墙才是连接能否抵达 MySQL 的前提
如果你连都连不上(Connection refused / timeout),大概率不是 Host 配错了,而是更外层拦住了。
-
bind-address = 127.0.0.1→ 外部 IP 根本发不到 MySQL,Host再精确也没用 - 云数据库(如阿里云 RDS)忽略
mysql.user中的Host,白名单必须在控制台安全组里配 - Docker 部署时,
-p 3306:3306默认映射到所有接口,应限制为-p 10.0.2.10:3306:3306或配合宿主机iptables - 系统防火墙规则顺序很重要:必须先
ACCEPT白名单 IP,再DROP其他所有--dport 3306流量,否则白名单无效
真正难的不是写几条 SQL,而是分清哪一层该管什么:MySQL 层只认账号 + Host,网络层才管 IP 到达与否。漏掉任意一层,白名单就形同虚设。


















