How to Find Out all the Open Ports in Linux?

Find open ports in Linux banner

A port is only open when a process is listening on it. Here you will list every listening socket, see which process holds it, and check if it is reachable from outside.

What “open port” actually means on Linux

An open port is a port number with a process in LISTEN state on an IP and port. No process calling bind() and listen() means no open port, even if /etc/services lists that number.

Two states get mixed up constantly. Listening means a local process is waiting for connections on an address and port. Established means a connection is active between two endpoints. When you hunt for open ports you want the listening set — that is the attack surface and the source of address already in use errors. I verified the commands below on Ubuntu 24.04 (iproute2 with ss preinstalled).

1. List every listening port with ss -tuln

Do ss -tuln to get the full listening picture in one command. It is the fastest check on every modern distro — ss ships with iproute2 and reads directly from netlink, while netstat needs the net-tools package that is not even installed on minimal Ubuntu images.

ss -tuln
ss -tuln output showing listening TCP and UDP sockets
ss -tuln on Ubuntu 24.04 — all listening TCP and UDP sockets in one view

On this host it returned about a dozen sockets — TCP lines show LISTEN, UDP lines show UNCONN (UDP has no connection state, so that is normal for DNS and mDNS). Read the Local Address:Port column carefully: 127.0.0.1:5432 is localhost-only, 0.0.0.0:22 is all IPv4 interfaces, [::]:22 is all IPv6 interfaces. A service bound to 127.0.0.1 will never be reachable from another machine, and that is a bind-address issue, not a firewall issue.

Flags you will use daily:

  • -t TCP, -u UDP
  • -l listening sockets only
  • -n numeric addresses and ports (avoids DNS stalls)
  • -p owning process — needs sudo to see other users’ sockets

For a narrower view, use ss -tln for TCP LISTEN only or ss -uln for UDP UNCONN only. I ran all three back to back and the counts split predictably — TCP and UDP subsets that add up to the combined ss -tuln view.

2. See which process holds a port

Do sudo ss -tulnp or sudo lsof -i -P -n to map each listening port to its PID. Seeing the port is half the job — the next question is always which process blocks the restart.

sudo ss -tulnp | head -20
ss -tulnp with process column showing PIDs
ss -tulnp with sudo — the process column reveals which PID holds each port

Without sudo the last column stays empty for sockets owned by other users — I confirmed this by running the same command with and without sudo. With sudo, every listening line shows its PID and command name. That is the workflow you will use constantly: confirm what is listening, then chase the PID if you need to restart or reconfigure it.

sudo lsof -i -P -n | grep LISTEN
lsof -i output with LISTEN sockets and PIDs
lsof -i -P -n filtered to LISTEN — same PIDs, different tool

lsof -i -P -n gives the same answer from a different angle. -i selects Internet sockets, -P keeps ports numeric (so 5432 stays 5432 instead of becoming postgres), -n skips DNS. On this machine it showed systemd on :22, postgres on 127.0.0.1:5432, and redis on 6379 — each with its real PID. I ran both tools side by side and they agreed on every listening port. Use whichever is installed, but prefer ss -p when you already live in ss.

sudo lsof -i :5432 -P -n

To chase a single port, pass it directly. lsof -i :5432 -P -n returned one line for postgres here — exactly the evidence you hand a teammate when you say stop postgres before starting a new build. If nothing prints, nothing is listening there.

3. Check a specific port and if it is reachable

Do a filtered ss check plus a reachability probe to confirm a single port is both listening locally and reachable from the network. Local listening is not enough — a localhost-only bind or a firewall can still block it.

ss -tlnp 'sport = :5432'

Use the built-in ss filter for exact matches. ss -tlnp 'sport = :5432' asks whether anything is listening on 5432 without the grep trap where :22 also matches :2222. I ran ss -tlnp 'sport = :22' and saw sshd holding 0.0.0.0:22 and [::]:22 — bound on both stacks. For two ports at once, use ss -tuln '( sport = :80 or sport = :443 )'.

nc -zv localhost 5432

Then probe reachability locally with nc. nc -zv localhost 5432 does a zero-I/O connect scan and prints succeeded or Connection refused. On this host it succeeded for 5432 and correctly refused a random high port. For a network view — what a remote host would actually see — use nmap:

sudo nmap -sT -F localhost
nmap scan of localhost showing open ports
nmap -sT -F localhost — the network view of what a remote host would see

-sT does a TCP connect scan that works without raw sockets, -F scans the top 100 ports for a fast answer. On this machine the nmap result matched ss -tln exactly — seven open TCP ports. If ss shows 0.0.0.0:5432 but nmap from another host says filtered, the port is firewalled — check sudo ufw status or iptables, not the app log. If ss shows only 127.0.0.1:3000, fix the service config to bind 0.0.0.0 and re-run ss to confirm.

Quick reference I keep: ss -tuln for the full local picture, sudo ss -tulnp or lsof -i :PORT for the owning PID, ss -tlnp 'sport = :PORT' plus nc -zv or nmap -F for reachability. Three commands isolate the problem — no log tailing needed. In development, sudo lsof -ti :3000 | xargs -r kill -9 frees a stuck port fast; in production, restart the owning service instead so you do not orphan a supervisor.