端口是否真在公网可达?先验证再排查:从外网执行telnet或nc检测,Connected才说明暴露,超时属防火墙/安全组问题,Connection refused则MySQL未监听外网或服务未启动;必须同步校验bind-address配置与防火墙策略。

端口是否真在公网可达?先验证再排查
别急着改配置,先确认 3306 端口是不是真的被公网访问到了。很多“暴露”其实是误判:比如本地 netstat 显示 0.0.0.0:3306,但云安全组或防火墙实际已拦截,外部根本连不上。
- 从外网机器执行:
nc -zv your_server_ip 3306或telnet your_server_ip 3306;返回Connected才算真正暴露 - 如果超时(timeout),问题出在防火墙/安全组,不是 MySQL 配置本身
- 如果报
Connection refused,说明 MySQL 没监听外网,或服务根本没起来 - 别信“我只开了内网 IP”,
bind-address = 192.168.1.100仍可能被同网段扫描到——只要路由可达,就算“局部暴露”
MySQL 是否监听了不该监听的地址?查 bind-address
bind-address 是第一道闸门,设错等于主动开门。默认值因发行版而异,Ubuntu 包安装常默认 0.0.0.0,CentOS 可能是 127.0.0.1,但运维改过配置却忘了这行,就埋下隐患。
- 登录 MySQL 执行:
SHOW VARIABLES LIKE 'bind_address';—— 结果必须是127.0.0.1或具体内网 IP(如192.168.10.5),绝不能是0.0.0.0或公网 IP - 查配置文件(常见路径:
/etc/mysql/mysql.conf.d/mysqld.cnf或/etc/my.cnf),确认[mysqld]下有明确的bind-address行,且未被注释 - 改完必须重启:
systemctl restart mysql;不重启,配置无效 - 重启后立刻验证监听状态:
ss -tlnp | grep :3306,输出里只应出现127.0.0.1:3306或你指定的内网地址
用户权限是否宽泛到允许任意远程登录?查 mysql.user 表
即使端口没暴露,若存在 root@'%' 这类账号,一旦将来某天端口被放开或绕过防火墙,就是零点击入口。
- 执行:
SELECT User, Host FROM mysql.user WHERE Host IN ('%', '0.0.0.0', '::%') OR Host LIKE '%.%'; - 特别注意:
Host = '10.%'、Host = '192.168.%'这类网段通配符,比%更隐蔽也更危险 - 空密码账号(
authentication_string IS NULL)和GRANT OPTION权限要立刻清理 - 临时加固命令示例:
UPDATE mysql.user SET Host='127.0.0.1' WHERE User='root' AND Host='%'; FLUSH PRIVILEGES;—— 但这只是补救,根源还在网络层隔离
防火墙和云安全组是否形同虚设?别依赖“只改端口”
把 3306 改成 3307 或 4306 不解决任何问题。端口扫描工具毫秒级扫遍 1–65535,换端口 ≠ 隐藏服务,只是躲开脚本小子的默认扫描,对专业扫描器无效。
- 云厂商安全组:默认拒绝所有入向,仅放行 DBA 办公 IP 或跳板机 IP 到 3306(不要写
0.0.0.0/0) - 系统防火墙(如 iptables):加显式拒绝规则,例如
iptables -A INPUT -p tcp --dport 3306 ! -s 192.168.10.0/24 -j DROP - Windows 防火墙:建两条规则——一条“允许指定内网段”,一条“阻止所有其他 3306 入站”,顺序不能错
- 关键点:安全组和系统防火墙是独立防线,任一缺失都可能导致暴露;二者都要配,且策略要一致
bind-address 设对了,但安全组全放行;或者安全组收紧了,MySQL 却还绑着 0.0.0.0。这两层必须同时成立,才算真正收口。


















