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, netstat, lsof and nmap to find the open ports on Linux. All the commands used are open source and freely available to use.