TCP socket states in ss and netstat: ESTAB, TIME-WAIT, CLOSE-WAIT, SYN-SENT and more
- tool
- ss / netstat
- versions
- RFC 9293, iproute2 5.x / 6.x
- os
- linux
The State column of ss (and netstat) shows where each TCP connection is in the TCP state machine defined in RFC 9293. Most sockets on a busy server are ESTAB (open connections), LISTEN (waiting for connections) and TIME-WAIT (recently closed by this side, normal). Large numbers of CLOSE-WAIT usually mean an application bug: the peer closed the connection and the program never closed its socket. Many SYN-SENT mean outgoing connections that get no answer.
States
| ss | netstat | Meaning | When many are a problem |
|---|---|---|---|
| LISTEN | LISTEN | Waiting for incoming connections on a port | Never; one per listening socket |
| SYN-SENT | SYN_SENT | This side sent a SYN, waiting for SYN-ACK | Remote host unreachable or a firewall drops packets |
| SYN-RECV | SYN_RECV | SYN received and SYN-ACK sent, waiting for the final ACK | SYN flood, or clients that cannot complete the handshake |
| ESTAB | ESTABLISHED | Open connection, data can flow | Only if above your capacity planning |
| FIN-WAIT-1 | FIN_WAIT1 | This side closed and sent FIN, waiting for ACK | Peer not responding |
| FIN-WAIT-2 | FIN_WAIT2 | Our FIN was acknowledged, waiting for the peer's FIN | Peer application keeps its side open |
| TIME-WAIT | TIME_WAIT | Closed by this side; kept for 2xMSL (60 s on Linux) to absorb late packets | Port exhaustion on clients opening many short connections |
| CLOSE-WAIT | CLOSE_WAIT | The peer closed; waiting for the local application to call close() | Application leaks sockets (missing close, stuck threads) |
| LAST-ACK | LAST_ACK | Local side closed after the peer; waiting for the final ACK | Peer gone |
| CLOSING | CLOSING | Both sides closed at the same time | Rare |
| UNCONN | (blank for UDP) | ss only: an unconnected socket, typically UDP | Never; normal for UDP services |
Filter by state
ss -tan state time-wait | wc -l # count TIME-WAIT (includes a header line)
ss -tanp state close-wait # CLOSE-WAIT with the owning process (root for all users)
ss -tan state syn-sent # outgoing connections that get no answer
ss -tan state established '( dport = :5432 )' # open connections to PostgreSQLss also accepts the group names connected (all except listening and closed), synchronized, bucket (syn-recv and time-wait) and big.
TIME-WAIT is normal
TIME-WAIT belongs to the side that closes first and lasts 60 seconds on Linux. Thousands of them on a web server are normal. On a client that opens many short outgoing connections to one destination, they can use up local ports (connect: Cannot assign requested address); fix that with connection reuse (HTTP keep-alive, connection pools) before touching kernel settings such as net.ipv4.tcp_tw_reuse.