默认不允许远程连接,因mysql绑定127.0.0.1且root用户host为’localhost’;需修改bind-address、授权非localhost用户并刷新权限。

MySQL 用户账户是否允许远程连接
默认安装的 MySQL 只监听 127.0.0.1,且 root 用户的 host 字段是 'localhost',这意味着它根本无法响应来自其他 IP 的连接请求。不能只改密码或开防火墙就认为能连上。
- 先确认 MySQL 绑定地址:检查
/etc/mysql/mysql.conf.d/mysqld.cnf(ubuntu)或/etc/my.cnf(centos),确保bind-address不是127.0.0.1,可设为0.0.0.0(监听所有接口)或具体内网 IP - 检查用户权限:登录 MySQL 后执行
select host, user FROM mysql.user;,若目标用户对应host是'localhost',需显式授权远程访问 - 远程用户必须用
CREATE USER或GRANT显式指定非 localhost 的 host,例如'user'@'192.168.1.%'或'user'@'%'
GRANT 语句中 host 参数的含义与风险
GRANT 里的 host 不是“允许从哪连”,而是“这个用户名在哪个 host 上被识别”——它是身份认证的一部分。写成 'user'@'%' 表示该账号可从任意 IP 连入,但也会让 MySQL 完全依赖密码强度来防御暴力破解。
-
'%'允许所有 IPv4/IPv6 地址,但不包括 unix socket 连接(localhost会走 socket,不走 TCP) - 生产环境强烈建议限制范围,比如
'app'@'10.0.2.5'或'reporter'@'172.16.0.0/255.255.0.0'(MySQL 8.0+ 支持 CIDR) - 执行
GRANT SELECT ON db.* TO 'reader'@'10.0.1.0/24';后必须跟FLUSH PRIVILEGES;,否则权限不生效 - 旧版本 MySQL(’reader’@’10.0.1.%’ 模糊匹配
连接失败时如何快速定位是权限还是网络问题
错误信息 ERROR 1045 (28000): Access denied for user 看似是权限问题,但实际可能是 MySQL 根本没收到包——得先排除网络和 MySQL 配置层拦截。
- 在客户端执行
telnet your-mysql-host 3306,不通说明被防火墙、安全组或bind-address拦了 - 在服务端用
ss -tlnp | grep :3306确认 mysqld 是否真在监听预期地址和端口 - 查 MySQL 错误日志(通常在
/var/log/mysql/error.log),看是否有Access denied记录及来源 IP - 注意 DNS 反向解析:如果客户端 IP 无法正向/反向解析,MySQL 可能将连接识别为
'user'@'some-hostname'而非你预设的'user'@'1.2.3.4';可在配置中加skip-name-resolve关闭此行为
最小权限原则下如何给应用分配账号
别给应用用 root,也别用 GRANT ALL。远程账号尤其要限制库、表、操作类型,还要考虑连接来源和并发控制。
- 创建专用账号:例如
CREATE USER 'webapp'@'192.168.5.10' IDENTIFIED BY 'strong-pass-2024'; - 按需授权:如仅需读写订单表,执行
GRANT SELECT, INSERT, UPDATE ON myshop.orders TO 'webapp'@'192.168.5.10'; - 限制资源:MySQL 8.0+ 支持
WITH MAX_CONNECTIONS_PER_HOUR 100防爆破,老版本只能靠中间件或防火墙限速 - 密码策略:启用
validate_password插件,并设置default_password_lifetime = 180强制定期轮换
防火墙、bind-address、host 匹配规则、密码策略这四层缺一不可,任何一层疏漏都会导致“明明授权了却连不上”或者“连上了但不安全”。尤其注意 MySQL 的 host 匹配是精确字符串比对,不是通配符路径匹配——这是最常被忽略的细节。