/commands/ss/ss-count-connections-by-state
ss: count TCP connections by state, port or remote IP
- tool
- ss / netstat
- versions
- iproute2 5.x / 6.x
- os
- linux
ss -s prints totals per protocol and TCP state in one call. To count by state yourself, list all TCP sockets without the header and count the first column: ss -Htan | awk '{print $1}' | sort | uniq -c. For one state, ss -Htan state established | wc -l. -H (--no-header) removes the header line so the counts are exact.
State names you can filter on
| Filter | Matches |
|---|---|
| established | Open connections exchanging data; the number most people mean by connections. |
| time-wait | Connections this host closed first, kept briefly so late packets are not misread. |
| close-wait | The peer closed, but the local application has not closed its socket yet. A growing count points to an application bug. |
| syn-sent / syn-recv | Handshakes in progress, outgoing and incoming. Many syn-recv can mean a SYN flood or a slow accept loop. |
| fin-wait-1 / fin-wait-2 | This side started the close and is waiting for the peer. |
| listening | Listening sockets (shown as LISTEN in the output, but the filter name is listening). |
| connected | Every state except listening and closed. |
| bucket / big | Minisockets (time-wait and syn-recv) and everything else. |
Use the full names with hyphens. The short forms printed in the State column (ESTAB, LISTEN) and the netstat spellings (TIME_WAIT) fail with ss: wrong state name; see that error. The meaning of each state is explained in TCP socket states.
Totals
ss -sThe TCP: line shows estab, closed, orphaned and timewait counts; it is cheap even with hundreds of thousands of sockets.
Count by state, port and peer
# All TCP sockets by state
ss -Htan | awk '{print $1}' | sort | uniq -c | sort -rn
# Established connections only
ss -Htan state established | wc -l
# Established connections per local port (which service is busy)
ss -Htn state established | awk '{n=split($3,a,":"); print a[n]}' | sort | uniq -c | sort -rn | head
# Top remote IPv4 addresses (who connects the most)
ss -Htn4 state established | awk '{sub(/:[0-9]+$/, "", $4); print $4}' | sort | uniq -c | sort -rn | head
# Connections to one port, for example nginx on 443
ss -Htn state established '( sport = :443 )' | wc -lWith a state filter, ss omits the State column, so the local address is column 3 and the peer address column 4; without a filter they are columns 4 and 5. IPv6 addresses contain colons, which is why the examples take the text after the last : for the port and strip only the final :port for the address. -4 limits the last example to IPv4.
Reading the numbers
A web server under normal load shows many ESTAB and TIME-WAIT lines and only a few in the other states. A steady rise in CLOSE-WAIT means the application is not closing sockets after the client leaves; restarting it hides the symptom but the leak returns. Many SYN-RECV entries from varied addresses point to a SYN flood or to a backlog that is too small for the accept rate. Compare counts over time with the watch commands below rather than reading a single snapshot.
Watch it change
watch -n 2 'ss -s | head -3'
watch -n 2 "ss -Htan state time-wait | wc -l"Equivalent with netstat
netstat -tan | awk 'NR>2 {print $6}' | sort | uniq -c does the same on systems that still have net-tools, but it is much slower with many sockets.
FAQ
Why do the ss -s totals differ from my awk count?
ss -s reads kernel counters for all sockets, including ones not shown by a filtered listing, while the awk pipeline counts only the lines that ss -tan prints. Small differences between the two are normal.
Is a large number of TIME-WAIT sockets a problem?
Usually not. TIME-WAIT is the normal end state of the side that closed the connection first and clears itself after a short time. It becomes a problem only when a client opens so many short connections that it runs out of local ports; reuse connections (keep-alive, pooling) instead of changing kernel settings first.
Does ss need root to count connections?
No. Any user can list and count sockets. Root is needed only for -p, to see which process owns sockets of other users.