Linux Network Diagnosis Cheat Sheet

Walk a network fault layer by layer — reachability, routing, ports, DNS, TLS and packet capture — and prove whether latency lives in the network or the application.

Networking command reference

Work bottom-up

Test the lowest layer first. Every minute spent debugging TLS on a host with no route is wasted.

LayerQuestionCommand
LinkIs the interface up?ip link
NetworkCan packets reach it?ping, mtr
TransportIs the port open?nc -zv, ss
SessionDoes TLS negotiate?openssl s_client
ApplicationDoes the app answer?curl -v

Interfaces and addresses

ip -br addr              # brief: name, state, addresses
ip link show             # link state and MTU
ip -s link show IFACE    # counters: errors, drops, overruns
ethtool IFACE            # negotiated speed and duplex

Non-zero errors or dropped in ip -s link points at cabling, a driver, or a saturated NIC ring buffer — not at your application.

Reachability and path

ping -c 5 HOST                  # ICMP reachability and RTT
ping -c 5 -M do -s 1472 HOST    # test 1500-byte MTU without fragmentation
mtr -r -c 20 HOST               # combines traceroute + per-hop loss
traceroute -T -p 443 HOST       # TCP traceroute — ICMP is often filtered

Loss at an intermediate hop is usually not a fault. Routers deprioritise generating ICMP replies. Only loss that persists to the final hop matters.

If ping works but a large payload hangs, suspect MTU. The -M do -s test above fails with “message too long” when the path MTU is smaller than you assume — a classic cause of hangs on VPNs and overlay networks.

Ports and sockets

nc -zv HOST PORT             # is the port accepting TCP?
nc -zv -w 3 HOST PORT        # with timeout

ss -tulpn                    # listening TCP/UDP sockets with process
ss -tan state established    # established connections
ss -tan state time-wait | wc -l
ss -tn dst HOST              # connections to a specific host
ss -i                        # per-socket rtt, cwnd, retransmits

ss -i shows retransmissions per socket — the most direct evidence that packet loss, not the application, is causing slowness.

sudo lsof -i :PORT           # which process owns a local port
sudo fuser -n tcp PORT

Connection refused vs timeout

SymptomMeaning
Connection refusedReached the host; nothing is listening. RST returned
Connection timed outPackets dropped silently — firewall or security group
No route to hostLocal routing or ARP failure

Refused means you got through. Timeout means you did not.

DNS

dig HOST                       # full answer
dig +short HOST
dig @1.1.1.1 HOST              # bypass the local resolver
dig +trace HOST                # full delegation chain from the root
dig -x 10.0.0.5                # reverse lookup

resolvectl status              # systemd-resolved: what is actually configured
cat /etc/resolv.conf

Compare a direct query against the local resolver. If dig @1.1.1.1 works and dig alone does not, the fault is your resolver, not the record.

getent hosts HOST              # resolution as the C library sees it

getent honours /etc/hosts and nsswitch.conf; dig does not. When an application and dig disagree, this is usually why.

Routing

ip route                       # routing table
ip route get 8.8.8.8           # which route and source IP will be used
ip neigh                       # ARP cache
ip rule list                   # policy routing rules

ip route get answers the only routing question that matters during an incident: which interface and source address this specific destination will use.

HTTP and TLS

curl -v https://HOST
curl -sS -o /dev/null -w 'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://HOST
curl --resolve HOST:443:1.2.3.4 https://HOST   # bypass DNS, test one backend

That -w timing breakdown is the fastest way to attribute latency. Slow time_namelookup is DNS; slow time_connect is the network; slow time_starttransfer is the application.

openssl s_client -connect HOST:443 -servername HOST </dev/null
echo | openssl s_client -connect HOST:443 2>/dev/null | openssl x509 -noout -dates -subject

Always pass -servername — without SNI you may be shown a completely different certificate than a browser sees.

Firewalls

sudo iptables -L -n -v --line-numbers
sudo nft list ruleset
sudo ufw status verbose

# Are packets being dropped by conntrack?
sudo conntrack -S
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

Conntrack exhaustion presents as random, intermittent connection failures under load while everything looks healthy. Compare count against max.

Packet capture

sudo tcpdump -i any -n port 443
sudo tcpdump -i any -n host 10.0.0.5 and port 5432
sudo tcpdump -i any -n -c 100 -w capture.pcap    # write for Wireshark
sudo tcpdump -i any -n 'tcp[tcpflags] & (tcp-rst) != 0'   # RSTs only

-n disables name resolution — without it tcpdump generates its own DNS traffic and pollutes the capture. Filtering for RSTs is the quickest way to find who is actively refusing connections.

Throughput and saturation

sar -n DEV 1 5            # per-interface throughput
sar -n EDEV 1 5           # per-interface errors
iftop -i IFACE            # live per-connection bandwidth
nload IFACE

iperf3 -s                 # on the server
iperf3 -c SERVER -t 30    # on the client

Fast checks

ip -br addr                                  # interfaces at a glance
ss -s                                        # socket summary by state
ss -tan state syn-sent                       # stuck outbound handshakes
sudo tcpdump -i any -n -c 20 icmp            # is anything ICMP arriving
curl -sS -o /dev/null -w '%{http_code}\n' https://HOST