How to check open ports on a Linux server and open the one you need

A listening port can still be blocked. Check it with ss inside and nmap outside, read open, closed and filtered, and open it in ufw.

A service can listen on a port and still be unreachable from the internet. Two different things decide whether a port works: whether a program listens on it, and whether the firewall lets traffic reach it. This guide checks both, from inside the server with ss and from outside with nmap, explains the three results (open, closed, filtered) and opens a port in ufw. Everything was run on a real server.

In short. Inside: ss -tlnp shows what listens. Outside: nmap -Pn -p PORT server from another machine shows what answers. "Filtered" means the firewall drops the traffic, "closed" means the server answered that nothing listens, "open" means a program answered. Open a port with ufw allow PORT/tcp, close it with ufw delete allow PORT/tcp.

The test server is a HIP-HOSTING VPS with Ubuntu 24.04.5 and 2 vCPU. Its ufw firewall is on and blocks incoming traffic by default, with rules that allow ports 22, 80 and 443. We scanned it from a second server. In the output the server address is replaced with 203.0.113.20. On a new server ufw may be off; check with ufw status before you rely on any of this. Scan only servers you own.

Step 1. See what listens on the server

To have something to test, we start two small web servers: one that listens on every address (0.0.0.0) on port 8000, and one that listens only on the server itself (127.0.0.1) on port 8001. The trailing & keeps them running in the background.

python3 -m http.server 8000 --bind 0.0.0.0 --directory /tmp &
python3 -m http.server 8001 --bind 127.0.0.1 --directory /tmp &

Now ask the system which programs listen on TCP ports. ss is the modern replacement for netstat. The flags: -t TCP, -l listening sockets only, -n show numbers instead of names, -p show the program (needs root). The part in quotes limits the list to the ports we care about. More about ss itself, including who is connected to your server, is in our article ss instead of netstat.

Read the Local Address:Port column. 0.0.0.0:8000 means "listening on all IPv4 addresses", so the port can be reached from outside if nothing blocks it. 127.0.0.1:8001 means "only from this server itself": an ordinary firewall allow rule will not make that one reachable from the internet. [::]:22 is the same as 0.0.0.0 for IPv6. The last column names the program, which tells you what you would be exposing.

Step 2. Look at the firewall rules

Listening is only half of the story. The firewall decides who may reach the port. Here are the rules for ports 22, 80 and 443 on our server:

Ports 22, 80 and 443 are allowed. Ports 8000 and 8001 are not, and because the default for incoming traffic is "deny", they are blocked even though a program listens on 8000.

Step 3. Check from outside: open, closed, filtered

The only reliable test is from another machine, not from the server itself. We scanned from a second server. nmap probes ports and reports what it saw; -Pn skips the ping check (many servers do not answer ping) and -p lists the ports. nc -vz -w 3 is a simpler single-port test with a 3-second limit.

Three states to know:

  • open: a program answered. Ports 22 and 80.
  • closed: the server answered "nothing listens here". The traffic got through, so the firewall is not in the way.
  • filtered: no answer at all (or an error message that nmap cannot interpret). Something blocks the traffic, most often a firewall. Port 8000 is the trap: a program listens on it (Step 1), yet from outside it looks dead. It is not a service problem, it is a rule problem.

The nc command agrees: after 3 seconds it gives up with "timed out", which is what a dropped connection looks like.

Step 4. Open the port in ufw

ufw allow 8000/tcp lets TCP traffic to port 8000 in. The comment keyword is optional and helps you remember why a rule exists. We also opened 8001 on purpose, to see what changes for a port that listens only on the server itself:

"Rule added (v6)" means ufw added the same rule for IPv6 too. Port 8000 flipped from filtered to open, and a real request returned HTTP 200. Port 8001 changed from filtered to closed: the firewall now lets the traffic in, but nobody listens on the external address, because the program is bound to 127.0.0.1. curl fails with exit code 7 ("could not connect"). The fix for a port like that is in the program, not the firewall: make it listen on 0.0.0.0, and only if you really want it public.

Step 5. Close the port again

A rule you no longer need is an open door. List the rules with ufw status numbered, then delete by the same words you used to add:

Both ports are filtered again. We then stopped the test servers. To allow a port only from one address, ufw accepts a form like ufw allow from 203.0.113.50 to any port 8000 proto tcp; we did not test it here.

When a port listens but is still unreachable

  1. Filtered from outside. Check ufw status first: is there an allow rule for this port and protocol (TCP or UDP)? If the OS firewall is open and the port is still filtered, something in front of the server may drop traffic. We did not test that case; ask support.
  2. Closed from outside. The firewall is fine. The program is not running, listens on another port, or listens only on 127.0.0.1. Go back to ss -tlnp.
  3. Works for IPv4, fails for IPv6. Look at [::] in the ss output; a program may listen on one family only.

One warning: never open database ports (3306, 5432, 6379) to the whole internet. Keep them on 127.0.0.1 or allow only the addresses that need them. To get back in if a rule cuts you off, use the web console.

FAQ

How do I check if a port is open on my server?

From another machine run nmap -Pn -p PORT server-address or nc -vz -w 3 server-address PORT. "Open" means a program answers. Checking from the server itself shows only whether the program listens, not whether the internet can reach it.

What does "filtered" mean in nmap?

It means the scan got no answer, usually because a firewall drops the traffic. In our test port 8000 was filtered while a program listened on it, until we added an allow rule.

What is the difference between closed and filtered?

Closed means the server replied that nothing listens on that port: the traffic arrived. Filtered means there was no reply at all, so something blocked it on the way.

How do I open a port on Ubuntu?

Run ufw allow PORT/tcp, then check from outside with nmap. If the port stays closed, the program is not listening on a public address.

Do I need nmap on the server I am testing?

No. Install it on a different machine and scan the server from there. nc is enough for a single port.

Takeaways

  • Two checks: ss -tlnp inside (who listens) and nmap from another machine (who answers).
  • Filtered means a firewall drops the traffic, closed means nobody listens, open means a program answered. In our test a listening port was filtered until we allowed it.
  • A program bound to 127.0.0.1 cannot be reached from outside, whatever the firewall says.
  • Open ports one by one with ufw allow, remove them with ufw delete allow and re-scan after each change.

Not tested here: rules limited to one address, IPv6 scans, a firewall in front of the server and systems other than Ubuntu 24.04. Related guides: securing a fresh VPS and connecting to your server.

SECTION
How To
REVIEWED
—
LANGUAGES
EN · RU