How to Use netstat in Linux

Tutorial Dec 19, 2020

The netstat command is an old but powerful tool that provides us with various network related information such as, the ports that are in use, the processes using them, interface statistics and more.

It should be noted that netstat is outdated and tools like ip and ss have replaced it. If you read the man page of netstat, you'll see these lines in there,

NOTES
       This program is mostly obsolete.  Replacement for netstat is  ss.   Re‐
       placement for netstat -r is ip route.  Replacement for netstat -i is ip
       -s link.  Replacement for netstat -g is ip maddr.

This is why linux distributions like Ubuntu do not come with netstat out of the box now. You will need to install the net-tools package.

sudo apt install net-tools

This guide is for the curious ones among us, who want to explore the old ways, the netstat ways. The alternative ip and ss commands will be provided too. You can try out both the netstat and the non-netstat way, to feel and experience the performance and feature differences between them.

1. LIST ALL SOCKETS

Use the -a (all) switch to see all the sockets. This command will output a rather long list, so it is better to pipe it into a utility like more, less or most.

netstat -a | less
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:http            0.0.0.0:*               LISTEN
tcp        0      0 localhost:domain        0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:9654            0.0.0.0:*               LISTEN
tcp        0      0 localhost:microsoft-ds  0.0.0.0:*               LISTEN
tcp        0      0 focal64:microsoft-ds    0.0.0.0:*               LISTEN
tcp        0      0 localhost:2368          0.0.0.0:*               LISTEN
tcp        0      0 localhost:33060         0.0.0.0:*               LISTEN
tcp        0      0 localhost:mysql         0.0.0.0:*               LISTEN
tcp        0      0 localhost:mysql         localhost:51298         ESTABLISHED
tcp        0      0 focal64:http            192.168.101.1:64362     TIME_WAIT
tcp        0      0 localhost:mysql         localhost:51296         ESTABLISHED
tcp        0      0 localhost:51296         localhost:mysql         ESTABLISHED
tcp        0      0 localhost:51298         localhost:mysql         ESTABLISHED
tcp        0     68 focal64:ssh             192.168.101.1:64228     ESTABLISHED
tcp6       0      0 [::]:http               [::]:*                  LISTEN
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN
tcp6       0      0 ip6-localh:microsoft-ds [::]:*                  LISTEN
udp        0      0 localhost:domain        0.0.0.0:*
udp        0      0 focal64:bootpc          0.0.0.0:*
raw6       0      0 [::]:ipv6-icmp          [::]:*                  7
:

The non-netstat way to do this is,

ss -a

2. LIST SOCKETS BY TYPE

We saw that the -a or --all switch spat out a lot of information. To narrow down our search to list out only TCP sockets we can use the -t switch.

netstat -a -t | less
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:http            0.0.0.0:*               LISTEN
tcp        0      0 localhost:domain        0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:9654            0.0.0.0:*               LISTEN
tcp        0      0 localhost:microsoft-ds  0.0.0.0:*               LISTEN
tcp        0      0 focal64:microsoft-ds    0.0.0.0:*               LISTEN
tcp        0      0 localhost:2368          0.0.0.0:*               LISTEN
tcp        0      0 localhost:33060         0.0.0.0:*               LISTEN
tcp        0      0 localhost:mysql         0.0.0.0:*               LISTEN
tcp        0      0 localhost:mysql         localhost:51298         ESTABLISHED
tcp        0      0 localhost:mysql         localhost:51296         ESTABLISHED
tcp        0      0 localhost:51296         localhost:mysql         ESTABLISHED
tcp        0      0 localhost:51298         localhost:mysql         ESTABLISHED
tcp        0     36 focal64:ssh             192.168.101.1:64228     ESTABLISHED
tcp6       0      0 [::]:http               [::]:*                  LISTEN
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN
tcp6       0      0 ip6-localh:microsoft-ds [::]:*                  LISTEN
(END)

And to filter out just the UDP connections, we can use the -u switch.

netstat -a -u | less
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
udp        0      0 localhost:domain        0.0.0.0:*
udp        0      0 focal64:bootpc          0.0.0.0:*
(END)

other than the -t (TCP) and -u (UDP) switches you can use the -x switch to filter out the UNIX sockets.

The non-netstat way to do this is,

ss -a -t

Just like netstat , the above command filters and lists out the TCP sockets. Replacing the -t (TCP) switch with -u(UDP) or -x (UNIX) will result in the same behaviour as seen on netstat.

3. LIST SOCKETS THAT ARE LISTENING

The -a or --all switch lists out sockets of all states. Some of the TCP socket states are LISTEN, ESTABLISHED, CLOSING and CLOSED. And the 5 UNIX socket states are FREE, LISTENING, CONNECTING, CONNECTED and DISCONNECTING.

Here, we are trying to filter out all the sockets that are in the listening state. For that, we use the -l (listening) switch.

netstat -l | less
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:http            0.0.0.0:*               LISTEN
tcp        0      0 localhost:domain        0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:9654            0.0.0.0:*               LISTEN
tcp        0      0 localhost:microsoft-ds  0.0.0.0:*               LISTEN
tcp        0      0 focal64:microsoft-ds    0.0.0.0:*               LISTEN
tcp        0      0 localhost:2368          0.0.0.0:*               LISTEN
tcp        0      0 localhost:33060         0.0.0.0:*               LISTEN
tcp        0      0 localhost:mysql         0.0.0.0:*               LISTEN
tcp6       0      0 [::]:http               [::]:*                  LISTEN
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN
tcp6       0      0 ip6-localh:microsoft-ds [::]:*                  LISTEN
udp        0      0 localhost:domain        0.0.0.0:*
udp        0      0 focal64:bootpc          0.0.0.0:*
raw6       0      0 [::]:ipv6-icmp          [::]:*                  7
raw6       0      0 [::]:ipv6-icmp          [::]:*                  7
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     STREAM     LISTENING     18703    /run/uuidd/request
unix  2      [ ACC ]     STREAM     LISTENING     14047    /run/systemd/private
unix  2      [ ACC ]     SEQPACKET  LISTENING     14076    /run/udev/control
:

And like the past commands, we can use the -l (listening) switch along with the -t (TCP), -u (UDP) or -x (UNIX) switches to narrow down our search.

Listening TCP sockets,

netstat -l -t

Listening UDP sockets,

netstat -l -u

Listening UNIX sockets,

netstat -l -x

The non-netstat way should be predictable,

ss -l

Just like the netstat command, we can use the -t (TCP), -u (UDP) or -x (UNIX) switches along with the -l switch of ss.

4. SEE NETWORK STATISTICS

To see the statistics of all protocols, run the netstat command with the -s (statistcis) switch.

netstat -s

To see statistics for a particualr protocol type, like TCP (-t), UDP (-u), use the appropriate switch.

For seeing statistics of just the TCP Protocol,

netstat -s -t | less
IcmpMsg:
    InType3: 10
    InType8: 45
    OutType0: 45
    OutType3: 55
Tcp:
    2231 active connection openings
    1900 passive connection openings
    683 failed connection attempts
    99 connection resets received
    5 connections established
    51047 segments received
    52962 segments sent out
    4 segments retransmitted
    0 bad segments received
    981 resets sent
UdpLite:
TcpExt:
    1 resets received for embryonic SYN_RECV sockets
    1733 TCP sockets finished time wait in fast timer
    281 delayed acks sent
    1 delayed acks further delayed because of locked socket
    Quick ack mode was activated 1709 times
:

For seeing statistics of just the UDP Protocol,

netstat -s -u | less
IcmpMsg:
    InType3: 10
    InType8: 45
    OutType0: 45
    OutType3: 55
Udp:
    545 packets received
    55 packets to unknown port received
    0 packet receive errors
    1131 packets sent
    0 receive buffer errors
    0 send buffer errors
    IgnoredMulti: 843
UdpLite:
IpExt:
    InBcastPkts: 843
    InOctets: 55694324
    OutOctets: 56778712
    InBcastOctets: 119985
    InNoECTPkts: 56119
(END)

On netstat we can't use the -x (UNIX) switch along with -s (statistics), it will show the following warning if we try.

netstat -s -x | less
netstat: No statistics support for specified address family: unix
(END)

The non-netstat way to do this is to use the ss command with the -s switch. And optionally, we can use -t (TCP) or -u (UDP) to narrow down the search, just like on netstat. But unlike netstat, it is possible to use the -x (UNIX) switch here.

ss -s -x

5. SEE PID AND PROCESS NAME

The -p (program) switch is the one that we are going to look at now. It enables us to see the process ID and the location of the process that is using the socket.

We will be needing sudo powers to use -p. The -p switch can be used along with the other filtering switches like -a (all) and -l (listening). And also the -t (TCP), -u (UDP) or -x (UNIX) switches. One possible combination is shown below,

sudo netstat -l -t -p | less
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:http            0.0.0.0:*               LISTEN      658/nginx: master p
tcp        0      0 localhost:domain        0.0.0.0:*               LISTEN      566/systemd-resolve
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN      656/sshd: /usr/sbin
tcp        0      0 0.0.0.0:9654            0.0.0.0:*               LISTEN      658/nginx: master p
tcp        0      0 localhost:microsoft-ds  0.0.0.0:*               LISTEN      4444/smbd
tcp        0      0 focal64:microsoft-ds    0.0.0.0:*               LISTEN      4444/smbd
tcp        0      0 localhost:2368          0.0.0.0:*               LISTEN      928/node
tcp        0      0 localhost:33060         0.0.0.0:*               LISTEN      739/mysqld
tcp        0      0 localhost:mysql         0.0.0.0:*               LISTEN      739/mysqld
tcp6       0      0 [::]:http               [::]:*                  LISTEN      658/nginx: master p
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN      656/sshd: /usr/sbin
tcp6       0      0 ip6-localh:microsoft-ds [::]:*                  LISTEN      4444/smbd
(END)

The non-netstat way to do this is to use ss with the -p switch. It is very much like a drop-in replacement as in the previous cases. And like netstat we need sudo to use the -p switch.

sudo ss -l -t -p

6. SEE NUMERIC ADDRESSES

We can use the -n (numeric) switch to display the local and remote addresses as IP addresses instead of their resolved domain and hostnames.

netstat -l -t -n | less
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:9654            0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:445           0.0.0.0:*               LISTEN
tcp        0      0 10.0.2.15:445           0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:2368          0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:33060         0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN
tcp6       0      0 :::80                   :::*                    LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 ::1:445                 :::*                    LISTEN
(END)

The non-netstat way to do this is to use the -n switch with the ss command.

ss -l -t -n

7. SEE CONTINUOUS INFORMATION

netstat will display and update information continuously every few seconds if we use the -c (continuos) switch.

netstat -l -t -c

Apparently, there is nothing available inside ss or ip to do this there.

8. SEE THE ROUTING TABLE

We can use the -r (route) switch to see the kernel routing table.

netstat -r
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
default         _gateway        0.0.0.0         UG        0 0          0 enp0s3
10.0.2.0        0.0.0.0         255.255.255.0   U         0 0          0 enp0s3
_gateway        0.0.0.0         255.255.255.255 UH        0 0          0 enp0s3
192.168.101.0   0.0.0.0         255.255.255.0   U         0 0          0 enp0s8

The non-netstat way to do this is to use ip with route as an option.

ip route

9. SEE NETWORK INTERFACE TABLE

Use the -i switch to see all the network interfaces that netstat can discover.

netstat -i
Kernel Interface table
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
enp0s3    1500     4624      0      0 0          2506      0      0      0 BMRU
enp0s8    1500    22212      0      0 0         16622      0      0      0 BMRU
lo       65536    57876      0      0 0         57876      0      0      0 LRU

The non-netstat way to do this is to use ip command with the -s (statistics) switch and link as its value.

ip -s link

10. SEE THE PORTS USED BY A PROCESS

By combining things we have learned sofar with grep, we can find and see which ports are being used by a specific process.

Here, with the help of -a (all), -p (program) and -n (numeric) switches and grep, we will see which ports are being used by nginx

sudo netstat -a -p -n | grep "nginx"
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      658/nginx: master p
tcp        0      0 0.0.0.0:9654            0.0.0.0:*               LISTEN      658/nginx: master p
tcp6       0      0 :::80                   :::*                    LISTEN      658/nginx: master p
unix  3      [ ]         STREAM     CONNECTED     19433    658/nginx: master p
unix  3      [ ]         STREAM     CONNECTED     19434    658/nginx: master p
unix  3      [ ]         STREAM     CONNECTED     19431    658/nginx: master p
unix  3      [ ]         STREAM     CONNECTED     19432    658/nginx: master p

The reverse is also possible, we can check which process is using port 80 by grep-ing for ":80",

sudo netstat -a -p -n | grep ":80"
tcp        0      0 0.0.0.0:80   0.0.0.0:*  LISTEN   658/nginx: master p
tcp6       0      0 :::80        :::*       LISTEN   658/nginx: master p

The non-netstat way to do this is,

sudo -a -p -n | grep "nginx"

And,

sudo -a -p -n | grep ":80"

Tags

Lime

Simple, like quantum physics.