If you’re still using netstat to investigate sockets on Linux, it’s time to learn ss. netstat was deprecated back in 2012 by its developer.

ss stands for socket statistics, and can provide lots of insight into sockets on your system. In this blog, we’ll run through the most common use cases for socket investigation, and show you how to conduct them with ss, so you can get the info you need quickly.

We’ll focus mostly on IPv4 and IPv6 TCP and UDP sockets in this blog.

Examples

  • With no arguments ss will list all open sockets with an established connection. This includes, TCP, UDP, and Unix sockets:
    ss
    
  • If we want to see all sockets, including listening sockets:
    ss -a
    
  • Show only IPv4:
    ss -4
    
  • Show only IPv6:
    ss -6
    
  • Usually when I’m using ss I’m verifying that something is listening on a given port. We can filter to just listening sockets with:
    ss -l
    
  • Show which process owns the socket with -p
    ss -lp
    
  • Show only TCP sockets with -t. Here we show all listening TCP sockets and their processes:
    ss -tlp
    
  • Show only UDP connections with -u, Here we show all listening UDP sockets and their processes:
    ss -ulp
    
  • Disable the resolution of port names via /etc/services with -n:
    ss -tlpn
    
  • If you want to see hostnames instead of IPs, you can resolve them with -r. Generally you’ll use this to see connected remote hosts, so we’ll drop the -l, as we know our local hostname:
    ss -tpr
    
  • Filter by address:
    ss -t 'dst 192.168.1.34'
    
  • Filter by network:
    ss -t 'dst 192.168.1.1/24'
    
  • Filter by network and port:
    ss -t 'dst 10.0.0.27:22'
    
  • Filter by network and port:
    ss -t 'dst 10.0.0.1/24:22'
    
  • IPv6 address must be enclosed in square brackets. This is necessary to differentiate between an IPv6 address and a port. The manual says you can do it with a / somehow, but it wasn’t clear to me how this worked. Brackets work great, and it’s still easy to specify the port, and it’s used in other systems, so I recommend going with brackets and ignoring the / stuff:
ss -t6 'dst [::1]:22'
  • Filter port with operators. Supports:
    • !, not
    • &, &&, and
    • |, ||, or
    • dst
    • src
    • dport
    • sport
    • =, ==, eq
    • >=, ge, geq
    • <=, le, leq
    • !=, nq, neq
    • >, gt
    • <, lt
    • autobound

I’m wrapping my filters in single quotes to prevent my shell from interpreting the operators. This might be a reason to favor the letter-style operators. Personally, I try to just use quotes and cover myself:


# Show privileged ports

ss -t 'dport <= 1024'


# Show outgoing HTTP and HTTPS traffic

ss -t 'dport = http or dport = https'


# Show connections to localhost

ss 'dst localhost'

# Show connection from the local network

ss 'src 10.0.0.1/24'

  • Show timer information for TCP sockets:
    ss -to
    
  • Filter TCP connections by state:
    ss state close-wait
    

Once you’ve confirmed your socket is listening, or that you have an expected connection to a remote host, you might need to dig in with tcpdump to see the actual traffic crossing the line.

If you want to check out the full document referenced in the ss manpage, I’ve conveniently converted it to PDF and made it available here. It goes into more detail on the filter syntax than either this blog or the manpage.

Thanks for reading! Consider aliasing netstat to something like echo 'Use ss!' if you’re having trouble breaking the habit.