skip to content

Socket & interface state: ss and ip

ss and ip replaced netstat and ifconfig, and between them they answer "is the port listening, is the route right, is the link healthy?". This is the fastest triage loop in Linux networking interviews.

on this pageshow

questions

5

On a Linux host you need to confirm whether anything is listening on TCP port 8080 and, if so, which process owns it. How do you do that with `ss`, what does each letter in `ss -tulpn` select, and why does the process column sometimes come back empty?

level: juniorimportance: must knowfreq 82%

answer

  1. socket statistics, not netstat
  2. five independent switches
  3. the p column needs privilege
  4. UDP never says LISTEN

basics

~20 s

Run ss -tulpn as root: t selects TCP, u UDP, l listening sockets only, p the owning process, n numeric ports. The process column is empty for sockets owned by other users unless you are root.

solid answer

~40 s

`ss` is the iproute2 socket inspector that replaced `netstat`; it reads socket state from the kernel over netlink rather than parsing `/proc`. `ss -tulpn` reads as five independent switches: `-t` TCP, `-u` UDP, `-l` only listening sockets, `-p` show the owning process, `-n` print numeric ports and addresses instead of resolving them. The Process column prints something like `users:(("nginx",pid=1234,fd=6))`, which is the answer to "who has my port". To narrow it I'd use `ss -tlnp 'sport = :8080'`. If I run it unprivileged the sockets still appear, but the process column is blank for anything I don't own — mapping a socket to a PID means reading other processes' file descriptors, so that needs root. `-n` also matters operationally: without it a broken resolver makes the command crawl.

go deeper

for a junior

Be able to type ss -tulpn from memory and say what each letter does, then point at the Process column and name the owning process. Knowing ss replaced netstat is expected.

for a middle

Explain that ss reads socket state over netlink rather than parsing /proc, why -n avoids resolver stalls, and why the process column needs root. Show the filter form ss -tlnp 'sport = :8080'.

for a senior

Demonstrate that this is step one of a triage, not the answer: state clearly what a bound socket does and does not prove, and account for network namespaces so you do not declare a container's listener missing.

for a principal

Frame it as tooling standardisation: which socket-inspection commands belong in your runbooks and base images, whether debug tooling ships in production images at all, and how operators inspect namespaced listeners without a shell in every container.

## What `ss` is `ss` — "socket statistics" — ships in the **iproute2** package and is the default socket inspector on every current Linux distribution. It asks the kernel for socket state through the netlink `sock_diag` interface instead of parsing `/proc/net/tcp` line by line the way `netstat` did, which is why it stays fast on a host holding tens of thousands of sockets. `netstat` belongs to the older **net-tools** package, which is deprecated and frequently not installed at all on minimal images and containers, so `ss` is the command to reach for by default. ## Decoding `-tulpn` The flags are independent and can be combined in any order: - `-t` — TCP sockets. - `-u` — UDP sockets. - `-l` — listening sockets only (without it you also get established connections). - `-p` — show the process holding each socket. - `-n` — numeric: do not translate port numbers to service names or addresses to hostnames. Other switches worth knowing: `-a` (all sockets, listening and not), `-x` (Unix domain sockets), `-4` / `-6` to restrict the address family, `-s` for a one-screen summary of socket counts by protocol and state. ## Reading the output ```bash sudo ss -tulpn # Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process # tcp LISTEN 0 511 0.0.0.0:8080 0.0.0.0:* users:(("nginx",pid=1234,fd=6)) # udp UNCONN 0 0 127.0.0.53:53 0.0.0.0:* ``` The columns are the socket family (`Netid`), the state, two queue counters, the local and peer address:port pairs, and the process. Two details trip people up here: - **UDP sockets never show `LISTEN`.** UDP is connectionless, so a bound UDP socket shows as `UNCONN`. `-l` still selects it, because from `ss`'s point of view it is a socket waiting for traffic. - **`Peer Address:Port` of `0.0.0.0:*`** on a listening row simply means "no specific peer" — it is not a wildcard peer the socket is talking to. ## Why the process column can be empty Enumerating sockets is unprivileged, but mapping a socket to the process that owns it is not: it means walking `/proc/<pid>/fd` for every process and matching socket inodes. An ordinary user may only do that for their own processes, so `ss -tulpn` run without `sudo` prints the sockets with a blank Process column for anything owned by root or another user. If you see listeners but no owners, add `sudo` before concluding anything. The same question has a container twist. Inside a container `ss -p` only sees processes in that container's PID namespace, and the PID it prints is the namespaced one — the same process has a different PID on the host. And if the container was started without the capability to inspect other processes, the column stays blank there too. ## Narrowing the search `ss` has a small filter language, which beats piping through `grep` because it filters in the right place and cannot match the wrong column: ```bash ss -tlnp 'sport = :8080' # who is listening on 8080 ss -tnp 'dst 10.0.0.5' # my connections to that host ss -tn state established # only established TCP ``` Note that `sport` is the right key for a *listening* socket. Filtering listeners on `dport` returns nothing, because a listening socket has no destination port — that is a common self-inflicted "nothing is listening" conclusion. ## Traps worth naming in an interview - **Forgetting `-l`.** `ss -tunp` on a busy host prints thousands of established connections and the listener you wanted scrolls past. - **Forgetting `-n`.** Name resolution turns `:22` into `:ssh` and, more importantly, makes the command hang for seconds per lookup when DNS is the thing that is broken. - **Treating "the port is listening" as "the service is healthy".** A socket can be bound by a process that is deadlocked, out of worker threads, or refusing every request. `ss` proves the socket exists, nothing more. - **Assuming `ss` sees inside containers.** A listener inside a network namespace does not appear in the host's `ss` output; you need `nsenter` into that namespace, or run `ss` in the container. The honest summary of what this command buys you: it answers "is the port bound, and by whom" definitively and in one second, which is why it is the first command in almost every Linux network triage.

  • You run `ss -tulpn` and see nothing on port 8080, but the application logs say it started successfully. What would you check next?
    First confirm you looked in the right network namespace — a process in a container or netns has listeners invisible to the host's `ss`. Then check whether the app bound a different port than configured, or bound and then crashed (`systemctl status`, the unit's logs). Finally re-run with `sudo` and without `-l`, in case it bound but is in a non-listening state.
  • Why is `ss` faster than `netstat` on a host with a very large number of sockets?
    `netstat` reads and parses text out of `/proc/net/*`, which the kernel regenerates as it is read, so cost grows badly with socket count. `ss` uses the netlink `sock_diag` interface, a binary protocol that lets it request exactly the families and states it wants and stream them, so it stays usable where `netstat` takes minutes.
  • How would you get a one-line picture of how many sockets exist and in what states, without listing them all?
    `ss -s` prints a summary: total sockets, and per-protocol counts broken down by state. It is the fast way to spot, for example, an enormous number of sockets in a single state on a box where you suspect connection churn, before you decide which detailed query to run.

saying these in an interview costs you the question

  • Reaching for netstat and assuming it is installed
  • Claiming ss needs no privileges to show PIDs
  • Saying a listening UDP socket shows state LISTEN
  • Treating a bound port as proof the service is healthy
  • Filtering listeners with dport instead of sport

context

open as a page

A database on a Linux server is running and `ss -tlnp` shows it in LISTEN state on port 5432, yet remote clients get no connection while a client on the same host connects fine. What in the ss Local Address:Port column explains this, and how do you fix it?

level: middleimportance: must knowfreq 68%

basics

~10 s

The Local Address is almost certainly 127.0.0.1, so the socket is bound to loopback only and is unreachable from any other host. Fix it in the application's own bind configuration, not in the firewall.

open as a page

In `ss -tln` output on Linux, the Recv-Q and Send-Q columns mean something different for a row in LISTEN state than for one in ESTAB. Explain both readings, and what a persistently non-zero Recv-Q on a listening socket tells you about the service.

level: seniorimportance: should knowfreq 40%

basics

~20 s

On an ESTAB row the columns are bytes: unread received data and unacknowledged sent data. On a LISTEN row they are connection counts: Recv-Q is completed connections waiting to be accepted, Send-Q the accept-queue limit.

open as a page

You log into a modern minimal Linux host and find that `netstat`, `ifconfig` and `arp` are not installed. Which iproute2 commands replace each of them, and why did distributions move away from the net-tools versions?

level: juniorimportance: nice to knowfreq 45%

basics

~20 s

Use iproute2: ss replaces netstat, ip addr and ip link replace ifconfig, ip route replaces route, ip neigh replaces arp, and ip -s link replaces netstat -i. Distributions dropped net-tools because it was unmaintained and never covered modern kernel features.

open as a page