In this tutorial you will learn how to find the port of a process running on a Linux system.
This is a very common thing we need to know when we manage applications on Linux, especially if they have been configured by someone else.
How do you find the port of a process running on Linux?
The netstat command allows to see the connections from and to our current Linux systems and it provides flags that also show which process a specific connection is related to. In the netstat output you can also see the port opened by a specific process. You can also see which ports are opened on a Linux system using the lsof, ss and fuser commands.
You will learn which netstat flags to use to show the port opened by a process on Linux and other tricks that can be very useful to manage a Linux system.
We will also go through alternatives to netstat like lsof, ss and fuser.
Let’s go for it!
What Ports Are Listening on Linux?
I see often that the concept of port is not easy to grasp for those who start learning about Linux.
A port is a communication channel opened on a Linux system when a process starts, ports allow users or programs outside of the Linux system to communicate with it.
All the examples in this tutorial are based on a common application running on Linux systems, an Apache Web Server.
When started, Apache opens ports (usually 80 or 443) that allow users to access static content or web pages hosted on our Linux system.
Ports are represented by numbers from 0 to 65535. The following table shows the meaning of different port ranges:
Port Range | How these ports are used |
0 to 1023 | Well known ports or system ports. Used by system processes to provide standard network services. Only processes with superuser privileges can open a port in this range on a Linux system. |
1024 to 49151 | Registered ports. These ports are assigned by IANA for specific applications (e.g. 1521 for Oracle). They can be opened on a system without superuser privileges. |
49152 to 65535 | Dynamic or private ports. They cannot be registered with IANA and they are used for automatically allocating ephemeral ports. |
The file /etc/services on Linux contains the details of all the reserved ports.
For example, using the grep command let’s find the port assigned to the SMTP protocol:
[ec2-user@ip-172-31-1-2 ~]$ grep -i "^smtp" /etc/services
smtp 25/tcp mail
smtp 25/udp mail
As you can see port 25 is used by the SMTP protocol, it’s one of the well-known ports considering that its value is lower than 1023 (do you remember the previous table?)
Another concept related to the concept of port is the socket.
What is a Linux socket?
A Linux socket is the combination of IP address, protocol (e.g. TCP or UDP) and port. TCP stands for Transmission Control Protocol, UDP stands for User Datagram Protocol.
Let’s start with the first command!
Netstat Command to Check Ports Listening on Linux
The main command to check open ports on a Linux system is netstat.
If I want to verify which ports are open, I can use the command netstat -na together with the grep command to filter only ports that are in listening state:
[ec2-user@ip-172-31-1-2 ~]$ netstat -na | grep -w "LISTEN"
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp6 0 0 :::111 :::* LISTEN
tcp6 0 0 :::22 :::* LISTEN
The grep command uses the -w flag to match the exact word “LISTEN”. It wouldn’t match a line that contains the word “LISTENING”.
But something is missing in the output, I would like to see what each column means…
[ec2-user@ip-172-31-1-2 ~]$ netstat -na | egrep -w "Local Address|LISTEN"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp6 0 0 :::111 :::* LISTEN
tcp6 0 0 :::22 :::* LISTEN
Using egrep I can filter the output using a OR logic that shows the lines that match either “Local Address” (one of the column names) or “LISTEN”.
Here is the meaning of the main columns:
- Proto: protocol used by the socket (tcp, udp, etc..)
- Local Address: address and port number of the local end of the socket.
- Foreign Address: address and port number of the remote end of the socket.
- State: state of the socket (LISTEN, ESTABLISHED, etc..)
When I look at the output of the netstat command I can see a list of sockets (protocol, IP address and port). And I can also quickly see that there is no Apache Web Server running on this Linux server.
How?
Because I don’t see a TCP port that I could associate to a web server, for example 80 or 443.
Let’s verify the status of Apache using the systemctl command:
[ec2-user@ip-172-31-1-2 ~]$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: man:httpd.service(8)
As you can see Apache is inactive, let’s start it!
[ec2-user@ip-172-31-1-2 ~]$ sudo systemctl start httpd
[ec2-user@ip-172-31-1-2 ~]$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: active (running) since Mon 2020-08-03 11:10:54 UTC; 13s ago
Docs: man:httpd.service(8)
Main PID: 5256 (httpd)
Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec: 0 B/sec"
CGroup: /system.slice/httpd.service
├─5256 /usr/sbin/httpd -DFOREGROUND
├─5257 /usr/sbin/httpd -DFOREGROUND
├─5258 /usr/sbin/httpd -DFOREGROUND
├─5259 /usr/sbin/httpd -DFOREGROUND
├─5260 /usr/sbin/httpd -DFOREGROUND
└─5261 /usr/sbin/httpd -DFOREGROUND
Aug 03 11:10:54 ip-172-31-1-2.....compute.internal systemd[1]: Starting The Apache HTTP Server...
Aug 03 11:10:54 ip-172-31-1-2.....compute.internal systemd[1]: Started The Apache HTTP Server.
And now the output of the netstat command is:
[ec2-user@ip-172-31-1-2 ~]$ netstat -na | egrep -w "Local Address|LISTEN"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp6 0 0 :::111 :::* LISTEN
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 :::22 :::* LISTEN
This time port 80 is in LISTEN state.
Confirming The Apache Port with Netstat
I’m pretty sure this is the port for the Apache Web Server, but how can I confirm that?
The netstat command provides an additional flag to show the PID and the name of the program a specific socket relates to. The -p flag, where p stands for program:
[ec2-user@ip-172-31-1-2 ~]$ netstat -nap | egrep -w "Local Address|LISTEN"
(No info could be read for "-p": geteuid()=1000 but you should be root.)
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 -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN -
tcp6 0 0 :::111 :::* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
Hmmm, I was expecting to see something next to LISTEN that would give me more details about the programs opening each port.
As you can see, the values of the column PID/Program name (ID and name of the process that owns the socket) are not visible.
Why I can’t see anything?
That’s because…
Only the process owner and the root user can retrieve detailed informations about processes running on a Linux system.
So, who is the owner of the Apache process? The ps command can help us find this out:
[ec2-user@ip-172-31-1-2 ~]$ ps -aef | grep httpd
root 5256 1 0 11:10 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5257 5256 0 11:10 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5258 5256 0 11:10 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5259 5256 0 11:10 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5260 5256 0 11:10 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 5261 5256 0 11:10 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
The parent process with PID 5256 has been started by root and the child processes by the apache user.
The reason why I can’t see any details about the PID of the processes using the netstat command, is that I’m running the command as the ec2-user.
To see more details in the output I have to provide the sudo command before the netstat command.
[ec2-user@ip-172-31-1-2 ~]$ sudo netstat -nap | egrep -w "Local Address|LISTEN"
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 2675/rpcbind
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 3322/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 3160/master
tcp6 0 0 :::111 :::* LISTEN 2675/rpcbind
tcp6 0 0 :::80 :::* LISTEN 5256/httpd
tcp6 0 0 :::22 :::* LISTEN 3322/sshd
This time the output is a lot better!
I can see that the httpd process with PID 5256 has opened port 80.
The -n flag in our netstat command shows addresses in a numerical form, this applies to both IP addresses and ports.
Have a look at output if we remove the -n flag:
[ec2-user@ip-172-31-1-2 ~]$ sudo netstat -ap | egrep -w "Local Address|LISTEN"
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:sunrpc 0.0.0.0:* LISTEN 2675/rpcbind
tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN 3322/sshd
tcp 0 0 localhost:smtp 0.0.0.0:* LISTEN 3160/master
tcp6 0 0 [::]:sunrpc [::]:* LISTEN 2675/rpcbind
tcp6 0 0 [::]:http [::]:* LISTEN 5256/httpd
tcp6 0 0 [::]:ssh [::]:* LISTEN 3322/sshd
Can you see the difference?
The netstat command is one of the most used commands to verify network connections on a Linux system.
Check If a Port is Open with Lsof
The lsof command stands for “List of open files” and it’s used to list all the files opened by processes on Linux.
But, what have files to do with open ports?
As I mentioned before…
Everything in Linux is a file and sockets are special types of files.
Let’s see how to use the lsof command to see which port is being opened by our Apache Web Server…
…don’t forget the sudo command as I explained before. Also remember that the PID for Apache on my Linux system is 5256:
[ec2-user@ip-172-31-1-2 ~]$ sudo lsof -p 5256 | grep LISTEN
httpd 5256 root 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
The -p flag takes as argument the PID of the process for which we want to find out the port, and the TCP *:http part of the output shows that the port opened by that process is the http port.
What if I want to know the port number mapped to http?
You can add the -P flag that disables the conversion from port numbers to port names:
[ec2-user@ip-172-31-1-2 ~]$ sudo lsof -p 5256 -P | grep LISTEN
httpd 5256 root 4u IPv6 11070402 0t0 TCP *:80 (LISTEN)
This shows that the Apache process has opened port 80 on my Linux host.
And what if I want to find the process opening a different port?
I can use the -i flag that retrieves the list of files that match the Internet address specified after the flag.
The generic syntax is:
lsof -i :port_number
Let’s see it in practice:
[ec2-user@ip-172-31-1-2 ~]$ sudo lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 5256 root 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5257 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5258 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5259 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5260 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5261 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
In the output of the lsof command you can see useful details like process name, PID and user owner.
You can also pass multiple ports to the lsof command:
[ec2-user@ip-172-31-1-2 ~]$ sudo lsof -i :80 -i :22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 3322 root 3u IPv4 20024 0t0 TCP *:ssh (LISTEN)
sshd 3322 root 4u IPv6 20026 0t0 TCP *:ssh (LISTEN)
httpd 5256 root 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5257 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5258 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5259 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5260 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
httpd 5261 apache 4u IPv6 11070402 0t0 TCP *:http (LISTEN)
sshd 10877 root 3u IPv4 11166512 0t0 TCP ip-172-31-1-2.mydomain:ssh->31.127.78.158:57775 (ESTABLISHED)
sshd 10895 ec2-user 3u IPv4 11166512 0t0 TCP ip-172-31-28-249.mydomain:ssh->31.127.78.158:57775 (ESTABLISHED)
Makes sense?
Using The SS Command To Find Open Ports on Linux
What is the ss command?
The ss command is similar to the netstat command and it can be used to retrieve details about sockets on Linux.
You will notice similar flags to the netstat ones.
The following command shows listening sockets ( -l flag ), the name of the process (or processes) opening the socket ( -p flag ) and filters only based on TCP sockets ( -t flag).
[ec2-user@ip-172-31-1-2 ~]$ sudo ss -tlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:sunrpc 0.0.0.0:* users:(("rpcbind",pid=2675,fd=8))
LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:* users:(("sshd",pid=3322,fd=3))
LISTEN 0 100 127.0.0.1:smtp 0.0.0.0:* users:(("master",pid=3160,fd=13))
LISTEN 0 128 [::]:sunrpc [::]:* users:(("rpcbind",pid=2675,fd=11))
LISTEN 0 128 *:http *:* users:(("httpd",pid=5261,fd=4),("httpd",pid=5260,fd=4),("httpd",pid=5259,fd=4),("httpd",pid=5258,fd=4),("httpd",pid=5257,fd=4),("httpd",pid=5256,fd=4))
LISTEN 0 128 [::]:ssh [::]:* users:(("sshd",pid=3322,fd=4))
The format of the output has also something similar to the netstat output, have a look at the column names…
To also see any UDP port in listening state, you can add the -u flag:
sudo ss -tulp
Now, I want to see just the process (or processes) that listen on port 80.
How do I do it with ss?
Here is the generic syntax of the ss command:
ss [options] [ FILTER ]
The second argument is a filter, let’s see an example of the filter for port 80:
[ec2-user@ip-172-31-1-2 ~]$ sudo ss -tlp 'sport = :80'
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:http *:* users:(("httpd",pid=5261,fd=4),("httpd",pid=5260,fd=4),("httpd",pid=5259,fd=4),("httpd",pid=5258,fd=4),("httpd",pid=5257,fd=4),("httpd",pid=5256,fd=4))
You can see the word sport in the filter, it stands for source port.
As with every command, you can use the man command to see more details about ss.
And this is not the end, there’s another command!
Use the Linux Fuser Command to Find a TCP Port
It’s very cool how Linux allows to do the same thing in many different ways!
Another option you have is the fuser command.
The fuser command identities processes using files or sockets on a Linux system.
Its syntax is:
fuser <port_name>/<protocol>
So, to find the PID of the processes that are opening TCP port 80 you can use the following command:
[ec2-user@ip-172-31-1-2 ~]$ sudo fuser http/tcp
http/tcp: 5256 5257 5258 5259 5260 5261
You can also replace http with 80:
[ec2-user@ip-172-31-1-2 ~]$ sudo fuser 80/tcp
80/tcp: 5256 5257 5258 5259 5260 5261
You can then use the ps command to see more details about the PIDs returned by the fuser command.
But there’s also a quicker option…
Try to pass the -v flag to the fuser command:
[ec2-user@ip-172-31-1-2 ~]$ sudo fuser 80/tcp -v
USER PID ACCESS COMMAND
80/tcp: root 5256 F.... httpd
apache 5257 F.... httpd
apache 5258 F.... httpd
apache 5259 F.... httpd
apache 5260 F.... httpd
apache 5261 F.... httpd
And voilà!
You also get details about the processes opening port 80. Very useful!
Conclusion
We went through so many options to get the port opened by a Linux process and also to get the PIDs starting from a port number.
It’s critical to know all the ports that are open on your Linux system to keep your system secure.
Why?
Because services running on well-known ports can be exploited to get access to your Linux system in case the version of your service is subject to vulnerabilities.
So, keeping an eye to ports in LISTEN state on your machine is the first step to keep it secure.
Which command do you prefer to find the port opened by a process? Netstat, lsof, ss or fuser?
Let me know in the comments 🙂
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design. He is a professional certified by the Linux Professional Institute.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for robotics with Raspberry Pi.