Linux Network Troubleshooting: Step-by-Step Diagnosis - 夜莺博客

Linux Network Troubleshooting: Step-by-Step Diagnosis

"The network is down" is one of the most common — and most misdiagnosed — Linux support calls. The disciplined approach is to work from the physical layer upward: interface state, local connectivity, gateway reachability, DNS resolution, routing, and finally application ports. This six-step methodology, based on a practical Linux troubleshooting guide, gives you the exact command sequence to isolate any network problem, plus the fixes for each layer, so you stop jumping straight to tcpdump and start finding root causes in minutes.

The individual commands in this guide are not the point — anyone can look up ip route. The point is the order. Each step is designed to eliminate every layer below it, so that when you reach the end you know exactly which one failed rather than guessing. A technician who runs ping 8.8.8.8, sees nothing, and starts capturing packets has skipped five cheaper tests; a technician who runs ip addr first often finds a downed interface in ten seconds.

The Layered Method


Layer 1  Link          ip link / ip addr            is the interface up, cabled, erroring?
Layer 2  Local stack   ping own IP, ping neighbour  is the TCP/IP stack and ARP working?
Layer 3  Gateway       ip route, ping gateway       can traffic leave the segment?
Layer 4  Name          dig, getent hosts            can names become addresses?
Layer 5  Path          traceroute, mtr              where along the route does it break?
Layer 6  Application   ss, nc, nft, tcpdump        is the service listening and permitted?

Work top-down and stop at the first layer that fails. Everything below it is already proven good, and everything above it is untestable until it is fixed.

Step 1: Check the Interface with ip addr

ip addr show       # or: ip a
sudo ip link set eth0 up        # interface DOWN — bring it up
sudo dhclient eth0              # no IP — request DHCP
ip -s link show eth0            # look for RX/TX errors

A surprising number of "network is down" cases are simply a disabled interface or a missing IP address.

Read the output carefully rather than just looking for an IP. state UP means the kernel believes the link is up; NO-CARRIER means the cable, the switch port or the SFP is the problem and no amount of software configuration will help. An interface that is UP but shows no inet line is a DHCP or static-configuration problem. The error counters from ip -s link tell you which: rising RX errors with falling RX packets usually points at a duplex mismatch or a bad cable, while TX carrier or TX errors suggests the far end is down or rejecting frames. On virtualised hosts, remember the interface may not be eth0 at all — predictable network interface names mean ens18, eno1, enp3s0 or a bond/bridge in between, and lspci | grep -i ethernet is quicker than grepping dmesg.

Also confirm you are looking at the right network namespace. On a container host or a machine running a VPN, the useful default route may live inside a namespace, and ip addr in the root namespace will look perfectly healthy while the service you cannot reach sits behind veth in another one.

Step 2: Test Local Connectivity with ping

ping -c 3 192.168.1.50     # your own IP — verifies the TCP/IP stack
ping -c 3 192.168.1.1      # another host on the same subnet
ip neigh show              # ARP table — is the gateway MAC being learned?

Pinging your own address should be an instant success; if it fails, the problem is inside the host — a broken route in the local table, a firewall rule dropping ICMP to the local address, or a service that has taken over the interface. Pinging the local address of another host on the same subnet tests the switch and the cabling without involving any router. This is also where the loopback check belongs: ping 127.0.0.1 failing means the machine itself is unwell, not the network.

If the same-subnet ping fails but the ARP entry is REACHABLE, the frame path works and something above it — a host firewall, a VLAN mismatch on one side of a trunk — is eating the traffic. If the ARP entry stays INCOMPLETE or flips between states, nothing is answering for that IP at layer 2, which is an addressing or VLAN problem rather than a routing one. Note that many hosts and most cloud providers rate-limit or block ICMP, so a failed ping is evidence, not proof; nc -zv host 22 on a known-open port is the more reliable test when a firewall is in the path.

Step 3: Check Gateway Reachability

ip route show
sudo ip route add default via 192.168.1.1 dev eth0   # no default route
ip neigh show | grep 192.168.1.1
sudo ip neigh flush all

If the gateway doesn't respond, nothing can leave your segment. Check ARP and clear stale entries before assuming the gateway is down.

Read ip route show for three things: whether a default via ... line exists at all, whether it points at the interface you expect, and whether a more specific route is shadowing it. A missing default route on a server that should have one usually means DHCP did not complete or netplan/NetworkManager wrote a configuration the kernel never applied. Multiple default routes with different metrics are normal on multi-homed hosts, but if the lower-metric one points down a dead interface, traffic will keep choosing it — check ip route get 8.8.8.8 to see precisely which source address and interface the kernel would use for a given destination, which is the single most useful command in this entire step.

A stale ARP entry is a real and recurring failure: the gateway was replaced or failed over to a VRRP/HSRP peer, the MAC changed, but the host cached the old mapping and keeps sending frames into the void. ip neigh flush all costs nothing and resolves it. If flushing temporarily fixes the problem and it returns, look for a gratuitous-ARP problem on the redundancy side — the new master is not announcing itself.

Step 4: Test DNS with dig

dig +short google.com                  # system resolver
dig +short google.com @8.8.8.8         # bypass /etc/resolv.conf
nc -zvu 8.8.8.8 53                     # is UDP 53 blocked?
resolvectl status                      # which resolvers is the host actually using?
resolvectl flush-caches

If the query works against 8.8.8.8 but not your configured resolver, the DNS server configuration is the problem — not the network.

Work through the possibilities in order. dig @8.8.8.8 succeeding while dig with no argument fails isolates the problem to your configured resolver or to /etc/resolv.conf being empty, overwritten by a VPN client, or pointing at a decommissioned internal server. Both failing while ping 8.8.8.8 works points at a firewall dropping UDP 53, which is common in environments with captive portals or egress filtering. Both failing and the ping failing takes you back to step 3. On systemd hosts, resolvectl status shows the per-link DNS servers actually in use — often different from what /etc/resolv.conf claims, because the file is a symlink into systemd-resolved — and resolvectl query name exercises the same path an application would, including search-domain expansion that plain dig skips.

Do not forget the reverse direction and the search list. A host that cannot resolve db01 but resolves db01.example.com has a search-domain problem, not a DNS server problem, and that lives in the resolver configuration rather than the network. Test with getent hosts db01, which uses the full NSS path including /etc/hosts — a static entry in /etc/hosts can make a broken DNS setup look healthy on one machine and broken on another.

Step 5: Trace the Route to the Destination

traceroute 8.8.8.8
mtr --report --report-cycles 10 8.8.8.8
sudo traceroute -T -p 443 google.com   # TCP-based trace (ICMP may be filtered)

Each hop that times out narrows the problem to a specific segment of the path.

Interpret hops with care. A run of * * * in the middle that is followed by responsive hops further along is not a break — it means those routers do not generate ICMP TTL-exceeded messages, which is a policy choice, not a fault. A break at the end of the trace is real. mtr is the better tool for anything intermittent because it sends continuous probes and reports loss per hop: look for loss that begins at a hop and continues to every hop after it, which indicates a genuine problem at that point. Loss that appears at one hop and disappears at the next is almost always control-plane rate limiting on that router's CPU and can be ignored.

When ICMP is entirely filtered along the path, which is common across carrier networks and cloud providers, the UDP and ICMP traces terminate at the first blocking hop. Switch to TCP mode against a port you know is open (-T -p 443) and the trace will usually complete, because the same filtering rules rarely apply to established-service traffic. Combined with the MTU question — a path that works for small packets and stalls for large ones — ping -M do -s 1472 destination is worth keeping next to mtr in your toolbox, since a black-holed PMTU is the classic cause of "SSH connects but then hangs".

Step 6: Check Application Ports with ss

sudo ss -tulnp | grep :80
nc -zv 192.168.1.100 80                 # from the client
sudo nft list ruleset | grep "dport 80" # firewall check
sudo tcpdump -i eth0 -nn "port 80" -c 20

If routing and DNS work but the app is unreachable, confirm the service is listening and nothing blocks the port — then capture traffic as the last resort.

The distinction between ss -tln and ss -tlnp matters when a service refuses connections in a puzzlingly selective way. A process listening on 127.0.0.1:80 is unreachable from the network no matter how correct your routing is; you need 0.0.0.0:80 or [::]:80. This single line explains a large share of "the application is running but the port is closed" reports, and it is invisible from any client-side test because the client only ever sees a refused connection. On dual-stack hosts it also explains the opposite: a service bound only to IPv6 that is unreachable over IPv4, or the reverse after an upgrade changed the default bind address.

Then work outward: nc -zv from the client tells you whether a TCP handshake completes, nft list ruleset (or iptables -S) shows whether a local rule drops the traffic, an upstream security group or ACL shows whether something else does, and tcpdump shows whether the SYN arrives and whether anything comes back. Where the capture is taken is the decisive detail — a SYN that arrives and is never answered is a host firewall problem, an unanswered SYN that never arrives is a routing or upstream filter problem, and a completed handshake followed by a RST from the application is neither.

Symptom to Layer: A Quick Map


No IP address at all                  Layer 1/2  DHCP or link
Pings work, names do not              Layer 4    DNS
Names resolve, connections hang       Layer 5    MTU, filtering, asymmetric routing
Local works, remote does not          Layer 3    Default route or gateway
Connection refused                    Layer 6    Not listening, or bound to loopback
Connection times out                  Layer 6    Firewall or upstream ACL
Works from one host, not another      Any        Client-specific config
Intermittent, affects everyone         Layer 5    Path, or a shared upstream device

Two Common Pitfalls

  • Jumping to complex tools: always start with ip addr and ip route — 10 seconds that should never be skipped.
  • Cached DNS masking intermittent failures: clear caches with resolvectl flush-caches before retesting with dig +short.

A third pitfall deserves mention because it wastes more time than either of the above: testing from the wrong place. Confirm the fault from the same host, the same network, and the same user context as the person reporting it. A problem that reproduces only from one subnet is a routing or ACL issue; one that reproduces only for one application is a bind-address or TLS issue; and one that reproduces only when someone is connected over VPN is a tunnel MTU issue. Collect the blast radius — one host, one subnet, one application, everyone — before you open a terminal, because that single answer eliminates more of the search space than any command in this guide.

For deeper packet-level debugging, pair this with our tcpdump BPF filter guide, and read the network end-to-end with mtr for packet loss and latency. When the symptom is a stalled connection rather than a dead one, MTU, MSS and PMTUD troubleshooting is the next stop. For day-to-day Linux ops see Linux server operations from selection to troubleshooting and the Chrony time sync troubleshooting article, and for DNS-specific faults see systemd-resolved and resolvectl troubleshooting.

原文链接:https://commandinline.com/linux-network-troubleshooting-guide