“The site is down.” “I can’t reach the server.” “It works on my machine but not in production.” Sooner or later, every person who touches a server hears one of these — and the instinct is to start poking at random until something works. That almost never goes well. You change three things at once, one of them accidentally fixes it, and you have no idea which, so the problem comes back next week and you’re lost all over again.
There’s a better way, and it isn’t about memorizing a hundred commands. Network troubleshooting is mostly a mindset: work from the bottom up, test one thing at a time, and let each result tell you where to look next. This article walks through that mindset and the small set of universal tools that go with it, so the next time something breaks you can stay calm and actually find the cause instead of guessing.
Troubleshoot in layers, from the bottom up
The single most useful idea in all of networking is that connectivity happens in layers, stacked on top of each other. A request from your browser to a server passes down through your machine’s layers, across the wire, and up through the server’s layers. If any one layer is broken, everything above it fails too — which is exactly why guessing is so painful. You poke at the top (the application) when the real problem is three layers down.
So flip it around. Start at the bottom and work up. Each layer you confirm as healthy lets you cross off a whole category of causes:
┌─────────────────────────────────────────┐
│ 5. Application → is the service itself │ ← check LAST
│ listening & answering? │
├─────────────────────────────────────────┤
│ 4. Ports / firewall → is the door open? │
├─────────────────────────────────────────┤
│ 3. DNS → does the name resolve │
│ to the right IP? │
├─────────────────────────────────────────┤
│ 2. Routing → can packets reach the │
│ other machine at all? │
├─────────────────────────────────────────┤
│ 1. Link / local → is the interface up? │ ← check FIRST
│ do I have an IP? │
└─────────────────────────────────────────┘
You don’t always start at the literal bottom — if you can already ping the server by IP, you’ve implicitly confirmed the lower layers and can jump ahead. But when you’re truly stuck, going to the very bottom and climbing up never lies to you. It’s slow, methodical, and it always finds the answer.
Change one thing at a time
This is the rule that separates people who fix problems from people who just rattle them. Make a single change, test, observe the result, then decide your next move. If you flip the firewall, restart the service, and edit the config all at once, you’ve learned nothing even if it works. Slower is faster here.
Layer 1: Is your own machine even on the network?
Before you blame the server, rule out your own side. A surprising share of “the server is down” turns out to be a laptop on the wrong Wi-Fi or a VPN that quietly dropped.
First, check whether your network interface is up and whether you have an IP address at all:
ip addr # Linux: list interfaces and their IPs
# (older systems use: ifconfig)
You’re looking for an interface that says UP and has a real IP next to inet — something like inet 192.168.1.40. If you only see a loopback address (127.0.0.1) and nothing else, your machine isn’t connected to anything beyond itself. If you see an address starting with 169.254. on most systems, that’s a “self-assigned” address meaning the machine asked for an IP and never got one — usually a DHCP or cable/Wi-Fi problem.
If the interface is up and has an IP, the absolute simplest sanity check is to talk to your own router or gateway:
ping 192.168.1.1 # your gateway — the door out of your local network
If that fails, the problem is entirely local: a cable, Wi-Fi, or your gateway. No point looking at a remote server yet. If it succeeds, your local network is fine and you can climb to the next layer.
Layer 2: Can packets actually reach the other machine?
Now test whether your machine can reach the destination at all. The classic tool is ping, which sends a tiny packet and waits for a reply. It answers one question only: is the other end reachable, and how long does the round trip take?
ping 93.184.216.34 # ping a server by its IP address
Three things can happen, and each tells you something different:
- Replies come back — the machine is reachable and packets flow both ways. Good. The lower layers are healthy; move up.
- “Request timed out” or 100% packet loss — packets are leaving but nothing comes back. The host may be down, unreachable, or (very commonly) just configured to ignore ping. Don’t over-trust this one (see the callout).
- “Destination host unreachable” / “no route to host” — your machine doesn’t even know how to get there. That’s a routing problem, often closer to home than you think.
When ping reaches something but the path feels slow or flaky, traceroute shows you the route hop by hop — every router your packets pass through on the way to the destination:
traceroute example.com # Linux/macOS
# Windows equivalent: tracert example.com
Each line is one hop. If the trace gets partway and then every remaining hop shows * * *, that’s roughly where things break down — a router along the path is dropping your packets or not responding. You can’t always fix a hop you don’t control, but knowing where a path dies is gold when you’re talking to a host or network provider.
A failed ping doesn't always mean 'down'
Many servers and firewalls are deliberately set to ignore ICMP (the protocol ping uses) for security reasons. So a server that doesn’t answer ping can still be perfectly alive and serving traffic on port 443. Ping is a quick first signal, not a verdict. If ping fails but you suspect the host is fine, jump to testing the actual port the service runs on.
Layer 3: Does the name resolve to the right address?
Here’s a failure mode that fools beginners constantly: the server is up, the network is fine, but the name doesn’t translate to the right IP address. Every time you type a hostname like example.com, your machine first asks DNS to turn that name into an IP. If DNS gives back the wrong answer — or no answer — everything downstream fails, and it looks like the server is broken when it isn’t.
To test name resolution directly, ask DNS yourself:
nslookup example.com
# or, more detailed:
dig example.com
You want to see the hostname mapping to the IP address you expect. Two common surprises:
- No answer / “server can’t find” / NXDOMAIN — the name doesn’t resolve at all. Maybe a typo, an expired domain, a missing DNS record, or your DNS resolver itself is broken. Try resolving a known-good name like
google.com: if that also fails, your resolver is the problem, not the domain. - It resolves, but to the wrong IP — classic after you move a site to a new server. DNS still points at the old address, often because a cached record hasn’t expired yet. The fix is patience (or correcting the record), not restarting the server.
A neat trick: if name resolution is broken but you know the correct IP, ping or connect to the IP directly. If the IP works but the name doesn’t, you’ve just proven the problem is DNS, not the server. That single test saves hours. (DNS has a lot more going on under the hood — if this layer keeps biting you, the DNS deep dive is worth the time.)
Layer 4: Is the specific port open and reachable?
Reaching a machine isn’t the same as reaching the service on it. A web server listens on a specific port — usually 80 for HTTP or 443 for HTTPS — and a database, mail server, or SSH each have their own. The machine can be perfectly up while the one port you care about is closed, blocked by a firewall, or has nothing listening behind it.
To test whether you can actually open a connection to a specific port, the most universal tool is nc (netcat):
nc -zv example.com 443 # try to connect to port 443; -z = scan only, -v = verbose
A “succeeded” or “open” message means the path all the way to that port is clear and something is listening. A “connection refused” means you reached the machine but nothing is listening on that port — the service is probably stopped or bound to the wrong address. A “timeout” (it just hangs) usually points at a firewall silently dropping your packets rather than rejecting them.
That difference is genuinely useful:
refused → reached the host, but the port is closed / service down
timeout → something (usually a firewall) is eating packets silently
open → the door is open; problem is higher up (the app itself)
For web servers specifically, you can skip straight to the real protocol with curl, which actually speaks HTTP and shows you what the server replies:
curl -v https://example.com
The verbose output walks through the whole handshake: the DNS lookup, the TCP connection, the TLS negotiation, and finally the HTTP status line the server sends back. If curl gets a 200 OK, the service is working and your problem is elsewhere (the client, the browser, a proxy). If it stalls at “Trying…” you’re back to a connectivity or firewall issue. curl is often the single fastest way to test a web service end to end. (If a closed port turns out to be a firewall on purpose, the article on firewalls explains how those rules decide what gets through.)
Layer 5: Is the service itself actually listening?
If you’ve confirmed every layer below and the port still refuses connections, the problem is the service — it crashed, never started, or is listening on the wrong address. Now you check from the server’s own side (over SSH, if it’s remote). The question becomes: is anything actually listening on the port I expect?
ss -tlnp # show TCP ports the machine is LISTENING on
# (older systems: netstat -tlnp)
Each line is a socket the machine is listening on. Look for your port in the list. Two classic findings:
- The port isn’t in the list at all — the service isn’t running. Start it (or check its logs to see why it died on startup). A “connection refused” from the outside lines up exactly with this.
- It’s listening on
127.0.0.1:PORTinstead of0.0.0.0:PORT— a sneaky one. Bound to127.0.0.1(loopback), the service only answers requests from the same machine and quietly ignores everyone on the network. It “works locally” but is unreachable from outside. The fix is to bind it to0.0.0.0(all interfaces) or the right network address.
That 127.0.0.1 versus 0.0.0.0 distinction is behind a huge number of “works on my machine, not in production” mysteries. Worth burning into memory.
When in doubt, read the logs
Every serious service writes logs, and they will usually tell you what the commands above can only hint at. “Address already in use,” “permission denied,” “failed to bind” — these errors are the service explaining exactly why it won’t start. Checking logs is less a separate step than a habit that runs alongside every layer. Confirm the layer with a command, then confirm the reason in the logs.
A worked example: putting the layers together
Imagine someone at ACY Partner Indonesia reports that the company’s internal dashboard at dashboard.example.com is “down.” Instead of panicking, John Doe works the ladder:
1. ping the gateway → replies ✓ my network is fine
2. nslookup dashboard... → resolves to 10.0.5.20 ✓ DNS is fine
3. ping 10.0.5.20 → request timed out ? (could be ICMP blocked)
4. nc -zv 10.0.5.20 443 → connection refused → reached host, port closed!
5. (ssh in) ss -tlnp → nothing on :443 → the web service isn't running
→ check service logs → "failed to start: config error on line 12"
In five quick, deliberate steps he went from a vague “it’s down” to a precise cause: a typo in a config file stopped the web service from starting. No restarting random things, no guessing — each command narrowed the search until the cause had nowhere left to hide. That’s the whole game.
A small troubleshooting toolkit
You don’t need much. These commands cover the overwhelming majority of everyday network problems, and most ship with the system by default:
ip addr— do I have a working interface and an IP? (Layer 1)ping— can I reach that machine at all? (Layer 2)traceroute/tracert— where along the path do packets die? (Layer 2)nslookup/dig— does the name resolve to the right IP? (Layer 3)nc -zv host port— is that specific port reachable? (Layer 4)curl -v url— does the web service actually answer, end to end? (Layer 4)ss -tlnp/netstat— is the service listening, and on which address? (Layer 5)
Knowing when to reach for each one matters more than memorizing every flag. The layer model tells you when. (Comfortable with these but shaky on the shell itself? The command line basics will make all of this feel a lot less foreign.)
Wrapping up
The next time the network breaks, here’s the whole approach in one place:
- Troubleshoot in layers, bottom up. Confirm each layer is healthy before climbing to the next; a broken layer breaks everything above it.
- Layer 1 — local: is your own interface up and do you have an IP? Ping your gateway first.
- Layer 2 — reachability:
pingandtraceroutetell you whether (and where) packets reach the destination. - Layer 3 — DNS:
nslookup/digconfirm the name resolves to the right IP. Test the IP directly to isolate DNS. - Layer 4 — ports:
ncandcurltest whether the specific port and service are reachable. Refused vs. timeout vs. open each mean something distinct. - Layer 5 — the service:
ss/netstatshow whether anything is listening, and on which address. Watch for127.0.0.1vs0.0.0.0. - Change one thing at a time, and read the logs. They turn guessing into diagnosing.
Get comfortable with this ladder and “the server is down” stops being a moment of dread and becomes a short, almost satisfying investigation. The tools are simple; the discipline of using them in order is what makes you fast.