Linux 防火墙为什么拦截了我的端口?
服务启动正常、本机访问也没问题,外部主机却连不上。按“客户端→监听进程→防火墙规则”的顺序排查,用 firewalld 或 ufw 永久放行端口,最后从外部扫描确认。
快速开始
被防火墙挡住的端口很有迷惑性:服务本身看起来一切正常,能启动,localhost 也能访问,日志里什么错误都没有,于是很容易误判成应用挂了。正确做法是沿着流量真实的路径走一遍——先看客户端、再看监听进程、最后才看防火墙规则。本指南按这个顺序展开,RPM 系发行版用 firewalld,Debian 系用 ufw,最后一定要从主机外部验证结果。
症状
先确认服务确实在监听
别急着改防火墙,先看应用有没有真的绑定到这个端口。如果监听列表里压根没有这个端口,或者只绑在 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 回应,说明包已经进来了、只是被主动拒绝,那问题在服务或监听地址,不在防火墙。
用 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 --reloadUbuntu / Debian 上用 ufw 放行(可选)
如果这台机器跑的是 ufw 而不是 firewalld,前面那条 firewalld 命令不会有任何作用,应该用这条。按需要的端口和协议加一条放行规则,delete 形式则用来撤销。新建主机时顺序很关键:先把 SSH 端口放行再启用 ufw,否则一启用防火墙,你自己的远程会话就会当场断开。
添加一条 UFW 规则,允许某个 TCP 或 UDP 端口的入站流量,例如 22 端口的 SSH。
$ sudo ufw allow 22/tcp▾ 撤销
$ sudo ufw delete allow 22/tcp从外部扫描复查
一定要从服务器之外的主机执行扫描,在本机扫描会绕过大部分过滤,证明不了任何东西。此时该端口应显示为开放并返回预期的服务版本,才算真正对外可用。如果仍然关闭,回头确认规则加在了承载入口流量的那个 zone 上,以及永久配置是否真的已经 reload 生效。
如何确认已解决
从外部主机执行连通性测试能够成功,端口扫描显示端口开放并返回预期的服务信息;同时在服务器上,该端口已出现在当前生效 zone 的放行列表中。
一键全部撤销
上面每一条命令都可以撤销。按此顺序执行即可全部还原。
$ sudo ufw delete allow 22/tcp
sudo firewall-cmd --permanent --remove-port=8080/tcp && sudo firewall-cmd --reload执行前请先确认——部分步骤之间可能并非相互独立。
来源
- nc(1) — arbitrary TCP and UDP connections and listens (OpenBSD netcat)依据: Documents -z (zero-I/O scan mode) and -v (verbose) for testing if a port is open without sending data
- OpenSSL — ArchWiki依据: ArchWiki network troubleshooting pages commonly recommend nc -zv for quick port reachability checks
- firewall-cmd(1) — firewalld command line client依据: Documents --list-all showing zone configuration including ports, services, and rich rules.
- Firewalld — ArchWiki依据: Community guide on querying firewalld state and permanently adding rules with --permanent plus --reload.
- tcpdump(1) — dump traffic on a network依据: Documents -i any (all interfaces), -n (no name resolution), and BPF filter expressions like `port 443`.
- firewall-cmd(1) — Ubuntu manual page依据: Reference for firewall-cmd port options and runtime vs permanent configuration behavior.
- firewall-cmd(1) — official man page依据: Documents --add-port, --permanent, and --reload for opening ports in firewalld zones.
- ss(8) — another utility to investigate sockets依据: The ss man page documents -t (TCP), -u (UDP), -l (listening), -p (show process), and -n (numeric ports/addresses).
最后验证: 2026-09-22