ss: socket statistics instead of deprecated netstat
When netstat hangs on a server with tens of thousands of connections, it’s time to switch to ss. Part of the iproute2 package, ss queries the kernel directly via netlink instead of parsing /proc/net/*. The result is instant output with minimal overhead.
Why switch from netstat
netstat from net-tools relies on a deprecated approach: it reads from /proc/net/tcp, /proc/net/unix and converts numeric IDs to symbolic names. On a server with active connections, this takes seconds and spikes CPU usage.
ss communicates with the kernel through a netlink socket. One call, structured data returned. For 10,000 connections, the difference is 0.02 seconds versus 3–5 seconds.
netstat is officially marked as deprecated in most distributions. iproute2 is the current standard for network management in Linux.
Separate installation is rarely needed: ss ships with iproute2, which is present in every Linux by default.
Basic flags: the -tulnp equivalent
No need to relearn everything — flags are similar, just with more flexible ordering:
| Flag | What it shows |
|---|---|
-t | TCP sockets |
-u | UDP sockets |
-l | Listening sockets only |
-n | Numeric addresses and ports (no DNS) |
-p | Process owner (PID, name) |
-a | All sockets (not just listening) |
-e | Extended info (uid, inode) |
-o | Timer information |
Flag order doesn’t matter — -tlnp and -ltnp are the same. -p needs root to show processes owned by other users.
Output differs structurally from netstat:
Key columns:
| Column | Meaning |
|---|---|
| Recv-Q | Bytes in receive buffer, not yet read by application |
| Send-Q | Bytes in send buffer, not acknowledged by peer |
| Local Address:Port | Local end of the connection |
| Peer Address:Port | Remote end |
Non-zero Recv-Q or Send-Q on an established connection signals a problem. The application isn’t keeping up with reads, or the network is congested.
Full set of basic filters:
Filtering by state and port
This is where ss beats netstat. Filters are native, not piped through grep:
State combinations:
Port filter — one of the most common:
The sport and dport filters work with numeric values. For ranges, use >= and <=: 'dport >= 3000 and dport <= 4000'.
Address filter:
Extended output: -e, -i, -s
For queue diagnostics and statistics:
Output with -e for an established connection:
Interface information (-i):
Key metrics:
| Metric | Description |
|---|---|
| cwnd | Congestion window |
| rtt | Round-trip time |
| pmtu | Path MTU |
| rcv_space | Receive buffer size |
| send | Current send rate |
State statistics (-s):
The timewait 2 in ss -s output is a quick way to assess connection buildup. If the number grows each time you run it — something isn’t closing connections properly.
Common use cases
Which process is listening on a port and which interface:
Listening twice — once on all interfaces, once on localhost. If you need external only — check bind-address in the config.
How many sockets in TIME_WAIT — and who they belong to:
High TIME_WAIT is usually normal. If it causes issues — on the client side use setsockopt with SO_LINGER, or SO_REUSEADDR on the server. Flag -ttu shows timers.
Whether a connection is stalled:
Check rtt and unacked. If unacked grows but rtt stays the same — packets aren’t arriving but aren’t being lost either. Most likely the remote side stopped reading from the socket.
Find the process that opened a connection to a specific host:
Aggregated statistics by process:
Shows how many connections each process holds. Useful for finding processes opening too many sockets.
Quick reference for everyday tasks: