MySQL用户IP绑定通过CREATE USER或GRANT语句的host字段实现,如'usr'@'192.168.1.100';不支持CIDR,子网限制需结合防火墙或云安全组;连接失败时据错误信息区分账号匹配与网络层问题。

MySQL 用户账号绑定 IP 的基本语法
MySQL 通过 CREATE USER 或 GRANT 语句中的主机名(host)部分控制访问来源,这个字段不是注释,而是强制匹配的网络条件。比如 'user1'@'192.168.1.100' 表示该用户仅允许从 192.168.1.100 连接,'user1'@'localhost' 则只响应本地 socket 连接。
常见误操作是省略 host 或写成 'user1'@'%' —— 后者等同于“任意 IP”,完全绕过 IP 限制。
- 创建时直接指定 IP:
CREATE USER 'app'@'10.0.5.22' IDENTIFIED BY 'pwd123'; - 已有用户需先删后建(MySQL 8.0+ 不支持直接修改 host):
DROP USER 'app'@'%'; CREATE USER 'app'@'10.0.5.22' IDENTIFIED BY 'pwd123'; - 授权必须匹配同一 host:
GRANT SELECT ON mydb.* TO 'app'@'10.0.5.22';,不能对'app'@'%'授权后再指望 IP 生效
通配符与子网限制的现实约束
MySQL 的 host 字段支持 % 和 _ 通配符,但不支持 CIDR(如 192.168.1.0/24)或正则表达式。想限制一个网段,只能用 'user'@'192.168.1.%',但这会匹配 192.168.1.1234 这类非法地址(MySQL 会静默截断),实际粒度较粗。
更严格的子网控制必须依赖外部手段:
- 防火墙(iptables / ufw)封禁非授权 IP 对 MySQL 端口(默认 3306)的 TCP 连接
- 云厂商安全组规则(如 AWS Security Group、阿里云 ECS 安全组)设置入方向白名单
- MySQL 8.0+ 可配合
validate_password插件 + 强密码策略,降低弱口令被爆破后跨 IP 滥用的风险
连接失败时如何确认是 IP 限制生效
当用户无法连接,错误信息是关键线索:
-
Access denied for user 'app'@'10.0.5.23':说明 MySQL 已识别客户端 IP,但没找到对应'app'@'10.0.5.23'账号 —— 是账号未创建或 host 写错 -
Host '10.0.5.23' is not allowed to connect to this MySQL server:mysqld 配置了skip-networking=OFF但bind-address未监听该网卡,或系统防火墙拦截了连接请求,尚未进入 MySQL 用户鉴权环节 - 用
SELECT User, Host FROM mysql.user;查看实际注册的 host 值,注意空格、大小写、特殊字符(如中划线)都会导致不匹配
MySQL 8.0+ 中 host 匹配的优先级细节
MySQL 按 host 字符串长度降序匹配账号,越具体的 host 优先级越高。例如同时存在 'app'@'10.0.5.22' 和 'app'@'10.0.5.%',来自 10.0.5.22 的连接一定走前者;但如果只建了 'app'@'10.0.5.%',而客户端 IP 是 10.0.5.220,也会匹配成功 —— 因为 % 会匹配任意长度数字。
容易被忽略的点:
- IPv6 地址需用方括号包裹,如
'app'@'2001:db8::1',否则会被当作文本字符串处理 - 如果应用使用 DNS 名称连接(如
mysql -h db-prod.example.com),MySQL 会反向解析 IP 再正向解析 hostname,两次 DNS 查询都必须成功且结果一致,否则 fallback 到'app'@'%'(若存在)或拒绝连接 -
localhost是特例:Unix socket 连接强制匹配'user'@'localhost',不会转为127.0.0.1;TCP 连接127.0.0.1则匹配'user'@'127.0.0.1'或'user'@'%',但不匹配'user'@'localhost'










