How to Check Listening Ports in Linux (2026 Guide)

Check listening ports in Linux with ss, netstat, lsof, and nmap — know which service owns each port, detect unexpected listeners, and troubleshoot connection refused errors.

April 22, 2026·6 min read·Damon

A connection refused error. An unexpected service. A security audit question. All of them start the same way: which ports are listening, on which interface, and which process owns them?


TL;DR

ss -tlnp          # TCP listening ports — use this first
ss -tlunp         # TCP + UDP listening
lsof -i -sTCP:LISTEN   # alternative with more process detail
nmap -sT localhost      # scan from outside the process table

ss: The Primary Tool

ss (socket statistics) is the modern replacement for netstat, pre-installed on all current Linux distributions.

ss -tlnp
State    Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
LISTEN   0       128     0.0.0.0:22          0.0.0.0:*          users:(("sshd",pid=1023,fd=3))
LISTEN   0       511     0.0.0.0:80          0.0.0.0:*          users:(("nginx",pid=2341,fd=6))
LISTEN   0       128     127.0.0.1:5432      0.0.0.0:*          users:(("postgres",pid=3012,fd=4))
LISTEN   0       128     [::]:22             [::]:*             users:(("sshd",pid=1023,fd=4))

Flags

-t   # TCP only
-l   # listening sockets only
-n   # show numbers, not service names
-p   # show process (requires root for full info)
-u   # include UDP

Check a specific port

ss -tlnp | grep :8080    # is 8080 in use?
ss -tlnp | grep :3306    # is MySQL accessible?

What the Output Tells You

Interface binding — the most important detail

0.0.0.0:80      → accessible from any network interface (externally reachable)
127.0.0.1:5432  → localhost only (not reachable from outside)
[::]:22         → all IPv6 interfaces
[::1]:6379      → IPv6 localhost only

This is the key security question. A service on 0.0.0.0 is exposed to every interface. A database that should be localhost-only but shows 0.0.0.0:3306 is a misconfiguration.

Recv-Q on LISTEN sockets

Recv-Q = 0   → normal
Recv-Q > 0   → accept backlog filling up — app is slower than connection rate

Alternative: lsof

lsof -i shows open internet sockets with more readable process detail:

lsof -i -sTCP:LISTEN
COMMAND   PID     USER   FD   TYPE  NODE NAME
sshd      1023    root    3u  IPv4  TCP  *:ssh (LISTEN)
nginx     2341    www     6u  IPv4  TCP  *:http (LISTEN)
postgres  3012    pg      4u  IPv4  TCP  localhost:postgresql (LISTEN)
# Check who's on a specific port
lsof -i :8080

# All TCP listeners with PIDs
lsof -nP -iTCP -sTCP:LISTEN

netstat (If ss Is Unavailable)

On older systems or containers where ss isn't available:

netstat -tlnp

# Install if missing (Ubuntu)
apt install net-tools

# Install if missing (RHEL)
dnf install net-tools

The output format is similar to ss but slightly different column ordering.


Real Examples

Full server port audit

echo "=== TCP Listeners ===" && ss -tlnp
echo "=== UDP Listeners ===" && ss -ulnp
echo "=== Established Connections ===" && ss -tnp state established | wc -l

Find unexpected listeners (security check)

# What's listening on non-standard ports?
ss -tlnp | awk '{print $4}' | grep -oE ':[0-9]+$' | sort -t: -k2 -n | uniq

# Expected ports on a web server: 22, 80, 443
# Anything else needs an explanation

Verify service is actually listening after start

systemctl start myapp
sleep 2
ss -tlnp | grep :8080
# If nothing: service crashed on startup — check journalctl -u myapp

Check if port is accessible from outside (nmap)

# Scan from the same host
nmap -sT -p 80,443,8080 localhost

# From another host
nmap -sT -p 80,443,8080 192.168.1.100

The difference between ss and nmap: ss shows what the kernel reports from inside the system. nmap tests actual network reachability — accounting for firewall rules. Both are useful.

Find which service is blocking a port

# Port 8080 shows in use but you don't know what:
ss -tlnp | grep :8080
# users:(("java",pid=4521,fd=12))

ps -p 4521 -o pid,comm,user,args
# Shows full command line of the process

Troubleshoot: Connection Refused

When clients get connection refused on a port you expect to be open:

# 1. Is anything listening?
ss -tlnp | grep :<port>
# Nothing → service not running or bound to wrong port

# 2. Is it bound to localhost only?
ss -tlnp | grep :<port>
# 127.0.0.1:8080 → only accessible locally

# 3. Is firewall blocking it?
iptables -L INPUT -n | grep <port>
# or
firewall-cmd --list-all   # RHEL
ufw status                # Ubuntu

# 4. Is the service on the right interface?
ss -tlnp | grep :<port>
# [::1]:8080 → IPv6 localhost only — if client is IPv4, won't connect

Common Mistakes

Mistake 1: Assuming a listening port is reachable The port could be bound to 127.0.0.1 or blocked by a firewall. Always check the local address column.

Mistake 2: Not using -n flag Without -n, ss resolves ports to service names (http, postgresql). For non-standard ports, it shows nothing or hangs. Use -n always.

Mistake 3: Missing process info because not running as root

ss -tlnp              # may show (null) for process
sudo ss -tlnp         # shows full process info

Mistake 4: Only checking TCP Some services use UDP (DNS, NTP, Syslog):

ss -ulnp              # UDP listeners
ss -tlunp             # both TCP and UDP

Pro Tips

# Watch for new listeners in real time
watch -n 2 'ss -tlnp'

# Find all listening ports sorted by port number
ss -tlnp | awk 'NR>1 {print $4}' | sort -t: -k2 -n

# Check if IPv6 is also listening (after binding to 0.0.0.0)
ss -tlnp | grep -E '0\.0\.0\.0|::'

# Monitor connection counts per port
watch -n 1 "ss -tn state established | awk '{print \$4}' | cut -d: -f2 | sort | uniq -c | sort -rn | head"

# Export to file for comparison
ss -tlnp > /tmp/ports_before.txt
# (make changes)
ss -tlnp > /tmp/ports_after.txt
diff /tmp/ports_before.txt /tmp/ports_after.txt

Conclusion

ss -tlnp gives you the full picture: port, interface, process. The local address column is what matters — 0.0.0.0 means externally reachable, 127.0.0.1 means local only. When connection refused errors appear, check if anything is listening, then check if it's bound to the right interface, then check the firewall.


Related: Check Open Ports in Linux: ss vs netstat — more depth on ss and netstat comparison. Linux Kill Process by Port — once you find the port, how to kill what's using it.