firewalld只执行--permanent添加3306端口而不reload,规则仅写入配置文件但未加载至运行时,导致客户端连接超时且无日志;必须执行firewall-cmd --reload才能生效。

firewalld 里只开 3306 端口但没 reload,等于没开
执行 firewall-cmd --zone=public --add-port=3306/tcp --permanent 只是把规则写进配置文件,不 reload 就不会生效。现象是客户端连不上,ss -tlnp | grep :3306 显示 MySQL 在监听,但连接直接超时,日志里也无任何记录——这是典型的静默丢包。
必须补上 reload:
-
firewall-cmd --reload(重载全部规则) - 或
firewall-cmd --complete-reload(更彻底,会中断现有连接,慎用)
验证是否真开了:firewall-cmd --list-ports 输出里要有 3306/tcp;如果为空,不代表没开,可能只是没加规则,得结合 firewall-cmd --list-all 看 full list。
别用 --add-service=mysql,它默认绑的是旧协议和端口
MySQL 的 firewalld service 定义在 /usr/lib/firewalld/services/mysql.xml,内容是 port=3306/tcp ——看起来没问题,但实际这个 service 是为 MySQL 5.x 设计的,且不带任何源 IP 限制逻辑。更重要的是,它无法配合 rich rule 做精细化控制,比如只放行某网段。
推荐直接用 port 规则,并叠加 source 限制:
- 只允许局域网访问:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="3306" protocol="tcp" accept' - 拒绝其他所有 3306 流量(默认策略通常是 deny,但显式加一条更安心):
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port port="3306" protocol="tcp" reject' - 然后
firewall-cmd --reload
开放端口后还连不上?先确认 bind-address 是否监听 0.0.0.0
防火墙只是第四道锁。MySQL 进程本身默认只监听 127.0.0.1:3306,外部请求压根进不来。即使用户权限、认证插件、防火墙全对,也会卡在连接阶段。
检查方式:ss -tlnp | grep :3306。输出中必须出现 *:3306 或 0.0.0.0:3306,而不是只有 127.0.0.1:3306。
修改方法:
- 编辑
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf - 在
[mysqld]段下加或改:bind-address = 0.0.0.0 - 重启 MySQL:
systemctl restart mysqld(CentOS/RHEL)或systemctl restart mysql(Ubuntu/Debian)
云服务器上光配 firewalld 不够,安全组才是第一道关
本地 firewalld 开了 3306,不代表云服务器能收到包。腾讯云、阿里云、AWS 的安全组默认全部拒绝入向流量,必须手动添加规则。
关键点:
- 协议选
TCP,端口填3306 - 源 IP 不要填
0.0.0.0/0,生产环境至少缩到具体 IP 或 CIDR 段(如203.0.113.42/32或192.168.10.0/24) - 安全组修改后立即生效,无需重启实例或服务
- 如果用了宝塔面板,它自带防火墙模块,得在面板里也开一次 3306,否则会覆盖系统级 firewalld 规则
最容易被忽略的是:安全组和 firewalld 是并行过滤,任一关卡失败都连不上。排查时建议按「安全组 → bind-address → 用户 host + plugin → firewalld」顺序逐层验证,别一上来就调用户权限。


















