Why is my Linux firewall blocking a port?
A service starts fine and works on localhost, but remote clients hang or get refused. Work from the client inward: probe the port, check the listener, read the firewalld or ufw ruleset, open the port permanently, then verify with an external scan.
What this covers
A firewalled port is deceptive, because the service itself looks perfectly healthy: it starts, localhost works, logs show nothing wrong. The trick is to walk the path the traffic actually takes — client, listener, then firewall rules — instead of guessing at the firewall. This guide keeps that order, uses firewalld commands for RPM-based distros and ufw for Debian-based ones, and ends with proof from outside the host.
Symptom
Confirm the service is actually listening
Before touching the firewall, check that the app is bound to the port at all. If the port does not appear in the listening sockets, or the process is bound only to 127.0.0.1 instead of 0.0.0.0, no firewall change will help — the problem is the service or its bind address. Note the owning process name and PID so you know you are looking at the right daemon, and whether it is bound to all interfaces or just loopback.
Show every TCP and UDP socket in listening state with the owning process name and PID — the modern replacement for netstat.
$ sudo ss -tulpnProbe the port from another machine
Run netcat in scan mode from a host outside the server; it opens exactly one TCP connection and prints the result. Three outcomes mean three different things: 'succeeded' means the path and the firewall are fine and the problem is elsewhere; 'connection refused' means the packet reached the host but nothing was listening on that port; a hang that ends in a timeout is the classic signature of a packet filter silently dropping the traffic. Only that last case points at the firewall.
The fastest way to answer 'is the firewall blocking me?' — netcat in scan mode attempts one TCP connection and prints whether it succeeded.
$ nc -zv example.com 443Inspect the firewalld ruleset
This dumps the active zone's services, open ports and rich rules in one go — the firewalld equivalent of reading the whole ruleset. If the port you need is neither in the ports list nor covered by a service or rich rule, the firewall is dropping it. Also note which zone is active and which zone the interface belongs to, because a rule added to the wrong zone will never match the inbound traffic.
One command to dump the default zone's services, open ports, and rich rules — the firewalld equivalent of a ruleset view.
$ sudo firewall-cmd --list-allCheck whether packets reach the host at all
Only needed if the netcat probe timed out and you want proof. Capture on any interface with a filter for the port while a client retries. If you see repeated SYNs and no reply from the server, something on the host is dropping them — almost always the firewall. If you see a SYN answered with a RST, the packet got through and was actively refused, so the service or its bind address is the culprit, not the firewall.
Sniff packets on any interface with a BPF filter — the fastest way to prove whether traffic is even reaching your server.
$ sudo tcpdump -i any -nn port 443Open the port permanently in firewalld
Use this on Fedora, RHEL and CentOS hosts. The permanent flag writes the rule into the stored configuration and the reload applies it right away, so the port stays open across reboots — a temporary rule would silently disappear next boot. Match the protocol to the service (TCP for HTTP-style apps, UDP for game and DNS-style traffic). Afterwards the port should show up in the allowed ports of the active zone.
Permanently allow a TCP or UDP port through firewalld on Fedora, RHEL, or CentOS so your web app or game server is reachable.
$ sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload▾ Undo
$ sudo firewall-cmd --permanent --remove-port=8080/tcp && sudo firewall-cmd --reloadOn Ubuntu or Debian, add the rule with ufw
If the host runs ufw instead of firewalld, the firewalld command has no effect and this is the correct fix. Add a rule for the port and protocol you need; the delete form removes it again. Order matters when you are still setting the host up: allow your SSH port before you enable ufw, otherwise enabling the firewall cuts your own remote session immediately.
Add a UFW rule to permit inbound traffic on a TCP or UDP port, such as SSH on port 22.
$ sudo ufw allow 22/tcp▾ Undo
$ sudo ufw delete allow 22/tcpVerify from outside with a port scan
Run the scan from a host outside the server, not from the server itself — a scan from localhost bypasses most filtering and proves nothing. The port should now appear open and report the expected service version, which confirms the rule is live for remote traffic. If it is still closed, re-check that the rule landed in the zone that owns the inbound interface, and that the permanent change was actually reloaded.
Enumerate every open port and running service version on a machine you administer.
$ nmap -sV -p- 192.168.1.10How to confirm it worked
From an outside host, a netcat probe succeeds and a port scan shows the port open with the expected service banner. On the server, the port now appears among the allowed ports of the active firewall zone.
Undo everything
Every command above can be reverted. Run these in order to undo all of it.
$ sudo ufw delete allow 22/tcp
sudo firewall-cmd --permanent --remove-port=8080/tcp && sudo firewall-cmd --reloadReview before running — some steps may not be independent.
Sources
- nc(1) — arbitrary TCP and UDP connections and listens (OpenBSD netcat)Evidence: Documents -z (zero-I/O scan mode) and -v (verbose) for testing if a port is open without sending data
- OpenSSL — ArchWikiEvidence: ArchWiki network troubleshooting pages commonly recommend nc -zv for quick port reachability checks
- firewall-cmd(1) — firewalld command line clientEvidence: Documents --list-all showing zone configuration including ports, services, and rich rules.
- Firewalld — ArchWikiEvidence: Community guide on querying firewalld state and permanently adding rules with --permanent plus --reload.
- tcpdump(1) — dump traffic on a networkEvidence: Documents -i any (all interfaces), -n (no name resolution), and BPF filter expressions like `port 443`.
- firewall-cmd(1) — Ubuntu manual pageEvidence: Reference for firewall-cmd port options and runtime vs permanent configuration behavior.
- firewall-cmd(1) — official man pageEvidence: Documents --add-port, --permanent, and --reload for opening ports in firewalld zones.
- ss(8) — another utility to investigate socketsEvidence: The ss man page documents -t (TCP), -u (UDP), -l (listening), -p (show process), and -n (numeric ports/addresses).
Last verified: 2026-09-22
Related guides
SSH refuses to connect to your Linux server? Test the port, check sshd, open the firewall, and validate the config — in that order.
A practical checklist for finding which ports are open on a Linux machine or across your network, from local sockets to a full nmap scan.
A terminal-first workflow to diagnose high CPU usage on Linux, identify the responsible process or service, and fix it without losing your work.