必须先删除root@'%'再创建root@'10.20.30.40',因mysql按user+host组合识别账号,通配符账号存在则限制失效;需执行drop user、create/alter user、grant、flush privileges,并验证current_user()和@@bind_address。

直接删掉 root@'%',再创建 root@'10.20.30.40'(替换成堡垒机真实IP),否则限制永远不生效。
必须先清理冗余的 root@'%' 账号
MySQL 按 User+Host 组合识别账号,root@'%' 和 root@'10.20.30.40' 是两个独立账号。只要前者存在,任何 IP 都能连上 root——通配符优先级不低,但问题在于它“存在即可用”。
- 查当前所有 root 账号:
SELECT User, Host FROM mysql.user WHERE User = 'root'; - 删掉泛用账号:
DROP USER 'root'@'%';(注意:不是DELETE FROM mysql.user) - 确认只剩目标条目:
SELECT Host FROM mysql.user WHERE User = 'root';应只返回你指定的堡垒机 IP 或'localhost'
创建或重命名 root 账号绑定到堡垒机 IP
不能用 UPDATE mysql.user 改 Host 字段,MySQL 8.0+ 会拒绝或导致认证失败;必须用 CREATE USER 或 ALTER USER ... RENAME TO。
- 全新创建(推荐):
CREATE USER 'root'@'10.20.30.40' IDENTIFIED WITH caching_sha2_password BY 'strong-pass'; - 已有
root@'%'但刚删过?别急着重试,先检查是否残留:SELECT User, Host FROM mysql.user WHERE User = 'root'; - 若还有
root@'old-ip',用重命名:ALTER USER 'root'@'old-ip' RENAME TO 'root'@'10.20.30.40'; - 授权必须匹配新 host:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'10.20.30.40' WITH GRANT OPTION;
FLUSH PRIVILEGES 不是可选步骤,而是强制重载权限表
权限变更后不执行这句,新连接仍可能报 Access denied,旧连接也可能沿用缓存规则。这不是“建议”,是 MySQL 权限系统的工作机制。
- 执行:
FLUSH PRIVILEGES; - 验证是否生效:从堡垒机执行
mysql -u root -p -h your-mysql-host,成功后立刻运行:SELECT USER(), CURRENT_USER(); - 关键看
CURRENT_USER()返回值——必须是root@'10.20.30.40',否则说明匹配到了别的账号 - 从非堡垒机 IP 尝试连接,应明确报错:
Host '192.168.5.67' is not allowed to connect to this MySQL server
别忘了 bind-address 和 skip_name_resolve
只改账号 host 不够,MySQL 进程本身得监听对应网卡,且 DNS 解析不能干扰 IP 匹配。
- 检查监听地址:
SELECT @@bind_address;若返回127.0.0.1或空,堡垒机根本连不上——需设为0.0.0.0或具体内网 IP,并重启 mysqld - 禁用反向 DNS:
skip_name_resolve = ON必须加在my.cnf的[mysqld]段,否则客户端 IP 可能被解析成主机名,导致root@'10.20.30.40'匹配失败 - Linux 下确认端口监听:
ss -tlnp | grep :3306,确保 LISTEN 地址包含你期望的内网 IP
最常被忽略的是 CURRENT_USER() 和 @@bind_address 这两个验证点——不看它们,你永远不知道限制到底起没起作用。











