Networking basics
ip, ss, ports, and sockets.
A server spends its whole life talking to other machines over the network. That makes it a little like an apartment building on a busy street. The street outside is the network. The building has one address, a row of numbered doors, and behind some of those doors somebody is waiting to answer. Whether you are keeping the place running or keeping intruders out, you need to know three things: the building's address, which doors are open, and who is standing behind each one.
Two small commands answer nearly every question you will have about a Linux machine's network. Both come from a package called iproute2 (Internet Protocol routing utilities, version two), the standard toolkit on any modern system. ip reports the machine's addresses and how its traffic leaves. ss (short for socket statistics) reports which programs are listening and who they are talking to. Older guides use ifconfig (interface configuration) and netstat (network statistics); those are the retired tools that ip and ss replaced, and on a fresh Ubuntu or Debian box netstat may not even be installed.
The machine's address, and where its traffic goes
Start with the building's own address. ip addr lists every network interface (the physical or virtual network cards the machine has) and the IP (Internet Protocol) addresses attached to each one.
There are two interfaces here. lo is the loopback interface, an internal intercom the machine uses to talk to itself and that never reaches the outside; it always carries the address 127.0.0.1. eth0 is the real network card, and it holds the address 10.0.1.10. The /24 after it is the network prefix, a shorthand for the subnet mask, and it says how big the local neighborhood is (here, addresses 10.0.1.0 through 10.0.1.255 count as next-door neighbors reachable directly). The inet6 lines are the IPv6 (Internet Protocol version 6) equivalents. scope global means the address is usable from other machines; scope host means it stays on this box.
Where does traffic go when it leaves? ip route prints the routing table, which is the building's set of rules for outgoing mail: hand local deliveries straight to the neighbor, and give everything else to the front gate.
The default line is the one that matters most. It says anything not on the local network goes to 10.0.1.1, the gateway (the router that connects this segment to everywhere else). The second line says the 10.0.1.0/24 neighborhood is reachable directly on eth0, no router needed. For you, this table decides whether a failed connection is a local problem or something upstream. For an attacker who has landed on the box, it is a free map of the network's shape.
Ports and sockets, in plain terms
A port is a numbered door on the building. The IP address gets a packet to the right building; the port number gets it to the right door inside. There are 65,536 of them (0 through 65535). Most services answer on a well-known number by convention: web traffic over HTTP (HyperText Transfer Protocol) uses door 80, its encrypted form HTTPS uses 443, SSH (Secure Shell, for remote logins) uses 22, the Postgres database uses 5432. These numbers are habits, not laws; a service can listen on any port you tell it to.
A socket is one end of a conversation. Think of a phone. A socket in the LISTEN state is a phone plugged in and waiting to ring: a program has claimed a port and is ready for callers. A socket in the ESTABLISHED state is a call already in progress. The operating system's kernel (the core part that manages hardware and connections) keeps thousands of these calls straight by tagging each one with five facts: the protocol, your address, your port, the other end's address, and the other end's port. That five-part label is why two people can load the same website at once without their traffic getting crossed.
Reading who is listening, and the 0.0.0.0 trap
This is the command you will run more than any other. ss -tlnp lists listening sockets. The flags read as a sentence: -t for TCP (Transmission Control Protocol, the reliable connection type most services use), -l for listening only, -n for numeric (show raw port numbers instead of translating them, which is faster and more honest), and -p to show the program that owns each socket.
Read the Local Address:Port column, because that is where the security is. 127.0.0.1 is the loopback address: only this machine can reach that door. 0.0.0.0 is a wildcard meaning every interface, including the public street outside. So sshd on 0.0.0.0:22 is reachable from other machines (intended, since you log in remotely), nginx on 0.0.0.0:80 is a public web server (intended), and postgres on 127.0.0.1:5432 is local-only (correct, a database should not face the world). systemd-resolve on 127.0.0.53 is the local DNS (Domain Name System) helper, and [::] is the IPv6 way of writing 0.0.0.0.
The high-value habit is this: run ss -tlnp on every server you touch, and for each 0.0.0.0 line ask one question, should the whole world be able to reach this? A database, an internal admin dashboard, a metrics endpoint, or a message queue bound to 0.0.0.0 is the most common serious exposure on Linux hosts. On a cloud server, 0.0.0.0 can mean the actual public internet, where automated scanners find an open port within minutes.
Locking a service down is usually one line in its config file. Modern Redis ships safe by default, and its config shows the pattern clearly.
# Only accept connections from this machine.bind 127.0.0.1 -::1protected-mode yesport 6379
bind lists the addresses the service will listen on. Change either entry to 0.0.0.0 and you have reopened the door to everyone. When you genuinely must expose a service, require a password and put firewall rules in front of it.
ss -tlnp as a normal user and it still lists the ports, but the Process column comes back blank for every service you do not own. Reading which program owns another user's socket needs privilege, so if those owners show up empty, you forgot sudo. Add it. Otherwise it is easy to fool yourself into thinking a port has no owner.When a connection won't cooperate
When something cannot connect, work from the street inward, the way you would trace a delivery that never arrived: does the building exist at that address, is the right door open, and does anyone actually answer. Three tools map to those three questions, and running them in order turns a vague it does not work into a specific failing step.
First, ping knocks on the building itself. It sends a small ICMP (Internet Control Message Protocol) message and waits for the echo, confirming the host is powered on and reachable.
Next, nc (netcat, a tool for opening raw network connections) checks whether one specific door is open. The -z flag means scan without sending data, and -v means say what happened.
Finally, curl (a command-line tool for making web requests) checks whether the service behind the door answers correctly, not only that the port is open.
Each result narrows the problem. If ping works but nc fails, the host is up but the port is closed or blocked by a firewall. If nc succeeds but curl hangs or errors, the door is open but the program behind it is broken. There is a security echo here: these same probes are exactly what an attacker's port scan does. A firewall configured to silently drop traffic (rather than politely refuse it) makes nc hang instead of failing fast, which is one reason careful scans are slow.
Listening is your surface, established is your activity
Listening sockets are the doors an attacker gets to try, so they are your attack surface. Established sockets are the calls in progress, so they are your activity. ss shows the second kind too, and that is how you catch a machine phoning home to somewhere it should not.
Two live connections here. One is an incoming SSH login from 203.0.113.7 (a face you should recognize, or start asking questions), and one is your own application reaching out to a Postgres database at 10.0.1.20. An established connection you cannot explain, especially an outbound one from a process that has no business talking to the internet, is one of the clearest signals of a compromised host: a reverse shell (a hidden connection that hands an attacker a command prompt on your machine) or malware beaconing back to whoever controls it. On a healthy server, you can name every line.
sudo ss -tlnp on a cloud server and see: LISTEN 0.0.0.0:6379 users:(("redis-server",pid=980)). What does this line tell you?Make ss -tlnp the first thing you run on any server someone hands you. The list it prints is the exact set of doors that anyone on the network gets to try, and everything sitting on 0.0.0.0 is your homework: prove each one is meant to be public, or move it behind loopback and a firewall.
Try this
Work through “Listening is your surface, established is your activity” yourself on a sandbox you can throw away, following the commands above in order. Then break one step deliberately and re-run, so you have seen the failure before it finds you.
Takeaway
The trap worth remembering here: every 0.0.0.0 listener is a door to the street. Check that on your own systems before you need to, because it is cheaper to find on a quiet afternoon than during an incident.