How to Check Listening Ports in Linux: ss, netstat, lsof

By 

•

Updated on

•

12 min read

Check Listening Ports in Linux

When troubleshooting network connectivity or application-specific issues, one of the first things to check is what ports are actually in use on your system and which application is listening on a specific port.

This article explains how to use the ss command , netstat, and the lsof command to find out which services are listening on which ports. The example output comes from an Ubuntu 26.04 server running SSH, Apache, and MySQL, but the commands work the same way on any modern distribution.

What is a Listening Port

A network port is identified by its number, the associated IP address, and the type of the communication protocol, such as TCP or UDP.

The IP address matters as much as the port number. A service bound to localhost at 127.0.0.1 accepts connections only from the same machine, while one bound to 0.0.0.0 listens on every IPv4 interface. Firewall and routing rules still determine whether remote clients can reach it.

A listening port is a network port on which an application or process listens, acting as a communication endpoint.

A local listening socket does not guarantee that the port is reachable from another host. A firewall can allow or block traffic to it, and a network scan may report the port as open, closed, or filtered. In general terms, an open port accepts incoming packets from the system running the scan.

Normally, two services cannot independently bind to the same port, protocol, and IP address.

For example, if you are running an Apache web server that listens on ports 80 and 443 and you try to install Nginx , the latter will fail to start because the HTTP and HTTPS ports are already in use.

Check Listening Ports with ss

ss is the modern replacement for netstat. It is faster, provides more detailed TCP state information, and is installed by default on all modern Linux distributions.

To get a list of all listening ports with ss, type:

Terminal
sudo ss -tunlp

The options used in this command have the following meaning:

  • -t - Show TCP ports.
  • -u - Show UDP ports.
  • -n - Show numerical addresses instead of resolving hosts.
  • -l - Show only listening ports.
  • -p - Show the process using the socket. Run the command as root or with sudo to see sockets owned by other users.

The output will look something like this:

output
Netid State  Recv-Q Send-Q    Local Address:Port  Peer Address:Port Process
udp   UNCONN 0      0            127.0.0.54:53         0.0.0.0:*    users:(("systemd-resolve",pid=499,fd=18))
udp   UNCONN 0      0         127.0.0.53%lo:53         0.0.0.0:*    users:(("systemd-resolve",pid=499,fd=16))
udp   UNCONN 0      0      10.0.2.15%enp0s1:68         0.0.0.0:*    users:(("systemd-network",pid=988,fd=33))
udp   UNCONN 0      0             127.0.0.1:323        0.0.0.0:*    users:(("chronyd",pid=1208,fd=4))
udp   UNCONN 0      0                 [::1]:323           [::]:*    users:(("chronyd",pid=1208,fd=5))
tcp   LISTEN 0      151           127.0.0.1:3306       0.0.0.0:*    users:(("mysqld",pid=3671,fd=22))
tcp   LISTEN 0      4096      127.0.0.53%lo:53         0.0.0.0:*    users:(("systemd-resolve",pid=499,fd=17))
tcp   LISTEN 0      70            127.0.0.1:33060      0.0.0.0:*    users:(("mysqld",pid=3671,fd=19))
tcp   LISTEN 0      4096         127.0.0.54:53         0.0.0.0:*    users:(("systemd-resolve",pid=499,fd=19))
tcp   LISTEN 0      4096            0.0.0.0:22         0.0.0.0:*    users:(("sshd",pid=1309,fd=3),("systemd",pid=1,fd=358))
tcp   LISTEN 0      4096               [::]:22            [::]:*    users:(("sshd",pid=1309,fd=4),("systemd",pid=1,fd=359))
tcp   LISTEN 0      511                   *:80               *:*    users:(("apache2",pid=4387,fd=4),("apache2",pid=4386,fd=4),("apache2",pid=4370,fd=4))

The important columns are:

  • Netid - The socket type, tcp or udp.
  • State - The socket state. LISTEN means a TCP port is waiting for incoming connections. UDP is connectionless and never enters the LISTEN state, so a UDP service waiting for datagrams shows UNCONN.
  • Local Address:Port - The IP address and port number the process listens on.
  • Process - The name, PID, and file descriptor of each process using the socket.

The local address shows which addresses and interfaces the service is bound to. In the output above, MySQL listens on 127.0.0.1:3306, so only programs on the same machine can connect to it. SSH listens on 0.0.0.0:22 (all IPv4 interfaces) and [::]:22 (all IPv6 interfaces). On this server, Apache shows *:80 for a dual-stack socket that accepts both IPv4 and IPv6 connections. A suffix such as %lo means the socket is bound to one network interface only.

You may also notice that port 22 lists two processes, sshd and systemd with PID 1. Recent Ubuntu releases start SSH through systemd socket activation: systemd opens the listening socket and passes it to sshd, so both processes hold the same socket. This is expected and does not mean that two services are fighting over the port.

To filter the results, you can pipe the output through grep . For example, to find what process listens on TCP port 22:

Terminal
sudo ss -tnlp | grep :22

The matching sockets are:

output
LISTEN 0      4096         0.0.0.0:22         0.0.0.0:*    users:(("sshd",pid=1309,fd=3),("systemd",pid=1,fd=358))
LISTEN 0      4096            [::]:22            [::]:*    users:(("sshd",pid=1309,fd=4),("systemd",pid=1,fd=359))

The ss command also has built-in filtering, which is faster than piping through grep:

Terminal
sudo ss -tlnp sport = :22

The exact port filter returns the same two SSH sockets:

output
State  Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0      4096         0.0.0.0:22        0.0.0.0:*    users:(("sshd",pid=1309,fd=3),("systemd",pid=1,fd=358))
LISTEN 0      4096            [::]:22           [::]:*    users:(("sshd",pid=1309,fd=4),("systemd",pid=1,fd=359))

Unlike grep :22, the sport = :22 expression matches the local port exactly, so it does not also return ports such as 2222.

You can also filter by state, source address, or destination address. For example, to show all connections in the ESTABLISHED state:

Terminal
ss -tn state established

On this server, one SSH connection is established:

output
Recv-Q Send-Q Local Address:Port Peer Address:Port
0      0          10.0.2.15:22       10.0.2.2:54758

The State column is gone because every row is in the same state. Here, the only established connection is the SSH session from 10.0.2.2.

Check Listening Ports with netstat

netstat is a legacy command-line tool that provides information about network connections. On modern Linux distributions, netstat is not installed by default. It is part of the net-tools package, which you can install with:

Terminal
# Ubuntu, Debian, and derivatives
sudo apt install net-tools

# Fedora, RHEL, and derivatives
sudo dnf install net-tools

To list all TCP or UDP ports that are listening, including the services using the ports and the socket status:

Terminal
sudo netstat -tunlp

The options are the same as with ss:

  • -t - Show TCP ports.
  • -u - Show UDP ports.
  • -n - Show numerical addresses instead of resolving hosts.
  • -l - Show only listening ports.
  • -p - Show the PID and name of the listener’s process. Run the command as root or with sudo to see sockets owned by other users.

The output will look something like this:

output
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      3671/mysqld
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      499/systemd-resolve
tcp        0      0 127.0.0.1:33060         0.0.0.0:*               LISTEN      3671/mysqld
tcp        0      0 127.0.0.54:53           0.0.0.0:*               LISTEN      499/systemd-resolve
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1/systemd
tcp6       0      0 :::22                   :::*                    LISTEN      1/systemd
tcp6       0      0 :::80                   :::*                    LISTEN      4370/apache2
udp        0      0 127.0.0.54:53           0.0.0.0:*                           499/systemd-resolve
udp        0      0 127.0.0.53:53           0.0.0.0:*                           499/systemd-resolve
udp        0      0 10.0.2.15:68            0.0.0.0:*                           988/systemd-network
udp        0      0 127.0.0.1:323           0.0.0.0:*                           1208/chronyd
udp6       0      0 ::1:323                 :::*                                1208/chronyd

The important columns are:

  • Proto - The protocol used by the socket.
  • Local Address - The IP address and port number the process listens on.
  • PID/Program name - The PID and the name of the process.

Compare this with the ss output. netstat prints only one process per socket, so port 22 shows 1/systemd instead of sshd, and Apache shows a single apache2 process instead of all three. The State column is empty for UDP sockets, and Apache appears only as tcp6 on :::80, even though that socket also accepts IPv4 connections.

To find what process listens on a specific port, for example TCP port 22:

Terminal
sudo netstat -tnlp | grep :22

The matching entries are:

output
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1/systemd
tcp6       0      0 :::22                   :::*                    LISTEN      1/systemd

If the output is empty, nothing is listening on that port. To test a port from another host, use netcat .

netstat is obsolete and replaced with ss and ip , but it is still one of the most used commands for checking network connections.

Check Listening Ports with lsof

lsof is a powerful command-line utility that provides information about files opened by processes.

In Linux, everything is a file. You can think of a socket as a file that writes to the network.

If lsof is not available on your system, install it with:

Terminal
# Ubuntu, Debian, and derivatives
sudo apt install lsof

# Fedora, RHEL, and derivatives
sudo dnf install lsof

To get a list of all listening TCP ports with lsof, type:

Terminal
sudo lsof -nP -iTCP -sTCP:LISTEN

The options used are as follows:

  • -n - Do not resolve hostnames, show numerical addresses.
  • -P - Do not convert port numbers to port names.
  • -iTCP -sTCP:LISTEN - Show only network files with TCP state LISTEN.

The output lists each process that holds a listening TCP socket:

output
COMMAND    PID            USER  FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd      1            root 358u  IPv4  18858      0t0  TCP *:22 (LISTEN)
systemd      1            root 359u  IPv6  18860      0t0  TCP *:22 (LISTEN)
systemd-r  499 systemd-resolve  17u  IPv4  10129      0t0  TCP 127.0.0.53:53 (LISTEN)
systemd-r  499 systemd-resolve  19u  IPv4  10131      0t0  TCP 127.0.0.54:53 (LISTEN)
sshd      1309            root   3u  IPv4  18858      0t0  TCP *:22 (LISTEN)
sshd      1309            root   4u  IPv6  18860      0t0  TCP *:22 (LISTEN)
mysqld    3671           mysql  19u  IPv4  27468      0t0  TCP 127.0.0.1:33060 (LISTEN)
mysqld    3671           mysql  22u  IPv4  31568      0t0  TCP 127.0.0.1:3306 (LISTEN)
apache2   4370            root   4u  IPv6  32272      0t0  TCP *:80 (LISTEN)
apache2   4386        www-data   4u  IPv6  32272      0t0  TCP *:80 (LISTEN)
apache2   4387        www-data   4u  IPv6  32272      0t0  TCP *:80 (LISTEN)

Most of the output column names are self-explanatory:

  • COMMAND, PID, USER - The name, the PID, and the user running the program associated with the port. lsof shortens long command names, so systemd-resolve appears as systemd-r.
  • NAME - The address and port the socket is bound to, followed by the TCP state. An asterisk (*) means the socket listens on all interfaces.

Like ss, lsof shows both systemd and sshd on port 22, and each Apache process on its own line. The USER column shows that the Apache parent process runs as root, while its workers run as www-data.

The quickest way to check a single port with lsof is the -i :PORT form. The following command shows every process that has port 80 open:

Terminal
sudo lsof -i :80

On the example server, the result is:

output
COMMAND  PID     USER FD   TYPE DEVICE SIZE/OFF NODE NAME
apache2 4370     root 4u  IPv6  32272      0t0  TCP *:http (LISTEN)
apache2 4386 www-data 4u  IPv6  32272      0t0  TCP *:http (LISTEN)
apache2 4387 www-data 4u  IPv6  32272      0t0  TCP *:http (LISTEN)

Without -P, lsof translates the port number into its service name from /etc/services, which is why the NAME column shows http instead of 80. The -i :80 form matches TCP and UDP sockets in any state, so on a busy web server it also lists established connections to and from port 80.

To find only the process listening on a particular port, for example port 3306, add the protocol and the state filter:

Terminal
sudo lsof -nP -iTCP:3306 -sTCP:LISTEN

The output shows that the MySQL server uses port 3306 and accepts connections only on 127.0.0.1:

output
COMMAND  PID  USER FD   TYPE DEVICE SIZE/OFF NODE NAME
mysqld  3671 mysql 22u  IPv4  31568      0t0  TCP 127.0.0.1:3306 (LISTEN)

UDP sockets have no LISTEN state, so drop the -s filter when you look for UDP services:

Terminal
sudo lsof -nP -iUDP

For more information, visit the lsof man page and read about all other powerful options of this tool.

Common Mistakes

  • Forgetting sudo. Without root privileges, the -p flag will not show the process name or PID for ports owned by other users. The port will appear in the output, but the process column will be empty. Depending on how lsof was built and the system security settings, its non-root output may also be limited to your own processes.
  • Confusing listening and established connections. The -l flag shows only listening ports. Without it, ss and netstat show all connections, including established ones. If you only care about what services are running, always use -l.
  • Looking for UDP services in the LISTEN state. UDP sockets show UNCONN in ss and an empty state in netstat. Filtering the output with grep LISTEN hides every UDP socket, such as the chronyd monitoring port used by chronyc on 323.
  • Searching for a port without the colon. When using grep to filter by port, always include the colon (e.g., grep :22). Searching for just 22 will also match PIDs, addresses, and other numbers that contain 22.

Quick Reference

For printable quick references, see the ss cheatsheet , netstat cheatsheet , and lsof cheatsheet .

TaskCommand
List all listening portssudo ss -tunlp
List listening UDP portssudo ss -unlp
List all listening ports (netstat)sudo netstat -tunlp
Find process on a specific portsudo ss -tlnp sport = :80
Find process on a specific port (grep)sudo ss -tnlp | grep :80
Find processes using port 80 (lsof)sudo lsof -i :80
List listening TCP ports (lsof)sudo lsof -nP -iTCP -sTCP:LISTEN
Find process on port 3306 (lsof)sudo lsof -nP -iTCP:3306 -sTCP:LISTEN
Show established connectionsss -tn state established
Show all connections with process infosudo ss -tunp

FAQ

What is the difference between ss and netstat?
Both show network connection information. ss is the modern replacement. It is faster, provides more TCP state details, and is installed by default on modern Linux distributions. netstat requires the net-tools package and is considered obsolete.

Why is the process column empty in the output?
You can generally see process information for sockets owned by your account. Run the command as root or with sudo to see details for sockets owned by other users. Some systems may impose additional restrictions on lsof output.

How do I check if a specific port is open from a remote machine?
The commands in this article check listening ports on the local system. To test whether a port is reachable from a remote machine, use netcat (nc -zv host port) or nmap.

Can two services listen on the same port?
Not normally. Two services cannot independently bind to the same port, protocol, and IP address simultaneously. The SO_REUSEPORT socket option lets processes that all opt in share a port for load balancing, while socket activation can pass one listener from systemd to a service such as sshd. Otherwise, a service trying to claim an address that is already in use will fail. To trace that error back to the process holding the port, see the guide on how to find which process is using a port .

Conclusion

The ss command is the standard choice for checking listening ports, while lsof provides a process-focused view and netstat remains available on older systems. For details beyond these common tasks, open the local manuals with man ss, man netstat, or man lsof.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page