Linux 防火墙为什么拦截了我的端口?

服务启动正常、本机访问也没问题,外部主机却连不上。按“客户端→监听进程→防火墙规则”的顺序排查,用 firewalld 或 ufw 永久放行端口,最后从外部扫描确认。

Linux进程网络nc 网络调试端口netcat 网络调试诊断高风险
先别急着改规则,从另一台机器用 netcat 测一下这个端口:如果是一直卡住直到超时(而不是 connection refused),基本可以断定是防火墙在丢包。

快速开始

被防火墙挡住的端口很有迷惑性:服务本身看起来一切正常,能启动,localhost 也能访问,日志里什么错误都没有,于是很容易误判成应用挂了。正确做法是沿着流量真实的路径走一遍——先看客户端、再看监听进程、最后才看防火墙规则。本指南按这个顺序展开,RPM 系发行版用 firewalld,Debian 系用 ufw,最后一定要从主机外部验证结果。

症状

?从其他主机连接应用端口时超时或被拒绝,但服务本身启动干净,在 127.0.0.1 上也能正常响应。远程客户端会一直挂到自己的超时时间;新装环境或防火墙重载之后,应用又变得无法访问。常见情形是昨天还好好的,改过一次配置或重启之后就废了,而应用日志里一个字都没提。

先确认服务确实在监听

别急着改防火墙,先看应用有没有真的绑定到这个端口。如果监听列表里压根没有这个端口,或者只绑在 127.0.0.1 上而不是 0.0.0.0,那防火墙怎么改都没用,问题出在服务本身或它的监听地址。顺便记下占用端口的进程名和 PID,确认看的是正确的那个守护进程。

显示所有处于监听状态的 TCP/UDP 套接字及其所属进程名和 PID,是 netstat 的现代替代品。

命令
$ sudo ss -tulpn

从另一台机器探测这个端口

在一台外部主机上用 netcat 的扫描模式测试,它只发起一次 TCP 连接并直接给出结果。三种结果含义完全不同:succeeded 说明链路和防火墙都没问题,问题在别处;connection refused 说明包已经到达主机、只是该端口没人监听;一直挂住直到超时,才是典型的“防火墙把包悄悄丢了”。只有最后一种情况才该怀疑防火墙。

回答「是不是防火墙挡住了我」最快的办法——netcat 扫描模式只建立一次 TCP 连接并打印结果。

命令
$ nc -zv example.com 443

查看 firewalld 规则集

这条命令一次性列出当前生效 zone 的服务、已开放端口和 rich rule,相当于把整套规则读一遍。如果目标端口既不在 ports 里,也没被某个 service 或 rich rule 覆盖,那基本就能确定是它把流量挡住了。同时看清当前生效的是哪个 zone、网卡又属于哪个 zone——规则加到错误的 zone 上,流量永远不会命中。

一条命令列出默认区域的服务、开放端口和富规则——firewalld 版的规则总览。

命令
$ sudo firewall-cmd --list-all

确认包到底有没有到达主机(可选)

只有在前面的连通性测试是超时、而你想拿到确凿证据时才需要这一步。在服务器上按端口抓包,同时让客户端反复重试。如果只看到不断重复的 SYN 而服务器毫无回应,说明主机侧在丢包——几乎总是防火墙干的;如果 SYN 收到了 RST 回应,说明包已经进来了、只是被主动拒绝,那问题在服务或监听地址,不在防火墙。

Linux用 tcpdump 抓取指定端口的流量中风险步骤 4可选

用 BPF 过滤表达式在任意网卡上抓包——验证流量是否真的到达服务器最快的方法。

命令
$ sudo tcpdump -i any -nn port 443

在 firewalld 中永久放行端口

Fedora、RHEL、CentOS 这类主机用这条。permanent 会把规则写进持久化配置,reload 让它立刻生效,重启后依然保留——用临时规则的话,下次开机就会悄悄失效。协议要和实际服务对上:HTTP 类应用用 TCP,游戏、DNS 类流量用 UDP。执行完之后,该端口应该出现在当前 zone 的放行端口列表里。

在 Fedora/RHEL/CentOS 的 firewalld 防火墙中永久放行 TCP 或 UDP 端口,让服务能被网络访问。

命令
$ sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload
▾ 撤销
撤销
$ sudo firewall-cmd --permanent --remove-port=8080/tcp && sudo firewall-cmd --reload

Ubuntu / Debian 上用 ufw 放行(可选)

如果这台机器跑的是 ufw 而不是 firewalld,前面那条 firewalld 命令不会有任何作用,应该用这条。按需要的端口和协议加一条放行规则,delete 形式则用来撤销。新建主机时顺序很关键:先把 SSH 端口放行再启用 ufw,否则一启用防火墙,你自己的远程会话就会当场断开。

Linux用 ufw 放行防火墙端口高风险步骤 6可选

添加一条 UFW 规则,允许某个 TCP 或 UDP 端口的入站流量,例如 22 端口的 SSH。

命令
$ sudo ufw allow 22/tcp
▾ 撤销
撤销
$ sudo ufw delete allow 22/tcp

从外部扫描复查

一定要从服务器之外的主机执行扫描,在本机扫描会绕过大部分过滤,证明不了任何东西。此时该端口应显示为开放并返回预期的服务版本,才算真正对外可用。如果仍然关闭,回头确认规则加在了承载入口流量的那个 zone 上,以及永久配置是否真的已经 reload 生效。

Linux用 nmap 扫描主机开放端口中风险步骤 7

查看自己机器上开放了哪些端口、运行着什么服务版本。

命令
$ nmap -sV -p- 192.168.1.10
!放行端口等于把它暴露给所有能路由到这台主机的网络,所以只开真正需要的端口,能用来源地址限制就别全开。改防火墙规则时请保留另一个 SSH 会话:一个拼写错误、把规则加到错误的 zone、或者先启用防火墙再放行 SSH,都可能把自己关在机器外面。

如何确认已解决

从外部主机执行连通性测试能够成功,端口扫描显示端口开放并返回预期的服务信息;同时在服务器上,该端口已出现在当前生效 zone 的放行列表中。

一键全部撤销

上面每一条命令都可以撤销。按此顺序执行即可全部还原。

一键全部撤销
$ sudo ufw delete allow 22/tcp
sudo firewall-cmd --permanent --remove-port=8080/tcp && sudo firewall-cmd --reload

执行前请先确认——部分步骤之间可能并非相互独立。

来源

最后验证: 2026-09-22

相关指南