Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

Diagnose a network problem on Linux

By updated

Improve this page

When the network stops answering, the question is not "which command should I use?" but "at which layer is the problem?". This guide gives you a structured network diagnosis method: you start from the symptom, follow a logical path, and identify the root cause. The commands are organised by incident scenario, not alphabetically. This page applies to networking the general diagnosis method of the Troubleshoot module: observe before acting, and change one thing at a time.

What you will learn

  • Diagnose a network problem methodically by following the OSI layers
  • Choose the right command for the symptom observed
  • Interpret the results to identify the root cause
  • Use the modern tools (ip, ss, mtr) rather than the deprecated commands

Prerequisites

Diagnosing means comparing what you observe with what should happen. Without a mental model of how a packet travels, the commands of this guide are only a list to copy. Make sure you master these foundations:

  • OSI model: understand the 7 layers and their role
  • IP addressing: CIDR notation, masks, subnets
  • Protocols: TCP vs UDP, ICMP, DNS
  • Routing: default gateway, routing tables

If one of these notions is missing, the Networking course (in French) covers them from the start: OSI model, protocols and addressing, before moving on to troubleshooting in production.

I am in an incident: which path should I follow?

During an outage, the most expensive reflex is to run commands at random. This table points you in the right direction: identify your symptom, run the first command to qualify the problem, then follow the matching path, detailed below.

SymptomPathFirst command
Remote machine unreachableHost unreachableping -c 3 <ip>
Service/port does not answerPort does not answernc -zv <ip> <port>
Name resolution failsDNS does not workdig <domain>
Slow or unstable connectionNetwork is slowmtr <destination>
HTTP request in errorHTTP does not workcurl -I <url>

Remote host unreachable

Symptom: impossible to reach a remote machine (SSH timeout, ping with no answer, connection refused). If it is specifically your SSH access that is lost, in particular after a change to sshd_config, follow the dedicated path Recover SSH access to a server instead: the diagnosis below covers the general case of an unreachable host.

  1. Check basic connectivity

    Terminal window
    ping -c 3 192.168.1.100

    If it answers → The host is reachable, the problem is elsewhere (port, application firewall).

    If it times out → Carry on with the diagnosis (ICMP may be blocked).

  2. Check your own IP configuration

    Terminal window
    ip addr show
    # Look for: inet 192.168.x.x/24 on the active interface

    Check: does the interface have an IP? Is it in the right subnet?

  3. Check the route to the destination

    Terminal window
    ip route get 192.168.1.100
    # Expected result: via 192.168.1.1 dev eth0

    If RTNETLINK answers: Network is unreachable → No route leads to this destination: check the gateway.

  4. Check the default gateway

    Terminal window
    ip route show default
    # Expected result: default via 192.168.1.1 dev eth0

    If missing → Add it with ip route add default via <gateway>.

  5. Test the gateway itself

    Terminal window
    ping -c 3 192.168.1.1

    If it times out → Problem between you and the router (cable, switch, VLAN).

  6. Trace the full path

    Terminal window
    mtr -r -c 10 192.168.1.100

    Interpret: at which hop does packet loss begin?

Essential IP diagnosis commands

The ip command gathers everything ifconfig, route and arp used to do: interfaces, addresses, routes and ARP neighbours. These five invocations cover the essentials of a network inventory, to know by heart before going further:

Terminal window
# Show every interface and its IPs
ip addr show
# Show only the UP interfaces
ip link show up
# Show the full routing table
ip route show
# Show the ARP neighbours (MAC resolution)
ip neigh show
# Show the interface statistics
ip -s link show eth0

The port does not answer

Symptom: connection refused or timeout on a specific port (SSH, HTTP, database). The nature of the refusal is already a clue: Connection refused means the machine answers but nothing listens, a timeout points to a firewall silently dropping packets.

  1. Test connectivity to the port

    Terminal window
    nc -zv 192.168.1.100 22
    # Debian, Ubuntu (netcat-openbsd):
    # Success: Connection to 192.168.1.100 22 port [tcp/ssh] succeeded!
    # Failure: nc: connect to 192.168.1.100 port 22 (tcp) failed: Connection refused
    # RHEL, AlmaLinux (nmap-ncat):
    # Success: Ncat: Connected to 192.168.1.100:22.
    # Failure: Ncat: Connection refused.

    Connection refused → The port is not listening on the server side.

    Timeout → A firewall blocks the flow.

  2. Check that the service listens (on the server)

    Terminal window
    ss -tlnp | grep :22
    # Expected: LISTEN 0 128 0.0.0.0:22 *:* users:(("sshd",pid=1234,fd=3))

    If no line → The service is not started.

    If 127.0.0.1:22 → The service only listens on localhost.

  3. Check the distribution firewall (on the server)

    Terminal window
    # Ubuntu/Debian with UFW
    sudo ufw status verbose
    # RHEL/AlmaLinux/Rocky with firewalld
    sudo firewall-cmd --list-all

    Check: is the port or service concerned allowed?

  4. Inspect the low-level rules (if no manager is active)

    Terminal window
    sudo nft list ruleset | grep -E "22|ssh"
    # Or on systems still using iptables:
    sudo iptables -L -n -v | grep -E "22|ssh"

    Look for: a DROP or REJECT rule on the port concerned.

  5. Test from the server itself

    Terminal window
    nc -zv 127.0.0.1 22

    If OK locally but not remotely → Firewall or listening configuration.

If the nc test succeeds but the application returns no useful answer (the connection opens then stays silent, or systemctl shows active (running) while nothing works), the problem is no longer networking: the process itself is at fault. Carry on with An active service that does not answer.

Essential ss commands

ss replaces netstat to inspect sockets: listening ports, established connections, associated processes. Its filter language avoids printing everything and then sorting with grep, which matters on a server handling thousands of connections:

Terminal window
# Every listening TCP port with its process
ss -tlnp
# Every listening UDP port
ss -ulnp
# Established TCP connections
ss -tn state established
# Filter by port
ss -tn 'sport == :22'
# Filter by remote address
ss -tn 'dst 192.168.1.0/24'
# Detailed connection statistics
ss -ti

DNS does not work

Symptom: impossible to resolve a domain name (ping google.com fails, but ping 8.8.8.8 works).

  1. Test DNS resolution

    Terminal window
    dig google.com +short
    # Expected: 142.250.xxx.xxx

    If empty or SERVFAIL → DNS problem.

  2. Check the configured DNS server

    Terminal window
    cat /etc/resolv.conf
    # nameserver 192.168.1.1
    # or nameserver 127.0.0.53 (systemd-resolved)
  3. Test with a public DNS

    Terminal window
    dig @8.8.8.8 google.com +short

    If it works → Your local DNS is failing.

  4. Query your DNS server directly

    Terminal window
    dig @192.168.1.1 google.com +short

    If it times out → The DNS server is unreachable or port 53 is filtered.

    If SERVFAIL or REFUSED → The server answers but refuses or fails to resolve.

  5. Check the local DNS cache

    Terminal window
    # On systems using systemd-resolved (Ubuntu by default)
    resolvectl statistics
    resolvectl flush-caches

Essential dig commands

dig queries DNS servers and prints the raw answer: record type, TTL, server that answered. It is this level of detail that nslookup lacks and that lets you tell a stale cache from a badly configured zone:

Terminal window
# Simple query (A record)
dig google.com
# Short answer only
dig google.com +short
# MX records (mail servers)
dig google.com MX
# Reverse resolution (IP to name)
dig -x 8.8.8.8
# Trace the full DNS delegation
dig google.com +trace
# Use a specific DNS server
dig @1.1.1.1 google.com
# Show only the answer section
dig google.com +noall +answer

The network is slow

Symptom: high latency, dragging connections, intermittent timeouts. It is the most delicate diagnosis, because "slow" can come from latency, packet loss or saturated bandwidth: each cause has its tool.

  1. Measure latency and loss

    Terminal window
    mtr -r -c 20 google.com

    Interpret:

    • Loss% > 5% = congestion or link problem
    • Avg > 100ms to a local server = abnormal
    • High StDev = unstable connection
  2. Identify the bottleneck

    Look at which hop the latency suddenly rises or the losses begin.

  3. Test the bandwidth

    Terminal window
    # On the remote server
    iperf3 -s
    # On your machine
    iperf3 -c <server> -t 30
  4. Watch traffic in real time

    Terminal window
    # Global view per connection
    sudo iftop -i eth0
    # Interface statistics
    ip -s link show eth0
  5. Check the interface errors

    Terminal window
    ip -s link show eth0
    # Read the line of values under RX: then under TX:;
    # errors, dropped, missed and carrier must stay at 0

    A grep errors on this output is a false friend: it only returns the header lines (RX: bytes packets errors dropped missed mcast), never the values, which sit on the next line.

Essential mtr commands

mtr combines ping and traceroute continuously: it replays the path in a loop and accumulates statistics per hop, which makes intermittent problems visible that a single traceroute misses. The TCP mode is precious when routers filter ICMP:

Terminal window
# Report after 10 probes
mtr -r -c 10 google.com
# Continuous mode (interactive)
mtr google.com
# Show IPs without resolution
mtr -n google.com
# Use TCP instead of ICMP
mtr --tcp -P 443 google.com
# Use UDP
mtr --udp google.com

HTTP does not work

Symptom: web page unreachable, 502/503/504 error, timeout on an API. curl lets you break down the response time step by step (DNS, TCP connection, TLS negotiation, first byte) and point at the faulty link.

  1. Test HTTP connectivity

    Terminal window
    curl -I https://example.com
    # HTTP/2 200 = OK
  2. Measure the response times

    Terminal window
    curl -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nFirst byte: %{time_starttransfer}s\nTotal: %{time_total}s\n" -o /dev/null -s https://example.com

    Interpret:

    • DNS > 1s → Resolution problem
    • Connect > 1s → Network problem or saturated server
    • TLS > 2s → Slow TLS negotiation
    • First byte > 5s → Slow backend
  3. Test without TLS (if applicable)

    Terminal window
    curl -I http://example.com
  4. Check the response headers

    Terminal window
    curl -v https://example.com 2>&1 | head -50
  5. Bypass DNS

    Terminal window
    # Get the real IP of the server
    dig +short example.com
    # Force curl to use this IP without going through DNS
    curl --resolve example.com:443:<ip> https://example.com

    If it works with the direct IP → The problem comes from DNS resolution, not from the web server.

curl commands for diagnosis

curl is much more than a downloader: its -v, -w and -I options make it a complete HTTP probe, able to measure each step of the request and isolate a certificate, redirect or timeout problem:

Terminal window
# Headers only
curl -I https://example.com
# Verbose (connection details)
curl -v https://example.com
# Ignore certificate errors (testing only)
curl -k https://example.com
# Custom timeout
curl --connect-timeout 5 --max-time 10 https://example.com
# Follow redirects
curl -L https://example.com
# HTTP code only (handy in a script)
curl -s -o /dev/null -w "%{http_code}\n" https://example.com

Toolbox by intent

Once the paths are learned, what stays in memory is the intent ("I want to see my routes", "I want to test a port"), not the exact option. These three tables serve as a cheat sheet: start from what you want to do, the command follows.

"I want to see..."

These commands are read-only: they display the state of the system without changing anything, you can run them safely even in production.

IntentCommandExample
My IP and interfacesip addr showip a
My routing tableip route showip r
Listening portsss -tlnp-
Established connectionsss -tn state established-
Real-time trafficsudo iftop -i eth0-
ARP neighboursip neigh showip n
Firewall rulessudo nft list ruleset-

"I want to test..."

These commands send active traffic to a target: keep them for machines you are responsible for or authorised to test.

IntentCommandExample
Whether a machine answersping -c 3 <ip>ping -c 3 8.8.8.8
Whether a port is opennc -zv <ip> <port>nc -zv 192.168.1.1 22
The route to a destinationmtr -r <ip>mtr -r google.com
DNS resolutiondig <domain>dig google.com +short
Bandwidthiperf3 -c <server>-
An HTTP endpointcurl -I <url>curl -I https://api.example.com

"I want to identify..."

These commands cross-reference information to trace back to the source: which process holds a port, who owns an address. The last row, nmap -sV, sends active traffic to the target: the caveat of the previous table applies, your own machines or a written authorisation only.

IntentCommandExample
Which process uses a portss -tlnp | grep :<port>ss -tlnp | grep :80
The connections of an IPss -tn 'dst <ip>'ss -tn 'dst 10.0.0.1'
The owner of an IPdig -x <ip>dig -x 8.8.8.8
The name servers of a domaindig <domain> NSdig google.com NS
The version of a servicenmap -sV -p <port> <ip>nmap -sV -p 22 192.168.1.1

Quick troubleshooting

This table condenses the most frequent network outages with their probable cause and the solution to try first. It does not replace the detailed paths above, but it is often enough to unblock simple cases.

SymptomProbable causeSolution
ping OK to the IP, failure to the nameFailing DNSTest dig @8.8.8.8, check /etc/resolv.conf
Connection refused on a portService stopped or listening on 127.0.0.1ss -tlnp, restart the service, fix the listening address
Timeout on a precise port, ping OKFirewall dropping the packetsufw status (Ubuntu), firewall-cmd --list-all (RHEL), nft list ruleset
No IP on the interfaceDHCP failure or interface DOWNip link set <iface> up, then Netplan on Ubuntu or NetworkManager on RHEL
ping: connect: Network is unreachableNo route to the destination, default gateway missingip route show default, add the default route
From <your IP> ... Destination Host UnreachableA host on the local network, or the gateway, does not answer ARP: switched off, wrong VLAN, wrong addressip neigh show (FAILED entry), check the targeted machine
Intermittent high latencyCongestion or loss on a hopmtr -r -c 20 <target> to locate the faulty hop

Common network diagnosis traps

The ping does not answer = machine switched off?

No. ICMP is often filtered. A machine can be perfectly reachable on its service ports while ignoring pings. Always test with nc -zv on a specific port.

The port is open = the service works?

No. A port can be listening (LISTEN) without the service being functional. For example, a web server can listen on port 80 but return 500 errors. Always test the application protocol (curl, mysql -e "SELECT 1").

DNS resolution works = no DNS problem?

No. The DNS cache can hide a problem. Flush the cache (resolvectl flush-caches) and test again. Also check the TTL of the records.

traceroute shows * = router down?

No. The * * * mean the router does not answer ICMP TTL-exceeded packets, not that it is down. Traffic may very well go through. Only a constant packet loss from one hop onwards points to a problem.

ss shows ESTABLISHED = connection alive?

Not always. A connection can stay ESTABLISHED even if the other end is dead (half-open). TCP keepalives detect it, but with a delay. Check the traffic counters (ss -ti).

Security warnings

Network diagnosis tools are double-edged: the same commands that help you locate an outage also serve to map a network, intercept traffic or obtain a privilege escalation. Before installing them everywhere and handing out sudo rights, measure what each one really allows.

Beyond these extreme cases, installing these tools itself increases the attack surface of a server: nmap can trigger security alerts, tcpdump captures sensitive data (passwords, tokens), netcat can serve as a backdoor and iftop needs elevated privileges to capture traffic. Prefer dedicated diagnosis bastions rather than installing these tools on your production servers.

Ready-to-use recipes

When the incident repeats, you might as well script the diagnosis: these three scripts chain the checks of the previous paths and produce a complete inventory in one command, handy to archive in a post-mortem.

Full diagnosis of a host

This script combines ping, route, a test of the standard ports and traceroute: it is the "host unreachable" path, automated.

#!/bin/bash
# diagnostic-host.sh <ip>
HOST="$1"
echo "=== Diagnosis of $HOST ==="
echo -e "\n--- Ping ---"
ping -c 3 "$HOST"
echo -e "\n--- Route ---"
ip route get "$HOST"
echo -e "\n--- Standard ports ---"
for port in 22 80 443; do
nc -zv -w 2 "$HOST" "$port" 2>&1
done
echo -e "\n--- Traceroute ---"
mtr -r -c 5 "$HOST"

Full DNS diagnosis

This script queries the A, NS and MX records of a domain, then compares the answer of two public DNS servers: a divergence signals a propagation problem or a failing local resolver.

#!/bin/bash
# diagnostic-dns.sh <domain>
DOMAIN="$1"
echo "=== DNS diagnosis of $DOMAIN ==="
echo -e "\n--- A resolution ---"
dig "$DOMAIN" A +short
echo -e "\n--- Name servers ---"
dig "$DOMAIN" NS +short
echo -e "\n--- Mail servers ---"
dig "$DOMAIN" MX +short
echo -e "\n--- Test with public DNS ---"
echo "Google (8.8.8.8):"
dig @8.8.8.8 "$DOMAIN" +short
echo "Cloudflare (1.1.1.1):"
dig @1.1.1.1 "$DOMAIN" +short

Full HTTP diagnosis

This script measures the detailed timing of a request (DNS, connection, TLS, first byte) then shows the response headers: enough to locate the slowness before blaming the backend.

#!/bin/bash
# diagnostic-http.sh <url>
URL="$1"
echo "=== HTTP diagnosis of $URL ==="
echo -e "\n--- Timing ---"
curl -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nFirst byte: %{time_starttransfer}s\nTotal: %{time_total}s\nHTTP code: %{http_code}\n" -o /dev/null -s "$URL"
echo -e "\n--- Headers ---"
curl -I -s "$URL" | head -20

Put it into practice

A diagnosis method is only acquired in front of a real outage. The lab puts you in front of a machine whose network connection is down: it is up to you to walk up the layers with ip, ss and ping, locate the root cause and restore the traffic.

Key points

  1. Diagnose by OSI layer: physical → data link → network → transport → application
  2. Use the modern commands: ip replaces ifconfig/route, ss replaces netstat
  3. A ping timeout proves nothing: ICMP is often filtered, test the real port
  4. An open port ≠ a working service: always test the application protocol
  5. mtr > traceroute: continuous view, statistics, detection of intermittent problems
  6. dig > nslookup: parsable output, advanced options, full trace
  7. Security: tcpdump and nmap widen the attack surface of a production server, prefer dedicated bastions; nmap outside your own networks requires a written authorisation
  8. Document the results: keep a record of the commands and outputs for post-mortems

Knowledge check

Check that the essentials of this guide stuck. The questions cover only what has just been explained here.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn