1. Overview

A port in Linux is a virtual concept that helps in accessing different services within a network. It is a 16-bit integer ranging from 0 to 65535 with no physical existence. A port, when combined with an IP address, results in a socket address that is used to establish a connection between the client and the server.

In this tutorial, we’ll learn about open ports and how they are important in achieving a secure environment. Then, we’ll look into different Linux commands to find all the open ports.

2. What Is Open Port?

A port that is actively accepting connections is called an open port. The connection thus established is used to access the service associated with that port.

A port can be occupied by a single service/process at a time. We can kill the existing process associated with a port and reassign a new process/service to the same port.

An open port serves as an entry point. Therefore, it increases the vulnerable endpoints for our secure environment. It’s the service/process running behind the port which can lead to some serious security vulnerabilities. For example, suppose that an Apache server hosts a basic HTML page at port 80. An attacker can never create a security threat by accessing an HTML page. But on the other hand, assume that now we have hosted a PHP application with some vulnerable code. This time, the attacker can easily exploit the system by accessing our application.

Note that the port (i.e., 80) was the same in both cases. Therefore, it’s the code running on the Apache server which is causing a real threat to the system.

Hence, as a best practice, we must always close all the open ports that are not meant to be exposed publicly.

3. Find Open Ports in Linux

Let’s now dive deep into various Linux commands to identify open ports on our machine.

3.1. Using the ss Command

ss (Socket Statistics) is a CLI utility used to display socket information. It belongs to the iproute2 package, which is faster, optimized, and provides more information than the old-fashioned net-tools package.

We can use the ss command with a bunch of options to list all the open TCP ports:

$ ss -tnlp
State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process                                                  
LISTEN  0       128     0.0.0.0:111         0.0.0.0:*          users:(("rpcbind",pid=795,fd=4),("systemd",pid=1,fd=48)) 
LISTEN  0       128     0.0.0.0:22          0.0.0.0:*          users:(("sshd",pid=1230,fd=5))                               
LISTEN  0       128     *:443               *:*                users:(("httpd",pid=21905,fd=9),... 
LISTEN  0       128     [::]:111            [::]:*             users:(("rpcbind",pid=795,fd=6),("systemd",pid=1,fd=52))
LISTEN  0       128     *:80                *:*                users:(("httpd",pid=21905,fd=4),...      
LISTEN  0       128     [::]:22             [::]:*             users:(("sshd",pid=1230,fd=7))

Here we have used four options to get the desired output:

  • t: display TCP sockets
  • n: display the numeric port number
  • l: display listening sockets
  • p: Display the process using the socket

In the command output generated above, the fourth column denotes the local socket address. It is a combination of the IP address and port. These ports are all open. Moreover, we can find the process associated with that particular port in the sixth column. This column includes process details like process name, process id, and file descriptors.

Since we have used the flag l in the command, so the “State” (first column) for each row will be LISTEN. This denotes that the particular socket is in a listening state.

ss is a very powerful command with a wide range of options. We can find all the available options using the help command ss -help and plug and play with them to get the desired output.

3.2. Using netstat Command

netstat is another Linux command that displays the network connection details. However, due to a lack of support for many modern features of the Linux kernel and some optimization issues, it is officially marked as obsolete.

To find the open ports, we’ll use the same options that we used in the ss command above:

$ netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      1/systemd           
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1230/sshd           
tcp6       0      0 :::443                  :::*                    LISTEN      925/httpd           
tcp6       0      0 :::111                  :::*                    LISTEN      1/systemd           
tcp6       0      0 :::80                   :::*                    LISTEN      925/httpd           
tcp6       0      0 :::22                   :::*                    LISTEN      1230/sshd          

The options and syntax of both ss and netstat are very similar. Hence the ss command serves as a replacement for the netstat command.

3.2. Using the lsof Command

Everything is a file in Linux. lsof (List of Open Files) is a utility that lists all the open files in Linux. lsof command reads the data from kernel’s proc file system. Hence, it has the capability to trace the network connection based on process, user, application, or port.

lsof command supports various options to filter the output as per our need. Let us now look into the combination of options that will list ports used by open TCP connections:

$ lsof -i -P -sTCP:LISTEN
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd     1   root   48u  IPv4   1822      0t0  TCP *:111 (LISTEN)
systemd     1   root   52u  IPv6   1824      0t0  TCP *:111 (LISTEN)
rpcbind   795    rpc    4u  IPv4   1822      0t0  TCP *:111 (LISTEN)
rpcbind   795    rpc    6u  IPv6   1824      0t0  TCP *:111 (LISTEN)
httpd     925   root    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd     925   root    9u  IPv6  25594      0t0  TCP *:443 (LISTEN)
sshd     1230   root    5u  IPv4  28121      0t0  TCP *:22 (LISTEN)
sshd     1230   root    7u  IPv6  28123      0t0  TCP *:22 (LISTEN)
httpd   21196 apache    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd   21196 apache    9u  IPv6  25594      0t0  TCP *:443 (LISTEN)
httpd   21197 apache    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd   21197 apache    9u  IPv6  25594      0t0  TCP *:443 (LISTEN)
httpd   21223 apache    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd   21223 apache    9u  IPv6  25594      0t0  TCP *:443 (LISTEN)
httpd   21905 apache    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd   21905 apache    9u  IPv6  25594      0t0  TCP *:443 (LISTEN)

In the command above, we use the -i option to list only the network files and -P to display the numeric value of the ports instead of their names.

-sTCP:LISTEN is used to filter TCP protocol files that are in LISTEN state.

The output is similar to that of the ss command. The only difference is that the ss command groups the output based on the processes.

We can check if any port is open or not using the lsof command:

$ lsof -P -i:80
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd     925   root    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd   21196 apache    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd   21197 apache    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd   21223 apache    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)
httpd   21905 apache    4u  IPv6  25918      0t0  TCP *:80 (LISTEN)

The major drawback of the lsof command is that it requires sudo privileges to display correct output. So far, we’ve used the root user to execute all the commands.

It is clear from the output generated above that the HTTP process is running using the root/apache user. Now let us run the same lsof command using a non-root user (say centos user):

$ su centos
$ lsof -i:80

This time, it displays no output. This is because the lsof command was not able to read the proc directories of the HTTP process, which was created using the root user.

3.3. Using the nmap Command

nmap (Network Mapper) is an open-source network scanner tool that is widely used by cybersecurity experts and system administrators. This tool can be used for various purposes including OS detection, port scanning, network auditing, etc.

Unlike other commands (ss and lsof), the nmap utility can find open ports on any remote machine. We do not require access to that machine. Also, there is no need for root privileges to run this command.

Let’s perform the port scanning using the nmap command:

$ nmap google.com
Starting Nmap 7.70 ( https://nmap.org ) at 2022-01-26 19:23 UTC
Nmap scan report for google.com (142.250.190.110)
Host is up (0.018s latency).
Other addresses for google.com (not scanned): 2607:f8b0:4009:809::200e
rDNS record for 142.250.190.110: ord37s35-in-f14.1e100.net
Not shown: 998 filtered ports
PORT    STATE SERVICE
80/tcp  open  http
443/tcp open  https

Nmap done: 1 IP address (1 host up) scanned in 12.29 seconds

In the above command, we scan the ports using the hostname google.com. The nmap command will automatically fetch the IP from the DNS record. We can also use the IP in the nmap command if already known.

The output includes some basic metadata related to the host, along with the list of open ports. We can use the -v option to display the output in verbosity mode.

Notice how there are no unnecessary open ports on the google server. This is done to minimize the security risk. We’ll notice this behavior for most of the popular hostnames like youtube.com, stackoverflow.com, amazon.com, netflix.com, etc.

4. Conclusion

In this article, we’ve learned about Linux open ports and their importance in minimizing security threats. We have discussed different commands like ss, netstatlsof and nmap to find the open ports on Linux. All the commands used are open source and freely available to use.