| Tested on | RHEL 10.2 (Coughlan) |
|---|---|
| Package | iproute 6.17.0-2.el10.x86_64lsof 4.98.0-7.el10.x86_64nmap 7.92-5.el10.x86_64nmap-ncat 7.92-5.el10.x86_64net-tools 2.0-0.73.20160912git.el10.x86_64 |
| Applies to | Ubuntu, Debian, Kali Linux, Linux Mint, Pop!_OS, Raspberry Pi OS, elementary OS, Zorin OS, Parrot OS, MX Linux, RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora, Arch Linux |
| Privilege | sudo or root for process names on sockets owned by other users; unprivileged ss and lsof may hide some PIDs |
| Scope | Check listening TCP/UDP ports locally with ss and lsof, test reachability from another host with nc and nmap, and troubleshoot bind address versus firewall versus remote access. Does not cover opening firewall ports or full ss/netstat/nmap references. |
| Related guides | ss command lsof command Test port connectivity Open a port on Linux netstat command |
"Check whether a port is open" usually means one of two things: is a service listening on this Linux host, or can another machine actually reach that port? The first question belongs to ss and lsof on the server; the second needs a test from a client with nc or nmap.
Three common questions map to these checks:
What is listening on this server? → sudo ss -tulnp
Which process owns port 8080? → sudo ss -ltnp 'sport = :8080' or sudo lsof -nP -i :8080
Can another host reach TCP port 8080? → nc -zv SERVER 8080 or nmap -p 8080 SERVERQuick Reference: Check Open Ports in Linux
| Task | Command |
|---|---|
| List listening TCP and UDP sockets | sudo ss -tulnp |
| List listening TCP ports | sudo ss -ltnp |
| List UDP sockets | sudo ss -lunp |
| Check a specific local port | sudo ss -ltnp 'sport = :22' |
| Find the process using a port | sudo lsof -nP -i :8080 |
| List listening TCP processes | sudo lsof -nP -iTCP -sTCP:LISTEN |
| Test one remote TCP port | nc -zv SERVER PORT |
| Scan specific remote ports | nmap -p 22,80,443 SERVER |
| Scan all TCP ports remotely | nmap -p- SERVER |
| Legacy listening-port command | sudo netstat -tulnp |
Use ss when you are logged into the Linux host and need a current socket list. Use lsof when you need the owning process and PID. Use nc for a quick TCP connectivity probe from another machine. Use nmap when you need formal port state from outside the host. Keep netstat for legacy scripts and older systems where ss is unavailable.
Understand open, listening, closed, and filtered ports
These terms answer different questions. Mixing them up is why a port can appear in ss locally yet fail a remote connection test.
Listening locally means a process created a socket and is waiting for traffic. Confirm with:
sudo ss -ltnpOpen from a remote scanner's perspective means a probe reached the target and found an application accepting connections on that port.
Closed means the host responded, but nothing is listening on that port.
Filtered means a firewall or other filter prevented the scanner from learning whether a service is listening.
For a typical TCP service, the relationship looks like this:
| Situation | Local ss |
Remote test |
|---|---|---|
| Service listening and reachable | Listener shown | Open or connect success |
Service listening only on 127.0.0.1 |
Listener shown | Not reachable remotely |
| Service listening but firewall blocks traffic | Listener shown | Filtered or timeout |
| Firewall allows port but nothing listens | Nothing listening | Closed |
| No listener and firewall drops traffic | Nothing listening | Filtered or timeout |
A firewall rule that permits TCP/8080 only allows packets to reach the host. A service must still listen on TCP/8080 before a normal connection succeeds. Do not describe a permitted-but-unused port as "open" in the port-scanning sense.
List listening ports with ss
The ss command is the preferred modern tool for many socket-listing tasks traditionally handled by netstat and reads socket state from the kernel. Start with every listening TCP and UDP socket:
sudo ss -tulnpSample output:
Netid State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
udp UNCONN 0 0 0.0.0.0:5353 0.0.0.0:* users:(("avahi-daemon",pid=1101,fd=12))
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1202,fd=7))
tcp LISTEN 0 511 127.0.0.1:43879 0.0.0.0:* users:(("node",pid=2407,fd=19))The flags matter:
-t— TCP sockets-u— UDP sockets-l— listening sockets only-n— numeric addresses and ports (no DNS lookups)-p— process name and PID when you run with sufficient privilege
Netid is the protocol, State is the socket state, Local Address:Port is where the service accepts traffic, and the Process column names the listener when -p can resolve it. TCP listeners normally show LISTEN; UDP sockets usually show UNCONN because UDP is connectionless. Do not expect LISTEN on UDP rows.
To list TCP listeners only:
sudo ss -ltnpSample output:
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1202,fd=7))
LISTEN 0 511 *:80 *:* users:(("httpd",pid=1228,fd=4),("httpd",pid=1295,fd=4))UDP sockets use the same tool with -u instead of -t:
sudo ss -lunpSample output:
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
UNCONN 0 0 0.0.0.0:5353 0.0.0.0:* users:(("avahi-daemon",pid=1101,fd=12))
UNCONN 0 0 127.0.0.1:323 0.0.0.0:* users:(("chronyd",pid=1102,fd=4))0.0.0.0:22 means SSH accepts IPv4 on all interfaces; 127.0.0.1:323 is chrony bound to loopback only.
Check whether a specific port is listening
Filter ss when you care about one port instead of the full table. For SSH on TCP/22:
sudo ss -ltnp 'sport = :22'Sample output:
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1202,fd=7))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=1202,fd=8))Matching rows mean a listener exists on that port. Empty output means nothing matched the filter.
The native filter is preferable to piping through grep, but this fallback works on any host:
sudo ss -ltnp | grep ':22 'Swap the port number for any check you need:
sudo ss -ltnp 'sport = :8080'When no process listens on 8080, ss prints only the header row and exits. That answers "is this port in use?" without scanning the full socket table.
Find which process is using a port
ss with -p is the fastest way to tie a port to a PID on the local host:
sudo ss -ltnp 'sport = :8080'Sample output (after starting a test listener on 8080):
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 5 127.0.0.1:8080 0.0.0.0:* users:(("python3",pid=55869,fd=5))The users:(("python3",pid=55869,fd=5)) field names the process, PID, and file descriptor.
lsof is often clearer when you want a dedicated process table:
sudo lsof -nP -i :8080Sample output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 55869 root 5u IPv4 513532 0t0 TCP 127.0.0.1:8080 (LISTEN)-i :8080 can also show established connections involving port 8080, not only a listening socket. For the TCP listener only:
sudo lsof -nP -iTCP:8080 -sTCP:LISTEN-n skips hostname resolution, -P keeps numeric ports, and -i selects network files. To list every TCP listener in one shot:
sudo lsof -nP -iTCP -sTCP:LISTENSample output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1202 root 7u IPv4 11499 0t0 TCP *:22 (LISTEN)
httpd 1228 root 4u IPv6 9954 0t0 TCP *:80 (LISTEN)Flag-level detail for lsof lives in the lsof command cheat sheet. This section only answers which process owns port X.
Check whether a port is open from another Linux host
ss reports what listens on the server. To learn whether a client can reach the service, run a test from another machine.
Example lab:
Client (192.168.1.10) ---> Server (192.168.1.20, SSH on TCP/22)From the client, probe one TCP port with nc:
nc -zv 192.168.1.20 22On this host, testing loopback shows the same success and failure shapes:
nc -zv 127.0.0.1 22Sample output:
Ncat: Connected to 127.0.0.1:22.
Ncat: 0 bytes sent, 0 bytes received in 0.04 seconds.A closed port on a reachable host usually returns connection refused:
nc -zv 127.0.0.1 59999Sample output:
Ncat: Connection refused.Connection refused typically means the packet reached the target, but no TCP service accepted the connection on that port. Connection timed out may indicate filtering, routing problems, or an unreachable host, not always a host firewall. telnet HOST PORT can test a TCP connection when Telnet is installed, but nc is generally more convenient for port checks. For a full client-to-server workflow, see test port connectivity.
Scan open ports on a remote host with nmap
nmap reports port state from the scanner's perspective. Run these from the client host in the lab (192.168.1.10) against the server (192.168.1.20). Check one port:
nmap -p 22 192.168.1.20Sample output:
PORT STATE SERVICE
22/tcp open sshScan several ports at once:
nmap -p 22,80,443 192.168.1.20Sample output:
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp closed httpsA default nmap run scans its built-in set of common ports, not all 65,535 TCP ports. To scan every TCP port on the server:
nmap -p- 192.168.1.20| Nmap state | Meaning |
|---|---|
open |
Application is accepting connections or packets |
closed |
Host responds, but no application is listening |
filtered |
Filtering prevents determining open versus closed |
open|filtered |
Nmap cannot distinguish open from filtered |
This article stops at everyday port checks. Advanced scan types and service-version enumeration belong in dedicated Nmap material, not here.
Check UDP ports
UDP is connectionless, so local and remote checks look different from TCP.
List local UDP sockets:
sudo ss -lunpRows show UNCONN rather than TCP's LISTEN. That is normal for UDP listeners.
From another host, probe UDP with Nmap (often requires root on the scanner):
sudo nmap -sU -p 53 192.168.1.20Sample output:
PORT STATE SERVICE
53/udp closed domainUDP scanning is less definitive than TCP. No response may appear as open|filtered because the scanner cannot tell whether the port accepted the probe or a filter dropped it.
Check listening ports with netstat (legacy systems)
netstat still appears in older scripts and minimal images. The listening-port view parallels ss:
sudo netstat -tulnpSample output:
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1202/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1194/cupsd
tcp6 0 0 :::22 :::* LISTEN 1202/sshdPrefer ss on current Linux systems when it is available. Flag reference and scripting notes live in the netstat command cheat sheet.
Why a port listens locally but is not reachable remotely
When sudo ss -ltnp shows the port but nc -zv SERVER PORT fails from another machine, work through these checks in order.
Bind address. 127.0.0.1:8080 accepts IPv4 traffic only through loopback. 0.0.0.0:8080 listens on all IPv4 interfaces, while [::]:8080 listens on all IPv6 interfaces. Whether an IPv6 wildcard socket also accepts IPv4 connections depends on the application's socket configuration and system settings. The bind address controls where the application accepts connections, not whether a firewall permits the port.
Host firewall. firewalld, nftables, or UFW may block traffic even when a service listens on 0.0.0.0. Opening a port is covered in open a port on Linux, not here.
Upstream controls. Cloud security groups, router ACLs, or another firewall between client and server can block traffic before it reaches the host.
Service health. Confirm the listener still exists:
sudo ss -ltnp 'sport = :8080'Replace 8080 with the port you want to verify.
Test location. A loopback nc test and a test from another subnet answer different questions. Run the probe from the network path your users actually use.
Summary
Use ss to find listening TCP and UDP sockets on the host you are logged into, lsof when you need the process and PID behind a port, nc for a quick TCP probe from another machine, and nmap when you need formal remote port state. Keep netstat for legacy compatibility when ss is not an option.
A service listening locally, a firewall permitting traffic, and a port being reachable from another host are related but separate conditions. Start with sudo ss -tulnp on the server, then verify from the client with nc or nmap when reachability is the question.

