MySQL 默认3306端口暴露公网极危险,须绑定内网IP、防火墙限流、SSH隧道访问;禁用root@%等通配符账户;禁用skip-grant-tables;强制SSL并验证加密生效。

MySQL 默认端口暴露在公网等于开门揖盗
MySQL 默认监听 3306 端口,一旦该端口直接暴露在公网且未做访问控制,攻击者可快速扫描、暴力破解甚至利用已知漏洞(如 CVE-2012-2122)绕过认证。真实攻防场景中,80% 以上的 MySQL 数据泄露始于开放的 3306 端口 + 弱密码或空密码账户。
必须做到:
- 生产环境禁止将 MySQL 绑定到
0.0.0.0或公网 IP,改用bind-address = 127.0.0.1或内网 IP(如192.168.10.10) - 防火墙(如
iptables或云厂商安全组)只放行可信来源 IP 对3306的访问,拒绝全量INPUT流量 - 若必须远程管理,走跳板机或 SSH 隧道:
ssh -L 3307:127.0.0.1:3306 user@db-server,然后本地连localhost:3307
root@% 这类通配符账户是最大安全隐患
MySQL 中用户由 'username'@'host' 构成,root@% 表示允许从任意主机以 root 登录——这和把服务器 root 密码贴在玻璃上没区别。即使设置了强密码,也极大增加撞库与提权风险。
立即执行以下操作:
- 登录后运行
SELECT User, Host FROM mysql.user;,检查是否存在root@%、admin@%、''@'%'(空用户名)等高危条目 - 删除通配符高权限账户:
DROP USER 'root'@'%';,保留且仅保留root@localhost - 为业务应用创建最小权限账号:例如只读账号用
GRANT SELECT ON mydb.* TO 'app_ro'@'192.168.10.%';,写入账号额外加INSERT,UPDATE,DELETE,禁用FILE、PROCESS、SUPER等危险权限
skip-grant-tables 启用后根本没密码保护
该配置项用于重置密码,但若忘记关闭并重启 mysqld,MySQL 将完全跳过权限验证系统——任何连接都能以任意用户身份执行任意 SQL,包括删库。
确认方式与修复:
- 检查配置文件(
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf)是否含skip-grant-tables,如有,立刻注释并重启服务:sudo systemctl restart mysql - 不要依赖它做日常运维;重置密码应使用
ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpass';(MySQL 5.7+)或SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpass');(5.6 及更早) - 若已启用且无法登录,需临时加
--skip-grant-tables --skip-networking启动,仅允许本地 socket 连接,完成修改后立刻退出并正常重启
SSL 加密不是“开了就行”,得验证是否真生效
即使配置了 ssl-ca、ssl-cert、ssl-key 并重启,客户端仍可能走非加密连接,因为 MySQL 默认不强制 SSL。攻击者可在中间人位置抓取明文账号密码和查询内容。
必须组合配置才有效:
- 服务端启用强制 SSL:
ALTER USER 'app_user'@'192.168.10.%' REQUIRE SSL;(对特定用户)或全局策略通过require_secure_transport = ON(MySQL 8.0.19+) - 客户端连接时显式指定:
mysql -u app_user -p --ssl-mode=REQUIRED -h db.example.com,否则驱动可能静默降级 - 验证是否加密:登录后执行
SHOW STATUS LIKE 'Ssl_cipher';,返回非空值(如AES256-SHA)才表示当前连接已加密
实际环境中最常被忽略的是权限粒度与网络隔离的配合——光删掉 root@% 不够,还要确保应用服务器只能访问对应业务库、且数据库主机出方向也限制(比如禁止访问外网,防止恶意 UDF 或日志外传)。安全不是功能开关,而是每一层连接点的收敛。


















