必须先放行127.0.0.1:3306,否则mysqld启动自检失败导致systemctl start mysql超时;规则须置于所有DROP之前,ufw还需额外执行ufw allow in on lo。

直接封 3306 端口会让 mysqld 自己连不上自己,服务根本起不来——必须先放行 127.0.0.1,再加白名单,顺序和协议限定一个都不能错。
MySQL 启动失败?先查本地回环是否被 iptables 拦了
现象:执行 systemctl start mysql 超时,journalctl -u mysql 只报 Can’t connect to local MySQL server,ss -tlnp | grep :3306 也看不到监听。大概率是 iptables 没放通本地自检流量。
-
mysqld启动时会主动连接127.0.0.1:3306做初始化校验,这条流量被 DROP 就卡死 - 必须加这条规则,且放在所有
DROP或REJECT规则之前:iptables -A INPUT -s 127.0.0.1 -p tcp --dport 3306 -j ACCEPT - 别漏空格:
! -s写成!-s或!- s会导致规则无效 - 仅写
-s 127.0.0.1不够,必须带-p tcp --dport 3306,否则可能被后续更宽泛规则覆盖
ufw 用户别忘了显式允许 lo 接口
ufw 默认策略虽是拒绝入向,但 lo(回环)接口不走普通规则链——不单独处理,127.0.0.1 连接照样被拦。
- 先执行:
ufw allow in on lo,确保本地自检能过 - 再加业务白名单,例如:
ufw allow from 192.168.1.50 to any port 3306 proto tcp - 启用前务必确认:
ufw status verbose输出里有类似Anywhere on eth0的条目,不能只有127.0.0.1相关项 - 最后别跳过:
ufw enable,否则规则不生效
规则顺序错了等于没设:放行必须在 DROP 前面
iptables 按顺序匹配,命中即停。把 DROP 放白名单前面,所有 3306 流量都被截胡,后面规则根本没机会执行。
- 错误顺序:
iptables -A INPUT -p tcp --dport 3306 -j DROP→ 再加白名单(无效) - 正确顺序:先
127.0.0.1,再可信网段(如192.168.1.0/24),最后兜底:iptables -A INPUT -p tcp --dport 3306 -j DROP - 用
DROP不用REJECT:前者静默丢包,外网扫描表现为超时;后者发RST包,直接暴露“这台机器跑着 MySQL” - 云服务器上,安全组比
iptables更早生效——安全组没开3306,本地防火墙再细也没用
bind-address 和防火墙必须对齐
bind-address 决定 MySQL 听谁,防火墙决定谁有资格敲门。两者不一致,就会出现“端口通了但连不上”或“端口不通但以为该通”的错觉。
-
bind-address = 127.0.0.1→ MySQL 只监听本地,此时防火墙放开3306给外网毫无意义 -
bind-address = 0.0.0.0→ MySQL 监听所有接口,此时防火墙必须严格限制来源,否则等于裸奔 - 生产环境推荐写具体内网 IP,比如
bind-address = 192.168.10.5,比0.0.0.0更可控 - 查实际监听地址用:
ss -tlnp | grep :3306,别只看配置文件——改完没重启,配置不生效
最容易被忽略的点:云服务器的安全组、本地防火墙、MySQL 的 bind-address、用户授权(host 字段)这四层必须全部对齐,缺一不可。任何一层错位,都会导致连接失败,且错误日志往往不直接指向真正原因。


















