opscape

Networking and remote

ss

List network sockets on Linux; above all, which ports are listening and which connections are open.

ss [OPTION...] [STATE-FILTER] [ADDRESS-FILTER]

7 of 7 examples run in Debian 13.7 on 2026-10-31 · iproute2 6.15.0-1 · manual: ss(8)

ss (socket statistics) answers "what is listening on this port?" and "who is connected to this machine?". It replaces netstat on Linux and is much faster on busy servers. The option letters combine like netstat's: -t TCP, -u UDP, -l listening sockets only, -n numeric ports and addresses, -p the owning process. ss -tlnp is the one to remember.

Without -l, ss shows established connections (and other non-listening states); -a shows both. Filters narrow it down on the kernel side: state established, sport = :443, dst 10.0.0.5.

In the sandbox, only two services listen, sshd on port 22 and the test web server on 8080, both on loopback. On a real server the same commands list every daemon.

Examples

Which TCP ports are listening

ss -tln
explain
output
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    
LISTEN    0         5                127.0.0.1:8080             0.0.0.0:*       
LISTEN    0         128              127.0.0.1:22               0.0.0.0:*       

-t TCP, -l listening, -n numbers instead of service names. 127.0.0.1:22 means sshd accepts connections on loopback only; 0.0.0.0:22 or *:22 would mean every interface. For a listening socket, Send-Q is the backlog size.

Show which process owns each socket

ss -tlnp
explain
output
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    Process                                                                         
LISTEN    0         5                127.0.0.1:8080             0.0.0.0:*        users:(("python3",pid=1,fd=3))                                                 
LISTEN    0         128              127.0.0.1:22               0.0.0.0:*        users:(("sshd",pid=8,fd=6))                                                    

-p adds the process name, PID and file descriptor. Run as root (as here) to see other users' processes; as an ordinary user the column stays empty for them.

Open connections

ssh server 'sleep 2' &
sleep 0.5
ss -tn
output
State    Recv-Q    Send-Q       Local Address:Port        Peer Address:Port     
ESTAB    0         0                127.0.0.1:40312          127.0.0.1:22       
ESTAB    0         0                127.0.0.1:22             127.0.0.1:40312    

Without -l, ss lists connections. A background ssh session is open, and since both ends are on this machine it appears twice: the client's side (a random high port to :22) and sshd's side (:22 to that port).

Filter by port

ss -tln 'sport = :8080'
explain
output
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    
LISTEN    0         5                127.0.0.1:8080             0.0.0.0:*       

sport is the source (local) port; dport is the remote port. Quote filters, since parentheses and = mean things to the shell.

Established connections to a given port

ssh server 'sleep 2' &
sleep 0.5
ss -tn state established '( dport = :22 )'
output
Recv-Q     Send-Q           Local Address:Port            Peer Address:Port     
0          0                    127.0.0.1:40314              127.0.0.1:22       

state established keeps only open connections and the expression keeps those whose remote port is 22, i.e. outgoing ssh sessions. With a state filter, the State column is left out.

Check in a script whether a port is in use

for port in 8080 9090; do
  if ss -Htln "sport = :$port" | grep -q .; then echo "$port: in use"; else echo "$port: free"; fi
done
output
8080: in use
9090: free

-H drops the header line, so any output at all means something is listening. Handy before starting a service that would fail with "address already in use".

UDP and TCP together

ss -tuln
explain
output
Netid   State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port   
tcp     LISTEN   0        5              127.0.0.1:8080          0.0.0.0:*      
tcp     LISTEN   0        128            127.0.0.1:22            0.0.0.0:*      

-u adds UDP. Nothing uses UDP in the sandbox, so the list holds only the two TCP listeners, with a Netid column naming the protocol. On a typical host you would see DNS (53) or NTP (123) here.

Common pitfalls

  • Without -n, ss shows service names (ssh, http-alt) instead of port numbers, which hides the actual port. Use -n when looking for a specific number.

  • Without root, -p cannot show processes owned by other users; the column is simply empty, which looks like "no process".

  • A service listening on 127.0.0.1 is unreachable from other machines even if the firewall allows it. Check the local address column.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • ss is Linux-only. On macOS and BSD use netstat -an (add -p tcp to filter) or lsof -iTCP -sTCP:LISTEN -n -P.

Options worth knowing

A selection, described in our own words. For the full list, see ss(8) or ss --help.

OptionWhat it does
-t, --tcpShow TCP sockets.
-u, --udpShow UDP sockets.
-x, --unixShow Unix domain sockets.
-l, --listeningShow only listening sockets.
-a, --allShow listening and non-listening sockets.
-n, --numericDo not resolve service names; show port numbers.
-r, --resolveResolve addresses to host names.
-p, --processesShow the process using each socket.
-e, --extendedShow extra details such as the owning uid and inode.
-o, --optionsShow timer information.
-i, --infoShow internal TCP information (rtt, congestion window).
-m, --memoryShow socket memory usage.
-s, --summaryPrint summary counts per protocol.
-H, --no-headerDo not print the header line.
-4, --ipv4Only IPv4 sockets.
-6, --ipv6Only IPv6 sockets.
-K, --killForcibly close the matching sockets (root).

Related