前言
之前在《VPS 的 DNS 总是被神秘力量"偷偷"改回去?一个 chattr 命令解决》文章里,提到到另一个问题——装了宝塔面板的机器,面板会自动生成一套 iptables 规则,和原有防火墙规则撞车,然后端口被拦得莫名其妙的。今天就来详细的解析一下这个问题。
具体现象:在宝塔的"系统防火墙"里把端口放行了,面板显示一切正常,结果外网访问还是超时;更气人的是有些机器反过来,明明没放行的端口居然能通。
根据这个现象,我排设了一个排查链:
服务监听;
面板防火墙;
系统防火墙;
机房侧拦截;
规则撞车。
我们将依次按照这条链来排查。
先确认服务真的在监听
排查要从里往外,第一层是服务本身。通过 SSH 登录机器,执行:
sudo ss -tlnp 在输出里找目标端口,重点看 Local Address 那一列。0.0.0.0:8080 表示对所有网卡监听,外部流量才能进来;如果显示的是 127.0.0.1:8080,说明服务只接受本机访问——这种情况防火墙放行一万条也白搭,流量根本到不了端口跟前。应用配置文件里绑定地址写成 127.0.0.1,是最常见的源头。
面板放行不等于系统放行
第二层看面板和系统对不对得上。宝塔的"系统防火墙"功能不是自己另起炉灶,操作的就是系统防火墙:按宝塔官方文档的口径,CentOS 7+ 上是 firewalld,Debian/Ubuntu 上是 ufw,规则会同步至系统。
但"面板显示已放行"和"规则真的写入成功"又是两回事——firewalld 服务没起来、ufw 没启用的时候,面板配置的那一下可能就会落空,实际状态却不提示。所以要在系统侧对账:
CentOS 7+
firewall-cmd --list-all Debian/Ubuntu
ufw status 跑完命令后,看放行列表里有没有目标端口。没有就说明面板那一下没真正写进去,直接在系统侧补上,再回面板核对显示。
别忘了机房侧还有一层
系统里全放行了还是不通,就往外再走一层:机房/商家侧的拦截。不少商家在控制台提供防火墙或安全组功能,规则在系统外面就把流量挡了——你在机器里翻遍 iptables 也查不到它。
比如 VMRack 这种自建机房的商家,它的网络安全组在控制台管理,遇到连不上时先到控制台看看有没有防火墙、防御类的拦截项,再考虑发工单确认。
一个快速排查的方法:在机器上 curl http://你的公网IP:端口,本机能通、外网却不通,那么问题就在系统之外的某一层。
规则撞车
我遇到的案例是:宝塔里放行了 8080,ufw status 里也有记录,外网照旧不通。执行下面这条命令,带序号列出所有规则:
iptables -L -n --line-numbers 其中一条 DROP 挡在放行规则前面,流量走到它就被丢了,后面的放行根本轮不到被匹配。
iptables 自上而下按顺序匹配,先命中先生效。面板写的规则、手敲的规则、系统服务生成的规则,全进同一张表;顺序一旦错乱,前面的 DROP 能让后面所有放行形同虚设。这就是"面板明明放行了还是连不上"的真相,不是面板显示错误,是有更靠前的规则拦在了半路。
处理分三步:
先备份:
iptables-save > ~/iptables.bak,把当前规则存一份,删错了还能救回来;按序号删除拦路的失效规则:
iptables -D INPUT 序号,删一条复核一次,别一次全清;理清管理入口:要么以后统一在面板点,要么统一命令行写,别两头同时写。宝塔会读取命令行加的规则,混着写,就容易乱。
还有一种变体:用 99CDN 这类自建 CDN 方案分流静态资源后,回源流量是从 CDN 节点发过来的,如果后来在 iptables 里加了限制来源 IP 的规则,记得把回源节点也一并放行。
排查链速查清单
把整条链收进一张表,下次端口出问题就照着表来:
总结
端口连不上的时,根据这个排查链来:服务监听 → 面板防火墙 → 系统防火墙 → iptables 规则顺序 → 机房侧拦截,从里到外逐层排除。
下一篇预告:排查时还剩一个更隐蔽的角色没展开——Docker,这个因素比较复杂,需要单开一篇。它会把自家规则直接写进 iptables,而且能绕过 ufw,是"放行了还连不上"的另一种可能。