mysql ip白名单本质是用户账号host字段匹配,需create user时指定ip/网段,grant必须与host一致;常见问题包括host不匹配、bind_address和防火墙拦截、caching_sha2_password兼容性问题。

MySQL 用户账号绑定 IP 地址(host 字段)是基础白名单
MySQL 本身没有“IP 白名单配置项”,它的访问控制靠的是用户账号的 host 字段。创建用户时指定具体 IP 或网段,就是最直接的白名单行为。
常见错误现象:ERROR 1045 (28000): Access denied for user 'xxx'@'192.168.1.100',但你确信密码正确——大概率是该用户只允许从 '%' 或 'localhost' 连,而没授权给实际来源 IP。
- 创建仅允许从
192.168.1.100连接的用户:CREATE USER 'app'@'192.168.1.100' IDENTIFIED BY 'pwd';
- 允许一个 C 类子网:
CREATE USER 'app'@'192.168.1.%' IDENTIFIED BY 'pwd';
- 允许 IPv6 地址需写完整格式,如
'app'@'2001:db8::1';通配符'%'不匹配 IPv6 地址,必须显式授权 -
host字段区分大小写,且不支持正则;'192.168.1.0/24'这种 CIDR 写法在 MySQL 中无效
GRANT 语句必须匹配 CREATE USER 的 host 才生效
很多人执行了 GRANT ALL ON *.* TO 'app'@'%',却发现从特定 IP 连不上——因为该用户根本不存在于 mysql.user 表中,或者存在的是 'app'@'localhost',两者是完全不同的账号。
使用场景:运维批量开通权限时,容易漏掉 host 一致性检查。
- 先查用户是否存在且 host 匹配:
SELECT User, Host FROM mysql.user WHERE User = 'app';
- 如果要改已有用户的 host,不能直接 UPDATE
mysql.user表(风险高),应先DROP USER 'app'@'old_host',再用正确 host 重建 -
GRANT不会自动创建用户(MySQL 8.0+ 默认行为),必须先CREATE USER,否则报错ERROR 1410 (42000): You are not allowed to create a user with GRANT
防火墙和 bind-address 会拦截连接,不是 MySQL 层面的问题
即使 MySQL 用户已正确绑定 IP,客户端仍连不上,90% 是卡在更外层:系统防火墙或 MySQL 自身监听配置。
性能 / 兼容性影响:把 bind_address 设成 0.0.0.0 并开放所有端口,等于把白名单逻辑交给了操作系统级工具(如 iptables),MySQL 层的 host 控制就退居二线。
- 检查 MySQL 是否监听外部地址:
netstat -tlnp | grep :3306
,若只显示127.0.0.1:3306,说明bind_address是127.0.0.1或未配置 - 修改
/etc/mysql/mysql.conf.d/mysqld.cnf中的bind_address,设为0.0.0.0或具体内网 IP;改完必须sudo systemctl restart mysql - Linux 上记得放行 3306 端口:
sudo ufw allow from 192.168.1.100 to any port 3306
,而不是简单ufw allow 3306
MySQL 8.0+ 的 caching_sha2_password 插件可能干扰白名单验证流程
新版本默认认证插件变更后,部分客户端(尤其是老版本 JDBC、PHP mysqli)在连接时会先尝试匿名握手,导致 IP 检查阶段被跳过或误判,表面看像白名单失效。
容易踩的坑:测试时用 mysql -u app -h xxx 能连,但应用死活连不上,日志里却没报 host 相关错误。
- 确认用户使用的认证插件:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'app';
- 若插件是
caching_sha2_password且客户端不兼容,临时降级为mysql_native_password:ALTER USER 'app'@'192.168.1.100' IDENTIFIED WITH mysql_native_password BY 'pwd';
- 注意:该操作不改变 host 绑定逻辑,只是让握手过程更“老实”,便于排查是否真卡在 IP 过滤环节
MySQL 的 IP 白名单本质是账号维度的 host 匹配,不是全局开关;真正拦住请求的,往往在 bind_address、防火墙、甚至客户端驱动的认证协商阶段。调不通时,一层层剥开看,别一上来就改 mysql.user。










