The Need for Network Visibility
If you are managing a Linux server, whether it is a small Raspberry Pi running a home media server or an enterprise web server hosted on AWS, understanding exactly what is listening on your network interfaces is critical for security and troubleshooting.
Every service on your machine communicates through a specific numbered “port.” For example, SSH listens on port 22, HTTP listens on port 80, and HTTPS listens on port 443. If a port is “open” and listening, it means an application is actively waiting for an incoming connection from the outside world.
If you cannot connect to a web server you just installed, you need to check if the port is actually open. Conversely, if you suspect a server has been compromised, you need to see if a malicious backdoor is secretly listening on an unknown port.
Historically, Linux administrators used the venerable netstat command for this task. However, netstat is now officially deprecated and has been replaced by a much faster, more powerful, and more detailed tool: the ss (socket statistics) command.
How to Check Open Ports Using ss
The ss command is built into almost all modern Linux distributions (Ubuntu, Debian, CentOS, RHEL) by default. You do not need to install any additional packages to use it.
To get a clean, human-readable list of every open port actively listening for connections, open your terminal and run the following command (you should run this with sudo privileges to see exactly which processes own the ports):
sudo ss -tulwn
Let us break down exactly what those five flags mean, as they are crucial for filtering out the noise:
-t(TCP): Displays only TCP sockets (the reliable connection protocol used by web browsers and SSH).-u(UDP): Displays only UDP sockets (the fast, connectionless protocol used by DNS and video games).-l(Listening): This is the most important flag. It tellsssto only show sockets that are actively waiting for incoming connections (open ports), rather than showing thousands of lines of established background connections to other servers.-w(Raw): Displays raw sockets (optional, but good for completeness).-n(Numeric): Stopsssfrom trying to resolve IP addresses into hostnames and port numbers into service names. It forces the output to show raw numbers (e.g.,127.0.0.1:80instead oflocalhost:http), which makes the output much faster to generate and much easier to read.
How to Identify the Process Owning the Port
Knowing that port 8080 is open is only half the battle; you need to know which specific application is holding that port open.
To see the process ID (PID) and the name of the program, simply add the -p flag to your command. (Note: You must run this with sudo, or the system will hide the process information for security reasons).
sudo ss -tulwnp
Look at the far right column of the output under “Process.” You will see something that looks like this: users:(("nginx",pid=1234,fd=6)). This instantly tells you that the Nginx web server (Process ID 1234) is the application keeping that port open.
How to Search for a Specific Port
If you are running a complex server with dozens of Docker containers, the ss output might still be too long to comfortably read. If you only want to know if a specific port (like port 3306 for MySQL) is open, you can pipe the output into the grep command to filter the results.
sudo ss -tulwnp | grep ":3306"
If the command returns a line of text, the port is open and listening. If it returns absolutely nothing (just a blank new prompt), the port is closed, meaning your database server is either crashed, stopped, or misconfigured.
Understanding the “Local Address” Column
When you look at the ss output, the “Local Address:Port” column tells you exactly where the port is listening. This is a vital security metric.
127.0.0.1:3306or[::1]:3306: This means the port is only listening on “localhost.” The application can only be accessed by other programs running on the exact same server. It is completely protected from the outside internet.0.0.0.0:80or*:80: This means the port is bound to all available network interfaces. It is completely open to the outside world, and anyone on the internet can attempt to connect to it.
If you see a sensitive database (like MySQL or Redis) listening on 0.0.0.0 instead of 127.0.0.1, you have a major security vulnerability and should immediately update your application’s configuration file to bind to localhost.