When something on a server is holding port 80, a connection is refusing to close, or a service is not reachable from the outside, the first question is almost always the same: what is actually listening, and who is talking to whom. For years, the answer on Linux was the netstat command.
netstat is part of the classic net-tools package and prints network connections, listening ports, routing tables, interface counters, and per-protocol statistics. It has been deprecated in favor of ss
and ip
, but it is still installed on many systems and the tool many sysadmins reach for first. This guide explains how to read its output and which flags cover the cases you run into day to day.
Install netstat #
On most modern distributions, net-tools is not installed by default. If netstat is not available, install it with your package manager.
On Ubuntu, Debian, and Derivatives:
sudo apt install net-tools
On Fedora, RHEL, and Derivatives:
sudo dnf install net-tools
Once the package is installed, verify the binary is on your path:
netstat Syntax #
The general form of the command is:
Run without options, netstat prints a list of open non-listening sockets, which is rarely what you want. In practice, you almost always pass a combination of flags that describe what kind of sockets you care about (TCP, UDP, Unix), what state they are in, and how you want the output formatted.
List All Connections #
To list every connection, both listening and established, use the -a option:
The output is divided into two parts. The top lists Internet sockets with columns for protocol, receive and send queue sizes, local and foreign address, and state. The bottom lists Unix domain sockets used for local inter-process communication.
Running netstat with sudo is recommended because without it, the command cannot read socket ownership for processes that belong to other users.
Show TCP and UDP Connections #
The -t and -u flags filter the output by protocol. To show only TCP connections:
To show only UDP connections:
You can combine both flags to get TCP and UDP together:
Show Listening Ports #
When you want to know which services are accepting new connections, use the -l option. For TCP, it restricts the output to sockets in the LISTEN state. UDP does not use the same connection states, but UDP sockets that are ready to receive traffic are still shown.
The combined flags read as: show TCP (-t) and UDP (-u) sockets that are listening (-l), with numeric addresses and ports (-n). The output looks similar to this:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
tcp6 0 0 :::80 :::* LISTEN
udp 0 0 0.0.0.0:68 0.0.0.0:*
From the output, we can see that SSH is listening on all interfaces on port 22, MySQL is bound to localhost only on port 3306, and a web server is listening on port 80 over IPv6.
Show the Process Using a Port #
To find out which program owns a socket, add the -p option. It prints the PID and the process name next to each connection:
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 812/sshd
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 1034/mysqld
tcp6 0 0 :::80 :::* LISTEN 1591/nginx: master
The PID/Program name column ties each listening port to a process. This is the quickest way to find out which service is holding a port when you get an Address already in use error.
To check one specific port, pipe the output to grep
:
sudo netstat -tulnp | grep ':80'
If the command prints a row, a process is listening on port 80. If it prints nothing, no TCP or UDP listener matched that port on the local system.
Show Numeric Output #
By default, netstat resolves IP addresses to hostnames and port numbers to service names (for example, 22 becomes ssh). On a busy system, this can be slow because each address needs a DNS lookup.
The -n option disables name resolution and prints raw numbers:
Numeric output is also easier to pipe into other tools such as grep or awk, because the field values are predictable.
Continuous Monitoring #
The -c option tells netstat to print the output every second until you stop it with Ctrl+C. It is useful when you want to watch a connection appear, change state, and close:
Each iteration prints the full table again, so it is best used together with a filter such as grep to isolate a single connection.
Show TCP Connection States #
TCP connections move through states such as ESTABLISHED, LISTEN, TIME_WAIT, and CLOSE_WAIT. To show active TCP sockets with numeric addresses, run:
The State column tells you where each connection is in the TCP lifecycle:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 192.168.1.10:22 192.168.1.5:52710 ESTABLISHED
tcp 0 0 192.168.1.10:80 203.0.113.25:51422 TIME_WAIT
tcp 0 0 127.0.0.1:3306 127.0.0.1:41834 CLOSE_WAIT
ESTABLISHED means the connection is active. TIME_WAIT is normal after a connection closes. A large number of CLOSE_WAIT entries can mean the local application is not closing sockets correctly.
To show only established TCP connections, filter the output:
sudo netstat -ant | grep ESTABLISHED
For new troubleshooting work, ss
gives better built-in state filters, such as ss -tn state established.
Count Connections #
On busy web servers, you may want a quick count instead of a full connection table. To count all current TCP connections that involve port 80, run:
sudo netstat -ant | grep ':80' | wc -l
To count only established connections on port 80, add the TCP state to the filter:
sudo netstat -ant | grep ':80' | grep ESTABLISHED | wc -l
These counts are useful as a quick signal, but they are not a replacement for application metrics. The number can change while the pipeline is running, especially on high-traffic systems.
Display the Routing Table #
To print the kernel IP routing table, use the -r option:
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
The first row is the default route, which sends all traffic not matching another rule to 192.168.1.1. The ip route command from ip
is the modern equivalent and is what you should use on new systems.
Interface Statistics #
The -i option prints a per-interface summary that includes received and transmitted packets, errors, drops, and the MTU:
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP TX-OK TX-ERR TX-DRP Flg
eth0 1500 2345678 0 12 1987654 0 0 BMRU
lo 65536 55432 0 0 55432 0 0 LRU
A growing RX-ERR or TX-ERR column is a hint that you have a cabling, duplex, or driver issue on that interface.
Protocol Statistics #
To print a summary of statistics for each protocol, use -s:
The output is long and grouped by protocol (Ip, Tcp, Udp, and so on). It includes counters such as total packets received, segments retransmitted, and connection resets. You can narrow the output to a single protocol by combining -s with -t or -u:
netstat vs ss #
On modern Linux distributions, ss is the recommended replacement for netstat. It is faster and reads information directly from the kernel through Netlink, with richer filter support. The ip command replaces the routing and interface parts of netstat.
A few common translations:
-
netstat -tuln is equivalent to ss -tuln
-
netstat -tulnp is equivalent to sudo ss -tulnp
-
netstat -s maps to ss -s (a much shorter summary)
-
netstat -i maps to ip -s link
-
netstat -r maps to ip route
For a full walkthrough of the replacement tool, see the guide on the ss command
.
Quick Reference #
For a printable quick reference, see the netstat cheatsheet
.
| Command |
Description |
netstat |
Show active non-listening sockets |
sudo netstat -a |
Show all listening and non-listening sockets |
sudo netstat -at |
Show all TCP sockets |
sudo netstat -au |
Show all UDP sockets |
sudo netstat -tuln |
Show TCP and UDP listening sockets with numeric output |
sudo netstat -tulnp |
Show listening sockets with PID and process name |
sudo netstat -tulnp | grep ':80' |
Find the process listening on port 80 |
sudo netstat -ant |
Show all TCP sockets with numeric addresses |
sudo netstat -ant | grep ESTABLISHED |
Show established TCP connections |
sudo netstat -ant | grep ':80' | wc -l |
Count TCP connections involving port 80 |
sudo netstat -atnc |
Refresh TCP connection output every second |
netstat -rn |
Show the routing table with numeric addresses |
netstat -i |
Show interface statistics |
netstat -s |
Show protocol statistics |
netstat -st |
Show TCP protocol statistics |
Troubleshooting #
netstat: command not found
The net-tools package is not installed. Install it with your package manager, or use ss instead.
No PID/Program name column shown
You need to run the command with sudo. Without root privileges, netstat cannot read process information for sockets owned by other users.
Output is slow or hangs
DNS resolution is slow or failing. Add the -n option to disable name lookups and print numeric addresses and ports.
A port shows up as LISTEN on :: but not on 0.0.0.0
The service is listening on the IPv6 wildcard address. On systems with dual-stack enabled, this accepts IPv4 traffic too. Check your IPv6 configuration if only IPv4 clients are failing.
FAQ #
Is netstat deprecated?
Yes. The net-tools suite, which includes netstat, ifconfig, and route, has been deprecated for years in favor of the iproute2 tools ss and ip. It is still functional and still shipped by most distributions, but new scripts should target ss and ip.
What is the difference between netstat on Linux and Windows?
The command name is the same, and the general idea is the same, but the flags are different. This guide covers the Linux version from net-tools. On Windows, the closest equivalents to netstat -tulnp are netstat -ano and Get-NetTCPConnection in PowerShell.
How do I find what process is using a specific port?
Run sudo netstat -tulnp | grep ':PORT', replacing PORT with the port number. The last column shows the PID and program name. With ss, the same query is sudo ss -tulnp 'sport = :PORT'.
Why is a port still TIME_WAIT after I stopped the service?
TIME_WAIT is a normal TCP state that keeps a closed connection around for a short period so late packets can be handled safely. The kernel clears these entries automatically, usually within one or two minutes.
Conclusion #
netstat remains useful when you need to inspect network connections on systems that still have net-tools installed. For new scripts and current Linux systems, prefer ss for sockets and ip for routes and interface statistics.