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

MySQL启动失败?先检查iptables是否放行127.0.0.1
mysqld启动卡住、systemctl start mysql超时、日志只报Can’t connect to local MySQL server,大概率是iptables没放通本地回环。MySQL启动时会主动连127.0.0.1:3306做自检,这条流量被阻断就直接挂。
-
iptables -A INPUT -s 127.0.0.1 -p tcp --dport 3306 -j ACCEPT必须加,且得放在所有拒绝规则之前 - 别写成
!-s或!- s——空格错一个,规则就失效 - 仅写
-s 127.0.0.1不够,必须带-p tcp --dport 3306,否则可能被后续更宽泛规则覆盖 - ufw用户别漏:
ufw allow in on lo,否则lo接口不走ufw规则链,本地连接照样被拦
白名单规则写在DROP前面,顺序错了等于没设
iptables按顺序匹配,命中即停。DROP写在白名单前面,等于所有3306流量都被截胡,后面规则根本没机会执行。
- 错误顺序:
iptables -A INPUT -p tcp --dport 3306 -j DROP→iptables -A INPUT -s 192.168.1.50 -p tcp --dport 3306 -j ACCEPT - 正确顺序:先放行
127.0.0.1,再放行可信IP(如192.168.1.0/24),最后兜底iptables -A INPUT -p tcp --dport 3306 -j DROP - 用
DROP不用REJECT:前者静默丢包,外网扫描表现为超时;后者发RST包,直接暴露“这台机器跑着MySQL” - 云服务器上,安全组规则比iptables更早生效——安全组没开3306,iptables再细也收不到包
bind-address和防火墙必须对齐,否则配置互相抵消
MySQL的bind-address决定它听谁,防火墙决定谁有资格敲门。两者不一致,就会出现“端口通了但连不上”或“端口不通但以为该通”的错觉。
-
bind-address = 127.0.0.1→ MySQL只监听本地,此时防火墙放开3306给外网毫无意义 -
bind-address = 0.0.0.0→ MySQL监听所有接口,此时防火墙必须严格限制来源,否则等于裸奔 - 查实际监听地址用:
ss -tlnp | grep :3306,别只看配置文件——改完没重启,配置不生效 - 生产环境推荐写具体内网IP(如
bind-address = 192.168.10.5),比0.0.0.0更可控
conntrack超时导致连接突然中断,不是MySQL问题
客户端报Lost connection to MySQL server during query或Connection reset by peer,但MySQL日志无异常?可能是Linux连接跟踪表把长连接踢掉了。
- 查当前超时值:
sysctl net.netfilter.nf_conntrack_tcp_timeout_established - MySQL的
wait_timeout默认8小时,而某些云主机内核把nf_conntrack_tcp_timeout_established设成30分钟,连接空闲30分钟后就被防火墙删记录 - 临时调大:
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=86400 - 永久生效要写进
/etc/sysctl.conf,但注意部分云厂商会在重启后重置该值
实际部署时最容易被忽略的是三件事:本地回环放行顺序、安全组与iptables双控、conntrack超时和MySQL超时参数的错位。这些点不出问题时一切正常,一出就是“连不上”“启不动”“连着连着就断”,排查起来特别绕。


















