“The network is broken” is one of the least useful sentences in system administration, because six different things can produce it and they need six different fixes. Getting from that sentence to an actual cause takes about a minute if you know what the layers are and which order to test them in.

This is the conceptual half. Networking basics covers the commands; this page covers what they are telling you.

The four things that must all work

LayerAnswersBroken means
AddressWho am I on this network?No connectivity at all
RouteWhere do I send packets for elsewhere?LAN works, internet does not
DNSWhat address is that name?Addresses work, names do not
PortWhich program on that machine?Host reachable, service is not

Nearly every network problem is one of those four, and the symptom column tells you which. That table alone does most of the work.

Addresses and subnets

An IP address identifies an interface on a network. It always comes with a prefix — the /24 in 192.168.1.10/24 — and the prefix is what splits the address into “which network” and “which machine on it”.

The number is how many bits belong to the network. /24 means the first three of the four numbers identify the network, so 192.168.1.x is the network and x is the machine.

PrefixNetmaskUsable addresses
/24255.255.255.0254
/25255.255.255.128126
/16255.255.0.065,534
/32255.255.255.2551 — exactly this address

Why this matters practically: two machines can talk directly only if they are on the same network by this calculation. If they are not, every packet goes to the gateway instead — and a mismatched prefix is a classic cause of “I can reach some machines on this LAN and not others”.

Certain ranges are reserved for private use and never routed on the internet:

RangeWhere you see it
10.0.0.0/8Cloud VPCs, larger networks
172.16.0.0/12Docker’s default bridge
192.168.0.0/16Home routers
127.0.0.0/8Loopback — this machine only
169.254.0.0/16DHCP failed — self-assigned

A 169.254.x.x address is worth recognising instantly: it means the machine asked for an address and nothing answered. The problem is DHCP or the physical link, not anything further up.

# What am I?
ip addr show
ip -brief addr        # much easier to read

Routes and the gateway

The routing table answers one question for every outgoing packet: which interface, and to whom next?

ip route

# default via 192.168.1.1 dev eth0
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

Read that as two rules. The second says “anything in 192.168.1.0/24 is on my own network, send it straight out”. The first — the default route — says “everything else, hand to 192.168.1.1 and let it deal with it”.

Most specific match wins, and no default route means no internet while the local network keeps working perfectly. That combination is diagnostic on its own.

# Which route would this packet take?
ip route get 8.8.8.8

# Where does it break down?
traceroute 8.8.8.8
mtr 8.8.8.8          # traceroute and ping combined, live

ip route get is underused and answers a real question: on a machine with several interfaces — a VPN, Docker bridges, two NICs — it tells you which one traffic to a given destination will actually use.

NAT, and why your address is not your address

Private addresses cannot be routed on the internet, so your router rewrites them. Outgoing packets get the router’s public address; replies get translated back. That is NAT, and it is why ip addr shows 192.168.1.10 while a website sees something entirely different.

# What the internet sees
curl -s https://api.ipify.org; echo

The consequence that shapes a lot of infrastructure: NAT is one-way by default. You can reach out; nothing can reach in, because the router has no idea which internal machine an unsolicited packet was meant for. Port forwarding exists to tell it, and Tailscale exists largely to avoid needing to.

Docker does the same thing on a smaller scale — containers get private addresses on a bridge network and are NATed out through the host, which is exactly why publishing a port is a separate deliberate act, and why those published ports bypass ufw. Linux firewalls covers that trap.

Ports

An address gets you to a machine. A port gets you to a program on it. A service listens on a port; a client connects from a random high-numbered one.

PortService
22SSH
53DNS
80 / 443HTTP / HTTPS
3306 / 5432MySQL / PostgreSQL
6379Redis

The detail that matters most is which address a service binds to:

sudo ss -tulpn
Local AddressReachable from
127.0.0.1:5432This machine only
0.0.0.0:5432Every interface — only the firewall protects it
192.168.1.10:5432That one interface

Binding to localhost is a stronger control than a firewall rule, because it cannot be undone by a misconfigured rule elsewhere. Where a service supports it, bind it there and let the firewall be the backup.

One refinement to that, because there is a stronger control still. A service bound to 127.0.0.1 is still reachable by every user and every process on the machine — localhost is a network, and a port has no owner and no permissions. A Unix socket has no address at all: it lives in the filesystem with an owner, a mode and a directory you control, and the kernel will tell the server which process is on the other end. That is what your database, your container runtime, systemd and your logging daemon are all using locally. The Life of a Unix Socket follows one through all seven stages — starting with the fact that only the write bit gates a connection, so the mode that looks safest is usually the one that locks everybody out.

Two error messages worth distinguishing, because they point at different layers:

  • Connection refused — you reached the machine and nothing was listening. The network is fine; the service is down or on another port.
  • Connection timed out — nothing answered at all. A firewall dropped it, or you cannot reach the host.

DNS

DNS turns names into addresses, and it is responsible for a wildly disproportionate share of problems that feel like something else — because when it is slow, everything is slow, and when it is wrong, everything is wrong in confusing ways.

Resolution order on a Linux machine:

  1. /etc/hosts — checked first, overrides everything. This is what makes the pre-DNS testing trick in migrating a server work.
  2. The configured resolver, from /etc/resolv.conf or systemd-resolved.
  3. The wider DNS hierarchy, if the resolver has no cached answer.
# Ask your configured resolver
dig example.com
dig +short example.com

# Bypass it and ask a public one - this is the key test
dig +short example.com @1.1.1.1

# Which resolver am I even using?
resolvectl status
cat /etc/resolv.conf

# Mail, name servers, everything
dig example.com MX
dig example.com NS
dig +trace example.com

The comparison is the diagnosis. If dig @1.1.1.1 returns the right answer and your normal resolver does not, the problem is your resolver or a stale cache — not the domain, and not the far end.

Use dig rather than ping to test DNS. ping mixes name resolution and reachability into a single result, so a failure tells you nothing about which one broke.

The diagnostic order

Work outwards. Each step assumes the previous one passed, so the first failure names the layer.

# 1. Do I have an address? (169.254.x.x means DHCP failed)
ip -brief addr

# 2. Is the interface actually up?
ip link

# 3. Can I reach my own gateway?
ip route
ping -c3 $(ip route | awk '/default/ {print $3}')

# 4. Can I reach the internet by address, ignoring DNS?
ping -c3 1.1.1.1

# 5. Does DNS work?
dig +short example.com
dig +short example.com @1.1.1.1

# 6. Is the service listening, and on what?
sudo ss -tulpn | grep :443

# 7. Can I reach that port from outside?
nc -zv example.com 443
curl -I https://example.com
First step to failLook at
1 or 2Cable, driver, DHCP, virtual NIC
3Local network, subnet mask, switch
4Default route, upstream, provider
5Resolver config, /etc/hosts, DNS records
6The service — it is not running, or bound to localhost
7Firewall, host or cloud security group

Step 4 versus step 5 is the split worth internalising: if ping 1.1.1.1 works and dig example.com does not, your network is fine and DNS is broken. That single distinction resolves a large fraction of “the internet is down” reports.

Things that catch people out

SymptomUsually
Address is 169.254.x.xDHCP got no reply
Some LAN hosts reachable, others notWrong subnet mask
Ping works, browsing does notDNS
Works by IP, not by nameDNS, or a stale /etc/hosts entry
Connection refusedNothing listening — check ss -tulpn
Connection timed outFirewall dropping it silently
Works locally, not remotelyService bound to 127.0.0.1
DNS change not taking effectTTL — the old answer is still cached
Container cannot resolve namesDocker DNS, not the host’s

The TTL one catches people during migrations especially. A DNS record you changed is still cached by resolvers everywhere for as long as its TTL said, and nothing you do locally speeds that up — which is why lowering the TTL days in advance is the first step of any cutover.

Quick reference

You wantCommand
My addresses, readablyip -brief addr
My gatewayip route
Which route will be usedip route get 8.8.8.8
What is listeningsudo ss -tulpn
My public addresscurl -s https://api.ipify.org
Resolve a namedig +short example.com
Bypass my resolverdig +short example.com @1.1.1.1
Which resolver am I usingresolvectl status
Is that port open?nc -zv host 443
Where does it break?mtr host

Related reading