mysql用户host字段匹配客户端连接来源ip或主机名,用于认证而非网络层访问控制;值为ip、网段、%或localhost时分别限制对应来源,需配合网络层策略分层防护。

MySQL用户Host字段到底匹配什么
Host字段不是IP白名单开关,而是MySQL用户认证时用来比对客户端连接来源的字段。它决定“谁可以通过这个用户名密码登录”,而不是“谁可以连上这台服务器”。很多人误以为改了Host就能拦住非法IP,其实前置的TCP连接、防火墙、云厂商安全组已经先一步放行或拦截了。
- 值为
'192.168.1.100':只允许该IP用此用户登录 - 值为
'192.168.1.%':匹配C类网段(注意:不跨子网,192.168.2.5不行) - 值为
'%':允许任意IP(含远程),但不等于“没限制”——仍受网络层控制 - 值为
'localhost':仅限Unix socket本地连接,和127.0.0.1是两个不同认证路径
创建带IP限制的MySQL用户要分两步走
直接CREATE USER 'app'@'10.20.30.40' IDENTIFIED BY 'pwd';只是建了用户,但权限还没给。漏掉授权步骤,连自己都登不进去。
- 先建用户:
CREATE USER 'app'@'10.20.30.40' IDENTIFIED BY 'strong_pwd_2024'; - 再赋权限:
GRANT SELECT, INSERT ON mydb.orders TO 'app'@'10.20.30.40'; - 别忘刷新:
FLUSH PRIVILEGES;(MySQL 8.0+在大多数情况下可省略,但重启mysqld前建议执行) - 验证是否生效:
SELECT User, Host FROM mysql.user WHERE User = 'app';
常见连不上原因:Host匹配失败 vs 网络不通
报错Access denied for user 'app'@'10.20.30.41'说明MySQL收到了连接,但用户Host不匹配;而报错Connection refused或超时,基本是防火墙、安全组、bind-address或skip-networking在起作用。
- 检查客户端真实出口IP:
mysql -h your.mysql.host -u app -p时,MySQL看到的是TCP包里的源IP,不是你本机ifconfig显示的内网IP - 云数据库(如阿里云RDS)默认禁用
Host字段控制,只认白名单IP列表(控制台配置),mysql.user表的Host被忽略 - 如果MySQL配置了
bind-address = 127.0.0.1,外部IP根本连不到3306端口,Host再精确也没用
生产环境真正有效的IP访问控制层级
靠MySQL自己的Host字段做第一道防线风险高、易绕过。实际应分层设防:
- 最外层:云厂商安全组 / 防火墙(iptables/nftables),只放行应用服务器IP到3306端口
- 中间层:MySQL配置
bind-address绑定内网IP(如10.20.30.10),不监听0.0.0.0或公网IP - 最内层:MySQL用户
Host字段作二次校验,比如写成'10.20.30.40'而非'%',防止内网横向渗透 - 额外提醒:
skip-name-resolve必须开启,否则MySQL会反向DNS查询客户端IP,拖慢连接且可能因DNS故障导致认证失败
general_log或对接外部审计工具。单靠它挡攻击,就像用筛子接瀑布。











