| Layer | Typical Symptom | Check First |
|---|---|---|
| 1 — Physical | No link light, port shows down, intermittent drops on one cable run | Cable, SFP/port, power, patch panel, link light on both ends |
| 2 — Data Link | One VLAN can't reach another, MAC flapping, spanning-tree blocking a port | Switch port config, VLAN assignment, trunk allowed-list, STP state |
| 3 — Network | Can't reach anything outside the local subnet, wrong subnet, asymmetric routing | IP/mask/gateway, routing table, ping gateway then a remote host |
| 4 — Transport | Host reachable but one service isn't ("port unreachable"/timeout on that port only) | Firewall/ACL/security group, service actually listening, NAT rule |
| 5-7 — Session/Presentation/App | Connects fine but app errors, cert warning, auth failure, slow app but fast ping | DNS resolution, TLS cert validity/chain, app logs, service health, auth/token expiry |
| Task | Windows | Linux / macOS | Notes |
|---|---|---|---|
| Reachability | ping -t host | ping host | Windows pings 4x by default and stops; -t for continuous, Ctrl+C to stop |
| Path / hop-by-hop | tracert host | traceroute host / tracepath host | Each hop = one router; * often just means ICMP is deprioritized there, not that the hop is down |
| Combined ping+trace | pathping host | mtr host | Runs multiple pings per hop over time — best for spotting intermittent loss a single traceroute misses |
| DNS lookup | nslookup host Resolve-DnsName host | dig host host host | dig +trace walks the full resolution chain from root; add @8.8.8.8 to query a specific resolver directly |
| Show IP config | ipconfig /all | ip addr ifconfig (legacy) | ifconfig is deprecated on most modern distros — prefer ip |
| Show routing table | route print | ip route netstat -rn | Look for a default route (0.0.0.0/0) and confirm it points where you expect |
| Show connections/ports | netstat -ano | ss -tulpn | ss is the modern replacement for netstat on Linux; -l = listening, -p = owning process |
| ARP / neighbor table | arp -a | ip neigh arp -a | Duplicate MAC for one IP usually means an ARP conflict or spoofing — VERIFY before assuming malicious |
| Flush DNS cache | ipconfig /flushdns | resolvectl flush-caches systemd-resolve --flush-caches (older) | Exact command depends on the distro's resolver — VERIFY which is active with resolvectl status |
| Release/renew DHCP | ipconfig /release ipconfig /renew | dhclient -r dhclient | NetworkManager systems: nmcli con up <name> instead |
| Test a specific port | Test-NetConnection host -Port 443 | nc -zv host 443 | Confirms TCP-level reachability without needing the actual application protocol to succeed |
| Wireless status | netsh wlan show interfaces | iwconfig / nmcli dev wifi | Check signal (RSSI), channel, and negotiated link speed, not just "connected" |
| Symptom | Likely Cause |
|---|---|
| NXDOMAIN | Name genuinely doesn't exist, or a typo — confirm the exact FQDN and TLD |
| SERVFAIL | Authoritative server error, broken DNSSEC chain, or resolver can't reach anything upstream |
| Resolves internally but not externally (or vice versa) | Split-horizon/internal DNS zone — expected behavior, not a fault, unless both are supposed to match |
| Works by IP but not by name | DNS-layer issue specifically — narrows the problem out of routing/firewall entirely |
| Intermittent resolution failures | Resolver timeout/overload, flaky upstream forwarder, or TTL churn during a recent record change |
| Old IP still returned after a DNS change | TTL caching — check the record's TTL before assuming propagation is "stuck"; low TTLs speed up future cutovers |
| Resource | Windows | Linux | What to Look For |
|---|---|---|---|
| CPU | Task Manager → Details Get-Process | sort CPU -desc | top / htop | One runaway process vs. sustained high load across many — very different root causes |
| Memory | Task Manager → Performance Get-Counter '\Memory\Available MBytes' | free -h vmstat 1 | Available memory near zero + heavy swap/page-file use = real pressure, not just "high usage" (caching inflates the raw number) |
| Disk I/O | Resource Monitor → Disk tab | iostat -x 1 iotop | High %util or await time, not just raw throughput — a "slow disk" complaint is often queue depth, not bandwidth |
| Network throughput | Resource Monitor → Network tab | iftop / nload | Sustained near-link-speed usage, or one process/host dominating — separates "link is saturated" from "app is slow for another reason" |
| Boot-time load | Task Manager → Startup tab | systemd-analyze blame | Ranks what's actually consuming boot time — faster than guessing which service to disable |
| Code | Meaning | Where to Look |
|---|---|---|
| 400 | Bad Request — malformed syntax the server won't even parse | Client-side request body/headers, not the server |
| 401 | Unauthorized — missing or invalid credentials | Auth token/session; check for expiry |
| 403 | Forbidden — authenticated but not permitted | Permissions/ACL/role, not credentials themselves |
| 404 | Not Found — no resource at this path | URL/route correctness, not necessarily server health |
| 408 | Request Timeout — server gave up waiting on the client | Client network latency or a client that hung mid-request |
| 429 | Too Many Requests — rate limited | Confirm actual request volume before assuming the limit is misconfigured |
| 500 | Internal Server Error — unhandled exception server-side | Application/server logs, not the network path |
| 502 | Bad Gateway — reverse proxy got an invalid response from upstream | The upstream app/backend, not the proxy itself, is usually the actual fault |
| 503 | Service Unavailable — server up but not ready to serve (overload, maintenance, health check failing) | App health/readiness state, load balancer target health |
| 504 | Gateway Timeout — reverse proxy got no response from upstream in time | Upstream latency/hang, or a proxy timeout set too low for a legitimately slow backend |
| Symptom | Likely Cause |
|---|---|
| Destination host unreachable | Local machine has no route to that network — check its own routing table/gateway, not the remote host |
| Request timed out | Packet sent, no reply received — could be genuinely down, or a firewall silently dropping rather than rejecting |
| TTL expired in transit | Routing loop, or TTL too low for the actual path length |
| Connection refused | Host is reachable but nothing is listening on that port — service down, wrong port, or bound to the wrong interface (e.g. 127.0.0.1 only) |
| Connection reset | Something actively tore down the connection mid-stream — often a firewall/IPS, or the app crashing/closing the socket |
| High latency, 0% packet loss | Congestion or a longer path (routing change, VPN, satellite/wireless hop) — not a connectivity fault |
| Intermittent loss, not total | Flaky physical link, duplex mismatch, oversubscribed wireless channel, or one bad hop — use continuous ping/mtr to catch the pattern rather than a single test |
| Works locally, fails over VPN/WAN | MTU/fragmentation issue is a common culprit — test with a smaller packet size before assuming routing or firewall |
| Pitfall | Why It Costs You Time |
|---|---|
| Changing multiple variables at once | If it works afterward, you don't know which change fixed it — and can't safely revert the unnecessary ones later |
| Fixing the symptom, not the cause | Restarting a service that keeps crashing "solves" the outage but guarantees a repeat until the actual fault is found |
| Skipping reproduction | Acting on a secondhand description risks solving the wrong problem entirely |
| Assuming instead of testing | "It's probably DNS" without actually checking wastes a cycle if it's wrong — test cheap theories first |
| No rollback plan | A "quick fix" that makes things worse, with no fast way back, turns a minor incident into a major one |
| Not verifying under real conditions | "Fixed" from your own machine/account doesn't confirm it's fixed for the affected user/site/load pattern |
| Tunnel vision on the first theory | Confirmation bias toward the first plausible cause can burn time while the actual cause goes unchecked |