mysql不支持基于主机名的免密安全通信,因host仅用于acl匹配而非认证;真正安全需同时满足tls加密与可信认证,如mysql_config_editor配ssl验证或auth_socket加ssh隧道。

MySQL 本身不支持“基于主机名的网络免密安全通信”这种说法——它没有内置的主机名认证机制,所谓“免密”必依赖某种认证插件或外部凭证管理,而“安全通信”必须靠 TLS/SSL,两者不能混为一谈。直接配置 host=‘hostname’ 并设空密码,等于公开裸奔。
为什么 host='myapp-server' 不能替代密码或 TLS?
MySQL 的 host 字段只是访问控制列表(ACL)的一部分,用于匹配客户端连接来源的 IP 或解析后的主机名(需开启 skip_name_resolve=OFF),但它不参与身份认证。即使你执行:
CREATE USER 'app'@'myapp-server' IDENTIFIED BY '';
这只是允许来自该主机名反向解析结果为 myapp-server 的连接——但前提是:① DNS 可靠且可控;② 该主机上任何用户都能用 mysql -u app -h your-mysql-host 直连;③ 中间链路(如交换机、宿主机)无嗅探风险。现实中,DNS 欺骗、/etc/hosts 劫持、容器网络 overlay 地址不可控,都会让这个 host 规则形同虚设。
真正安全的远程免密通信只有两条路
必须同时满足:认证可信 + 链路加密
-
TLS + mysql_config_editor(推荐脚本/CI 场景):
mysql_config_editor存的是明文凭证,但可配合--ssl-mode=VERIFY_IDENTITY强制校验服务端证书 CN/SAN,防止中间人。生成命令示例:
mysql_config_editor set --login-path=prod \ --host=db.example.com \ --user=app \ --password \ --ssl-ca=/etc/mysql/ssl/ca.pem \ --ssl-cert=/etc/mysql/ssl/client.crt \ --ssl-key=/etc/mysql/ssl/client.key
之后用 mysql --login-path=prod 连接,MySQL 客户端会自动加载证书并验证服务端身份。
-
auth_socket + SSH tunnel(推荐开发/跳板机场景):禁用所有远程密码登录,只留
localhost的auth_socket用户(如'dev'@'localhost'),然后通过 SSH 端口转发把远程 MySQL 端口映射到本地:
ssh -L 3307:127.0.0.1:3306 user@db-server
再在本地执行 mysql -u dev -h 127.0.0.1 -P 3307 ——此时流量走 SSH 加密隧道,认证走本地 OS 用户身份,双保险。
常见错误:用 skip_name_resolve + hostname 免密 = 自欺欺人
有人在 [mysqld] 里加 skip_name_resolve=OFF,再建 'app'@'web01.internal' 并设空密码,以为“只有 web01 能连”。但问题在于:
- DNS 解析由 MySQL 服务端发起,若内网 DNS 不稳定,
web01.internal可能解析失败或被污染 - MySQL 不验证客户端是否真是 web01,只看 TCP 包源 IP 是否能反向解析出该名——攻击者只要伪造源 IP(在同网段易实现)或污染本地 DNS 缓存,就能绕过
- 所有流量明文传输,抓包即得 SQL 内容和结果集
这类配置在渗透测试中基本是“送分题”。
真正要落地,记住一个硬约束:网络免密 ≠ 删除密码,而是把密码换成更难窃取的凭证(如 client cert)、或把通信管道锁死(如 SSH tunnel)。任何脱离 TLS 或本地认证的信任模型,在生产环境都不该存在。











