netstat was one of the first commands I used on a Linux server to monitor network connections between servers. However, on a busy server netstat can be a bit slow to capture and display all the information. There is another newer command ‘ss’ that is much faster than netstat and uses similar command line options to show network information.
ss is used to dump socket statistics and as per its man page, it can display more TCP and state information than other tools. With the help of this command you can easily debug network issues and get a good idea of how connections are being handled and what ports are being used.
In this post, I am going to review some of the most common options used with ss to monitor network connections.
#1 No options
When no option is passed, ss will display a list of all open non-listening sockets (e.g. TCP/UNIX/UDP) that have established connections.
#2 tcp only
To show tcp connections only, pass the -t option.
ss -t
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 192.168.86.28:54056 172.217.3.99:https
ESTAB 0 0 192.168.86.28:47140 192.168.86.65:8009
ESTAB 564 0 192.168.86.28:35274 172.217.10.42:https
ESTAB 564 0 192.168.86.28:50206 172.217.9.227:https
ESTAB 337 0 192.168.86.28:53556 172.217.15.67:https
ESTAB 0 0 192.168.86.28:56544 172.217.11.1:https
#3 Do not resolve service name
Passing the -n option avoids name resolution and makes the command complete faster. Notice the ports are listed as numeric instead of http or https.
ss -nt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 192.168.86.28:47140 192.168.86.65:8009
ESTAB 0 0 192.168.86.28:50232 172.217.9.227:443
ESTAB 0 0 192.168.86.28:38996 167.206.252.79:80
ESTAB 0 0 192.168.86.28:43964 172.217.6.234:443
ESTAB 0 0 192.168.86.28:33808 172.217.12.174:80
ESTAB 0 0 192.168.86.28:48976 172.217.197.188:5228
#4 Listening sockets
Passing the -l option displays only the listening sockets. This is useful for checking if your service that listens on a specific port is running.
ss -lpt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:http 0.0.0.0:*
LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:*
LISTEN 0 5 127.0.0.1:ipp 0.0.0.0:*
LISTEN 0 128 [::]:http [::]:*
LISTEN 0 128 [::]:ssh [::]:*
LISTEN 0 5 [::1]:ipp [::]:*
Another interesting variation of this is to see both listening and non listening sockets.
ss -tan
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 127.0.0.1:3306 0.0.0.0:*
LISTEN 0 128 127.0.0.1:6379 0.0.0.0:*
TIME-WAIT 0 0 127.0.0.1:44388 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44398 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44404 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44392 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44408 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44412 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44396 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44400 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44410 127.0.0.1:6379
TIME-WAIT 0 0 127.0.0.1:44390 127.0.0.1:6379
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 128 *:443 *:*
#5 Process name and process id
to show the process name and pid pass the -p option
ss -pt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 192.168.86.28:47140 192.168.86.65:8009 users:(("chrome",pid=30945,fd=231))
ESTAB 0 36 192.168.86.28:ssh 192.168.86.60:62945
ESTAB 0 0 192.168.86.28:48976 172.217.197.188:5228 users:(("chrome",pid=30945,fd=168))
ESTAB 0 0 192.168.86.28:57798 69.147.82.60:https users:(("chrome",pid=30945,fd=261))
ESTAB 0 0 192.168.86.28:35502 192.168.86.64:8009 users:(("chrome",pid=30945,fd=234))
ESTAB 0 0 192.168.86.28:47224 192.168.86.100:8009 users:(("chrome",pid=30945,fd=235))
#6 Filter by connection state
ss allows you to filter output by connection state. Below is a way to filter and display only the ESTABLISHED connections.
ss -tn state established
Recv-Q Send-Q Local Address:Port Peer Address:Port
0 0 192.168.86.28:37882 192.0.78.32:443
0 0 192.168.86.28:38460 192.168.86.100:8009
0 0 192.168.86.28:57950 192.0.76.3:443
0 0 192.168.86.28:58374 209.85.201.188:5228
0 0 192.168.86.28:56202 192.0.73.2:443
0 0 192.168.86.28:45402 104.27.188.146:443
0 36 192.168.86.28:22 192.168.86.60:64497
0 0 192.168.86.28:52018 192.168.86.64:8009
0 0 192.168.86.28:44144 192.168.86.65:8009
0 0 192.168.86.28:53284 172.217.12.208:80
0 0 192.168.86.28:47718 192.0.78.22:443
0 0 192.168.86.28:42650 172.217.9.227:443
and this one shows by time-wait
ss -tn state time-wait
Recv-Q Send-Q Local Address:Port Peer Address:Port
0 0 192.168.86.28:60180 74.121.138.88:443
0 0 192.168.86.28:38546 35.190.130.252:443
0 0 192.168.86.28:40632 98.139.225.43:443
0 0 192.168.86.28:57124 204.13.192.141:443
0 0 192.168.86.28:41178 169.60.66.35:443
0 0 192.168.86.28:47328 52.0.77.209:443
0 0 192.168.86.28:58958 31.13.71.36:443
0 0 192.168.86.28:50410 51.255.68.171:443
0 0 192.168.86.28:45482 52.94.232.32:443
Basic filter usage as shown in the help is like this
FILTER := [ state STATE-FILTER ] [ EXPRESSION ]
STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}
TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listening|closing}
connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}
synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}
bucket := {syn-recv|time-wait}
big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listening|closing}
Some valid filter examples are as shown below
ss -tn state bucket
State Recv-Q Send-Q Local Address:Port Peer Address:Port
TIME-WAIT 0 0 192.168.86.28:37812 172.217.10.99:443
TIME-WAIT 0 0 192.168.86.28:47280 66.218.84.137:443
TIME-WAIT 0 0 192.168.86.28:54062 192.168.86.65:8008
TIME-WAIT 0 0 192.168.86.28:34736 52.94.232.33:443
TIME-WAIT 0 0 192.168.86.28:47376 52.85.105.89:443
ss -tn state connected
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 36 192.168.86.28:22 192.168.86.60:64497
CLOSE-WAIT 1 0 192.168.86.28:52982 128.95.160.157:80
#7 Show connections from a specific ip address
ss allows you to filter and display connections by ip addresses. Lets say you wanted to see how many connections you had to an address, you could run a command like this
ss -tn dst 192.168.86.60
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 36 192.168.86.28:22 192.168.86.60:64497
You can also use CIDR notation like this
ss -tn dst 192.168.86.0/24
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 192.168.86.28:44646 192.168.86.65:8009
ESTAB 0 0 192.168.86.28:52532 192.168.86.64:8009
ESTAB 0 36 192.168.86.28:22 192.168.86.60:64497
ESTAB 0 0 192.168.86.28:54112 192.168.86.65:8008
ESTAB 0 0 192.168.86.28:38962 192.168.86.100:8009
ESTAB 0 0 192.168.86.28:44344 192.168.86.64:8008
#8 Show connections for a specific port
Let us say you wanted to see all outbound HTTP connections
ss -tn dport = :80
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 192.168.86.28:54728 104.20.2.47:80
ESTAB 0 0 192.168.86.28:33542 172.217.6.226:80
ESTAB 0 0 192.168.86.28:50626 184.25.147.20:80
CLOSE-WAIT 1 0 192.168.86.28:52982 128.95.160.157:80
ESTAB 0 0 192.168.86.28:59984 104.70.178.121:80
ESTAB 0 0 192.168.86.28:54724 104.20.2.47:80
ESTAB 0 0 192.168.86.28:33540 172.217.6.226:80
ESTAB 0 0 192.168.86.28:43050 54.165.199.84:80
ss also allows you to query and display by local port. Say you want to list all connections higher then port 50000. I used the -H option to suppress header and sorted the output to show the connections higher than 50000.
ss -Htn sport gt :50000 | sort
CLOSE-WAIT 1 0 192.168.86.28:52982 128.95.160.157:80
ESTAB 0 0 192.168.86.28:52846 192.168.86.64:8009
ESTAB 0 0 192.168.86.28:54428 192.168.86.65:8008
ESTAB 0 0 192.168.86.28:58156 104.27.189.146:443
ESTAB 0 0 192.168.86.28:58716 192.0.76.3:443
ESTAB 0 0 192.168.86.28:59198 209.85.201.188:5228
#9 Combine filters
You can also combine filters to perform more advanced queries. Here I combined local port and destination address
ss -Htn sport gt :40000 dst 192.168.86.0/24
ESTAB 0 0 192.168.86.28:44660 192.168.86.64:8008
ESTAB 0 0 192.168.86.28:54428 192.168.86.65:8008
ESTAB 0 0 192.168.86.28:44960 192.168.86.65:8009
ESTAB 0 0 192.168.86.28:52846 192.168.86.64:8009
#10 Monitor the output
Using the Linux watch command you can setup a monitor to see continuous output on your terminal. Below I refresh the output every four seconds and display all HTTPS connection information
watch -n 4 ss -tn dst :443
The ss command also has an option -s to print summary statistics
ss -s
Total: 1245 (kernel 0)
TCP: 21 (estab 11, closed 1, orphaned 0, synrecv 0, timewait 1/0), ports 0
Transport Total IP IPv6
* 0 - -
RAW 1 0 1
UDP 9 7 2
TCP 20 17 3
INET 30 24 6
FRAG 0 0 0
Summary
In the above examples I showed some of the most common commands that I normally use when I need to inspect network connection and states on a Linux server. The ability to add multiple filters and output the information fast makes it a very useful tool to debug and understand network connections and states.